Skip to content

Commit

Permalink
Merge pull request #103 from cowlicks/selenium
Browse files Browse the repository at this point in the history
Add selenium tests
  • Loading branch information
cowlicks authored Oct 1, 2018
2 parents 535afd6 + a786f22 commit 09981f5
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 17 deletions.
File renamed without changes.
19 changes: 18 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
dist: trusty
sudo: required
language: node_js
node_js:
- "10"
install: make npm_install
script: make test
matrix:
include:
- name: "Node Unit Tests"
install: make npm_install_node
script: make test_node
- name: "Selenium Unit Tests"
addons:
chrome: stable
hosts:
- firstparty.local
- thirdparty.local
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
install: make npm_install_selenium
script: make test_selenium
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
test:
test_node:
./scripts/test.sh

npm_install:
./scripts/npm_install.sh
test_selenium:
./scripts/selenium_test.sh

npm_install_node:
./scripts/npm_install.sh src/js/.

npm_install_selenium:
./scripts/npm_install.sh selenium/.

psl:
./scripts/getpsl.py > src/js/domains/psl.js

release:
./scripts/release.sh

.PHONY: test npm_install psl release
.PHONY: test_node test_selenium npm_install_node npm_install_selenium psl release
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,4 @@ Exported stuff is assigned to properties on `exports` just like in node.

## Testing

From inside `src/js/` run `npm test`. To check coverage run `npm run cover`.
From inside `src/js/` you can run node tests with `npm test`, check coverage with `npm run cover`, and run selenium tests inside `selenium/` by running `npm test`.
5 changes: 1 addition & 4 deletions scripts/npm_install.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#!/usr/bin/env bash
source $(git rev-parse --show-toplevel)/scripts/source_me.sh

pushd ${js_dir} > /dev/null
trap "popd > /dev/null" EXIT

npm install
run_in_dir $1 "npm install"
4 changes: 4 additions & 0 deletions scripts/selenium_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
source $(git rev-parse --show-toplevel)/scripts/source_me.sh

run_in_dir $selenium_dir "npm test"
7 changes: 7 additions & 0 deletions scripts/source_me.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@
toplevel=$(git rev-parse --show-toplevel)
src_dir=${toplevel}/src
js_dir=${src_dir}/js
selenium_dir=${toplevel}/selenium

run_in_dir() {
pushd $1 > /dev/null
trap "popd > /dev/null" EXIT
$2
}
5 changes: 1 addition & 4 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#!/usr/bin/env bash
source $(git rev-parse --show-toplevel)/scripts/source_me.sh

pushd ${js_dir} > /dev/null
trap "popd > /dev/null" EXIT

npm test
run_in_dir $js_dir "npm test"
72 changes: 72 additions & 0 deletions selenium/cookies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict';

const express = require('express'),
cookieParser = require('cookie-parser'),
{firstPartyHostname, thirdPartyHostname, thirdPartyHost} = require('./utils'),
vhost = require('vhost');

let fpcookie = {name: '1pname', value: '1pvalue'},
tpcookie = {name: '3pname', value: '3pvalue'};

class Channel {
constructor() {
this.items = [];
this.waiting = [];
}
async popQueue() {
if (this.items.length > 0) {
return this.items.pop();
} else {
return new Promise((resolve) => {
this.waiting.push(resolve);
});
}
}
async next() {
return await this.popQueue();
}
push(item) {
if (this.waiting.length > 0) {
this.waiting.shift()(item);
} else {
this.items.push(item);
}
}
}

function firstPartyApp(app = express(), tpHost = thirdPartyHost) {
app.use(cookieParser());
app.requests = new Channel();

app.get('/', (req, res) => {
app.requests.push(req);
res.cookie(fpcookie.name, fpcookie.value);
return res.send(
`<script type="text/javascript" src="http://${tpHost}/tracker.js"></script>`
);
});
return app;
}

function thirdPartyApp(app = express()) {
app.use(cookieParser());
app.requests = new Channel();

app.get('/tracker.js', (req, res) => {
app.requests.push(req);
res.cookie(tpcookie.name, tpcookie.value);
return res.send('console.log("third party script")');
});
return app;
}

