mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-18 10:49:02 +00:00
Add Nightwatch.js E2E tests
Nightwatch uses Selenium, so we can run tests in real browsers. This makes it easier to test features that use the web cryptography API.
This commit is contained in:
parent
078d10d177
commit
7bf011d161
25
.travis.yml
Normal file
25
.travis.yml
Normal file
@ -0,0 +1,25 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 5.2.0
|
||||
sudo: required
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -y libappindicator1 fonts-liberation
|
||||
- wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
- sudo dpkg -i google-chrome*.deb
|
||||
- wget http://chromedriver.storage.googleapis.com/2.21/chromedriver_linux64.zip
|
||||
- unzip chromedriver_linux64
|
||||
- sudo mv chromedriver /usr/bin
|
||||
before_script:
|
||||
- export CHROME_BIN=/usr/bin/google-chrome
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
|
||||
- sleep 5 # give xvfb some time to start
|
||||
- gulp bundle
|
||||
- node index.js &
|
||||
- sleep 5
|
||||
script: node_modules/mocha/bin/mocha test/unit --compilers js:babel-core/register && node_modules/nightwatch/bin/nightwatch --test test/acceptance/index.js --config test/acceptance/nightwatch.json -e chrome
|
@ -25,7 +25,7 @@ gulp.task('start', function() {
|
||||
nodemon({
|
||||
script: 'index.js',
|
||||
ext: 'css js mustache',
|
||||
ignore: ['src/public/main.js'],
|
||||
ignore: ['src/public/main.js', 'test'],
|
||||
env: {
|
||||
'NODE_ENV': 'development'
|
||||
},
|
||||
@ -34,9 +34,31 @@ gulp.task('start', function() {
|
||||
});
|
||||
|
||||
gulp.task('test', function() {
|
||||
let test = spawn(
|
||||
'mocha',
|
||||
['test', '--compilers', 'js:babel-core/register'],
|
||||
let unitTest = spawn(
|
||||
'node_modules/mocha/bin/mocha',
|
||||
['test/unit', '--compilers', 'js:babel-core/register'],
|
||||
{stdio: 'inherit'}
|
||||
);
|
||||
|
||||
unitTest.on('exit', function() {
|
||||
|
||||
// Start app
|
||||
let app = spawn('node', ['index.js']);
|
||||
|
||||
app.stdout.on('data', function(data) {
|
||||
console.log(String(data));
|
||||
});
|
||||
|
||||
let acceptanceTest = spawn(
|
||||
'node_modules/nightwatch/bin/nightwatch',
|
||||
['--test', 'test/acceptance/index.js', '--config', 'test/acceptance/nightwatch.json'],
|
||||
{stdio: 'inherit'}
|
||||
);
|
||||
|
||||
acceptanceTest.on('exit', function() {
|
||||
// Kill app Node process when tests are done
|
||||
app.kill();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
10
package.json
10
package.json
@ -9,6 +9,7 @@
|
||||
"browserify": "^13.0.0",
|
||||
"compression": "^1.6.0",
|
||||
"express": "^4.13.3",
|
||||
"forever": "^0.15.1",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-uglify": "^1.5.1",
|
||||
"mustache-express": "^1.2.2",
|
||||
@ -27,10 +28,17 @@
|
||||
"gulp-nodemon": "^2.0.6",
|
||||
"jscs": "^2.10.1",
|
||||
"jshint": "^2.9.1",
|
||||
"mocha": "^2.4.5",
|
||||
"mocha-jscs": "^4.2.0",
|
||||
"mocha-jshint": "^2.3.1",
|
||||
"nightwatch": "^0.8.16",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"zombie": "^4.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "gulp start",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"author": "Daniel Seripap",
|
||||
"license": "MIT"
|
||||
|
90
test/acceptance/app.js
Normal file
90
test/acceptance/app.js
Normal file
@ -0,0 +1,90 @@
|
||||
describe('Darkwire', () => {
|
||||
|
||||
describe('starting a room', () => {
|
||||
|
||||
let browser;
|
||||
|
||||
before((client, done) => {
|
||||
browser = client
|
||||
.url('http://localhost:3000/', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after((client, done) => {
|
||||
browser.end(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach((client, done) => {
|
||||
done();
|
||||
});
|
||||
|
||||
beforeEach((client, done) => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should show welcome modal', () => {
|
||||
browser
|
||||
.waitForElementVisible('#first-modal', 5000)
|
||||
.assert.containsText('#first-modal .modal-title', 'Welcome to darkwire.io');
|
||||
});
|
||||
|
||||
it('should have correct header', () => {
|
||||
browser.expect.element('#first-modal .modal-title').text.to.equal('Welcome to darkwire.io');
|
||||
});
|
||||
|
||||
describe('opening a second window', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.url((result) => {
|
||||
let urlSplit = result.value.split('/');
|
||||
let roomId = urlSplit[urlSplit.length - 1];
|
||||
let url = 'http://localhost:3000/' + roomId;
|
||||
browser.execute(() => {
|
||||
window.open('http://localhost:3000/', '_blank');
|
||||
}, [], () => {
|
||||
browser.window_handles((result) => {
|
||||
browser.switchWindow(result.value[1], () => {
|
||||
browser.execute((id) => {
|
||||
window.open('http://localhost:3000/' + id, '_self');
|
||||
}, [roomId], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show welcome modal', () => {
|
||||
browser.assert.hidden('#first-modal');
|
||||
});
|
||||
|
||||
describe('sending messages', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.waitForElementPresent('ul.users li:nth-child(2)', 5000, () => {
|
||||
browser.setValue('input.inputMessage', ['Hello world', browser.Keys.RETURN], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', () => {
|
||||
browser.window_handles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('span.messageBody', 5000, () => {
|
||||
browser.assert.containsText('span.messageBody', 'Hello world');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
BIN
test/acceptance/bin/selenium-server-standalone-2.52.0.jar
Normal file
BIN
test/acceptance/bin/selenium-server-standalone-2.52.0.jar
Normal file
Binary file not shown.
2
test/acceptance/index.js
Normal file
2
test/acceptance/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
require('babel-register')();
|
||||
require('./app.js');
|
49
test/acceptance/nightwatch.json
Normal file
49
test/acceptance/nightwatch.json
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"src_folders" : ["test"],
|
||||
"output_folder" : "reports",
|
||||
"custom_commands_path" : "",
|
||||
"custom_assertions_path" : "",
|
||||
"page_objects_path" : "",
|
||||
"globals_path" : "",
|
||||
"test_runner" : "mocha",
|
||||
"selenium" : {
|
||||
"start_process" : true,
|
||||
"server_path" : "test/acceptance/bin/selenium-server-standalone-2.52.0.jar",
|
||||
"log_path" : false,
|
||||
"host" : "127.0.0.1",
|
||||
"port" : 4444,
|
||||
"cli_args" : {
|
||||
"webdriver.chrome.driver" : "/usr/bin/chromedriver",
|
||||
"webdriver.ie.driver" : ""
|
||||
}
|
||||
},
|
||||
|
||||
"test_settings" : {
|
||||
"default" : {
|
||||
"launch_url" : "http://localhost",
|
||||
"selenium_port" : 4444,
|
||||
"selenium_host" : "localhost",
|
||||
"silent": true,
|
||||
"screenshots" : {
|
||||
"enabled" : false,
|
||||
"path" : ""
|
||||
},
|
||||
"desiredCapabilities": {
|
||||
"browserName": "firefox",
|
||||
"javascriptEnabled": true,
|
||||
"acceptSslCerts": true
|
||||
}
|
||||
},
|
||||
|
||||
"chrome" : {
|
||||
"desiredCapabilities": {
|
||||
"browserName": "chrome",
|
||||
"javascriptEnabled": true,
|
||||
"acceptSslCerts": true,
|
||||
"chromeOptions" : {
|
||||
"args" : ["-e", "--no-sandbox"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import mochaJSCS from 'mocha-jscs';
|
||||
import mochaJSHint from 'mocha-jshint';
|
||||
|
||||
mochaJSCS();
|
||||
mochaJSHint();
|
50
test/helpers.js
Normal file
50
test/helpers.js
Normal file
@ -0,0 +1,50 @@
|
||||
var helpers = {
|
||||
polyfillCrypto: () => {
|
||||
window.crypto = {
|
||||
subtle: {
|
||||
generateKey: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({});
|
||||
});
|
||||
},
|
||||
exportKey: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve([{}]);
|
||||
});
|
||||
},
|
||||
importKey: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve([{}]);
|
||||
});
|
||||
},
|
||||
encrypt: () => {
|
||||
return {};
|
||||
},
|
||||
decrypt: (opts, key, data) => {
|
||||
if (opts.name === 'AES-CBC') {
|
||||
// This means it's decrypted a message
|
||||
return new Promise((resolve, reject) => {
|
||||
// "Hello world" as an array buffer
|
||||
resolve(new Uint8Array([72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]));
|
||||
});
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({});
|
||||
});
|
||||
}
|
||||
},
|
||||
sign: () => {
|
||||
return {};
|
||||
},
|
||||
verify: () => {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
getRandomValues: () => {
|
||||
return [1,2,3,4];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = helpers;
|
80
test/unit/app.js
Normal file
80
test/unit/app.js
Normal file
@ -0,0 +1,80 @@
|
||||
import helpers from './helpers';
|
||||
import app from '../index';
|
||||
import mochaJSCS from 'mocha-jscs';
|
||||
import mochaJSHint from 'mocha-jshint';
|
||||
|
||||
const Browser = require('zombie');
|
||||
Browser.localhost('localhost', 3000);
|
||||
|
||||
mochaJSCS();
|
||||
mochaJSHint();
|
||||
|
||||
describe('Visiting /', () => {
|
||||
|
||||
const browser = new Browser();
|
||||
|
||||
before((done) => {
|
||||
browser.on('active', () => {
|
||||
// browser.evaluate needs a string, so this regex just extracts the body of the function as a string
|
||||
browser.evaluate(helpers.polyfillCrypto.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]);
|
||||
});
|
||||
|
||||
browser.visit('/', done);
|
||||
});
|
||||
|
||||
it('should be successful', () => {
|
||||
browser.assert.success();
|
||||
});
|
||||
|
||||
it('should show welcome modal', () => {
|
||||
browser.assert.evaluate('$("#first-modal:visible").length', 1);
|
||||
browser.assert.text('#first-modal h4.modal-title', 'Welcome to darkwire.io');
|
||||
});
|
||||
|
||||
describe('closing the initial modal', () => {
|
||||
|
||||
before((done) => {
|
||||
browser.pressButton('#first-modal .modal-footer button', done);
|
||||
});
|
||||
|
||||
it('should close the modal and show the main chat page', () => {
|
||||
browser.assert.evaluate('$("#first-modal:hidden").length', 1);
|
||||
});
|
||||
|
||||
describe('opening another tab', () => {
|
||||
|
||||
before((done) => {
|
||||
let roomIdSplit = browser.url.split('/');
|
||||
let roomId = roomIdSplit[roomIdSplit.length - 1];
|
||||
browser.open();
|
||||
browser.tabs.current = 1;
|
||||
browser.visit(`/${roomId}`, done);
|
||||
});
|
||||
|
||||
it('should be successful', () => {
|
||||
browser.assert.success();
|
||||
});
|
||||
|
||||
it('should not show welcome modal', () => {
|
||||
browser.assert.evaluate('$("#first-modal.fade.in").length', 0);
|
||||
});
|
||||
|
||||
describe('sending message', () => {
|
||||
|
||||
before((done) => {
|
||||
browser.fill('.inputMessage', 'Hello world');
|
||||
browser.click('span#send-message-btn', done);
|
||||
});
|
||||
|
||||
it('should send message', () => {
|
||||
browser.tabs.current = 0;
|
||||
browser.assert.text('body', /Hello world/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user