function cookieApp(app = express(), fpHostname = firstPartyHostname, tpHostname = thirdPartyHostname) {
let firstParty = firstPartyApp(),
thirdParty = thirdPartyApp();
app.use(vhost(fpHostname, firstParty));
app.use(vhost(tpHostname, thirdParty));
Object.assign(app, {firstParty, thirdParty});
return app;
}

Object.assign(module.exports, {cookieApp, fpcookie, tpcookie});
36 changes: 36 additions & 0 deletions selenium/integration_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const {assert} = require('chai');

const {newDriver, startApp, stopApp, firstPartyHost} = require('./utils'),
{cookieApp, fpcookie} = require("./cookies");

describe('cookie tests', function() {
beforeEach(function() {
this.app = cookieApp();
this.driver = newDriver();
startApp(this.app);
});
afterEach(function() {
stopApp(this.app);
this.driver.quit();
});

it('blocks cookies', async function() {
let {app, driver} = this;
driver.get(firstPartyHost);
let request = await app.firstParty.requests.next();
// no cookies initially
assert.deepEqual(request.cookies, {});
request = await app.thirdParty.requests.next();
assert.deepEqual(request.cookies, {});

driver.get(firstPartyHost);
request = await app.firstParty.requests.next();
// now we have first party cookies set
assert.deepEqual(request.cookies, {[fpcookie.name]: fpcookie.value});
request = await app.thirdParty.requests.next();
// but not third party cookies
assert.deepEqual(request.cookies, {});
});
});
20 changes: 20 additions & 0 deletions selenium/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "privacy-possum-selenium-tests",
"version": "1.0.0",
"description": "",
"main": "integration_tests.js",
"scripts": {
"test": "mocha ./integration_tests.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"chai": "^4.2.0",
"chromedriver": "^2.42.0",
"cookie-parser": "^1.4.3",
"express": "^4.16.3",
"mocha": "^5.2.0",
"selenium-webdriver": "^4.0.0-alpha.1",
"vhost": "^3.0.2"
}
}
51 changes: 51 additions & 0 deletions selenium/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

const sw = require('selenium-webdriver'),
{createServer} = require('http');

function startApp(app, port=PORT) {
app.server = createServer(app);
app.server.listen(port);
}

const path = '../src/.',
PORT = 8000,
host = (hostname, port) => `${hostname}:${port}`,
firstPartyHostname = 'firstparty.local',
thirdPartyHostname = 'thirdparty.local',
firstPartyHost = host(firstPartyHostname, PORT),
thirdPartyHost = host(thirdPartyHostname, PORT);

function startApp(app, port=PORT) {
app.server = createServer(app);
app.server.listen(port);
}

function stopApp(app) {
app.server.close();
}

/*
* in /etc/hosts this requires:
* 127.0.0.1 firstparty.local
* 127.0.0.1 thirdparty.local
*/

function loadDriverWithExtension(extPath) {
let chromeOptions = sw.Capabilities.chrome();
chromeOptions.set("chromeOptions", {"args": [
`--load-extension=${extPath}`,
'--no-sandbox',
]});
return new sw.Builder()
.forBrowser('chrome')
.withCapabilities(chromeOptions)
.build();
}

function newDriver() {
return loadDriverWithExtension(path);
}


Object.assign(module.exports, {newDriver, startApp, stopApp, PORT, firstPartyHostname, thirdPartyHostname, firstPartyHost, thirdPartyHost});
6 changes: 3 additions & 3 deletions src/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
"main": "utils.js",
"dependencies": {},
"devDependencies": {
"react": "file:./external/react",
"react-dom": "file:./external/react-dom",
"chai": "^4.1.2",
"coveralls": "^3.0.1",
"eslint": "^4.19.1",
"jsdom": "^11.10.0",
"mocha": "^4.1.0",
"nyc": "^11.7.3"
"nyc": "^11.7.3",
"react": "file:./external/react",
"react-dom": "file:./external/react-dom"
},
"scripts": {
"test": "mocha --recursive",
Expand Down

0 comments on commit 09981f5

Please sign in to comment.