mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-04-14 11:46:23 +00:00
First pass at Gulpifying the test suite.
This commit is contained in:
parent
c39ad2a2ae
commit
6a397a8be5
3 changed files with 130 additions and 100 deletions
125
gulpfile.babel.js
Normal file
125
gulpfile.babel.js
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import { exec } from 'child_process';
|
||||
import psTree from 'ps-tree';
|
||||
import gulp from 'gulp';
|
||||
import net from 'net';
|
||||
import Q from 'q';
|
||||
|
||||
const TEST_SERVER_PORT = 3001
|
||||
const TEST_DB = 'habitrpg_test'
|
||||
|
||||
const TEST_DB_URI = `mongodb://localhost/${TEST_DB}`
|
||||
|
||||
/*
|
||||
* This is a helper function that allows us to kill background tasks, such as
|
||||
* the Selenium webdriver. We need to recurse through any child processes they
|
||||
* have spun up, or gulp will hang after task completion.
|
||||
*/
|
||||
let kill = (proc) => {
|
||||
((pid) => {
|
||||
psTree(pid, (_, pids) => {
|
||||
if(pids.length) {
|
||||
pids.forEach(kill); return
|
||||
}
|
||||
try {
|
||||
exec(/^win/.test(process.platform)
|
||||
? `taskkill /PID ${pid} /T /F`
|
||||
: `kill -9 ${pid}`)
|
||||
}
|
||||
catch(e) { console.log(e) }
|
||||
});
|
||||
}(proc.PID || proc.pid));
|
||||
};
|
||||
|
||||
/*
|
||||
* Another helper function, returns a promise that will resolve when a response
|
||||
* is received on the specified port. Accepts a second argument indicating the
|
||||
* maximum seconds to wait before failing.
|
||||
*/
|
||||
let awaitPort = (port, max = 60) => {
|
||||
let socket, timeout, interval;
|
||||
let deferred = Q.defer();
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
clearInterval(interval);
|
||||
deferred.reject(`Timed out after ${max} seconds`);
|
||||
}, max * 1000);
|
||||
|
||||
interval = setInterval(() => {
|
||||
socket = net.connect({port: port}, () => {
|
||||
clearInterval(interval);
|
||||
clearTimeout(timeout);
|
||||
socket.destroy();
|
||||
deferred.resolve();
|
||||
}).on('error', () => { socket.destroy });
|
||||
}, 1000);
|
||||
|
||||
return deferred.promise
|
||||
};
|
||||
|
||||
/*
|
||||
* And another helper function to add "noisy" listeners (pipe child process
|
||||
* stdout and stderr to the parent.
|
||||
*/
|
||||
let listen = (child) => {
|
||||
child.stdout.on('data', (data) => { process.stdout.write(data) });
|
||||
child.stderr.on('data', (data) => { process.stderr.write(data) });
|
||||
};
|
||||
|
||||
gulp.task('test:common', (cb) => {
|
||||
listen(exec('NODE_ENV=testing ./node_modules/.bin/mocha test/common', cb));
|
||||
});
|
||||
|
||||
gulp.task('test:api', (cb) => {
|
||||
listen(exec('NODE_ENV=testing ./node_modules/.bin/mocha test/api', cb));
|
||||
});
|
||||
|
||||
gulp.task('test:karma', (cb) => {
|
||||
listen(exec('NODE_ENV=testing ./node_modules/.bin/grunt karma:continuous', cb));
|
||||
});
|
||||
|
||||
gulp.task('test:prepare:build', (cb) => {
|
||||
exec('grunt build:test', cb);
|
||||
});
|
||||
|
||||
gulp.task('test:prepare:mongo', (cb) => {
|
||||
exec(`mongo "${TEST_DB}" --eval "db.dropDatabase()"`, cb);
|
||||
});
|
||||
|
||||
gulp.task('test:prepare', [
|
||||
'test:prepare:build',
|
||||
'test:prepare:webdriver',
|
||||
'test:prepare:mongo'
|
||||
]);
|
||||
|
||||
gulp.task('test:prepare:webdriver', (cb) => {
|
||||
exec('./node_modules/protractor/bin/webdriver-manager update', cb);
|
||||
});
|
||||
|
||||
gulp.task('test:e2e', ['test:prepare'], (cb) => {
|
||||
let support = [
|
||||
'Xvfb :99 -screen 0 1024x768x24 -extension RANDR',
|
||||
`NODE_DB_URI="${TEST_DB_URI}" PORT="${TEST_SERVER_PORT}" node ./website/src/server.js`,
|
||||
'./node_modules/protractor/bin/webdriver-manager start',
|
||||
].map(exec);
|
||||
|
||||
awaitPort(3001)
|
||||
.then(awaitPort.bind(null, 4444))
|
||||
.then(() => {
|
||||
listen(
|
||||
exec('DISPLAY=:99 NODE_ENV=testing ./node_modules/protractor/bin/protractor protractor.conf.js', () => {
|
||||
support.forEach(kill);
|
||||
cb();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gulp.task('test', [
|
||||
'test:common',
|
||||
'test:api',
|
||||
'test:karma',
|
||||
'test:e2e'
|
||||
]);
|
||||
|
||||
gulp.task('default', ['test']);
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
"dependencies": {
|
||||
"async": "~0.9.0",
|
||||
"aws-sdk": "^2.0.25",
|
||||
"babel": "^5.5.4",
|
||||
"bower": "~1.3.12",
|
||||
"browserify": "~3.30.2",
|
||||
"coffee-script": "1.6.x",
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
"grunt-karma": "~0.6.2",
|
||||
"grunt-nodemon": "~0.3.0",
|
||||
"grunt-spritesmith": "~3.5.0",
|
||||
"gulp": "^3.9.0",
|
||||
"icalendar": "git://github.com/lefnire/node-icalendar#master",
|
||||
"image-size": "~0.3.2",
|
||||
"in-app-purchase": "^0.2.0",
|
||||
|
|
@ -52,7 +54,9 @@
|
|||
"paypal-ipn": "2.1.0",
|
||||
"paypal-rest-sdk": "^1.2.1",
|
||||
"pretty-data": "git://github.com/vkiryukhin/pretty-data#master",
|
||||
"ps-tree": "^1.0.0",
|
||||
"push-notify": "^1.1.1",
|
||||
"q": "^1.4.1",
|
||||
"qs": "^2.3.2",
|
||||
"request": "~2.44.0",
|
||||
"s3-upload-stream": "^1.0.6",
|
||||
|
|
@ -74,7 +78,7 @@
|
|||
"node": "0.10.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/coffee-script/bin/coffee ./test/runTests.coffee -n",
|
||||
"test": "./node_modules/.bin/gulp",
|
||||
"start": "grunt run:dev",
|
||||
"postinstall": "./node_modules/bower/bin/bower --config.interactive=false install -f; ./node_modules/.bin/grunt;",
|
||||
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html"
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
sh = require('shelljs')
|
||||
async = require('async')
|
||||
TEST_DB = 'habitrpg_test'
|
||||
TEST_DB_URI = "mongodb://localhost/#{TEST_DB}"
|
||||
TEST_SERVER_PORT = 3001
|
||||
MAX_WAIT = 60
|
||||
|
||||
announce = (msg) ->
|
||||
sh.echo '\x1b[36m%s\x1b[0m', "TEST SUITE: #{msg}"
|
||||
|
||||
Suite =
|
||||
# Primary Task
|
||||
run: ->
|
||||
announce "Preparing the test environment."
|
||||
Suite.prepareEnvironment ->
|
||||
announce "Test prep complete. Waiting for server availability."
|
||||
Suite.awaitServers ->
|
||||
announce "Servers are ready. Beginning tests."
|
||||
Suite.summarize
|
||||
"API Specs": Suite.runApiSpecs()
|
||||
"Common Specs": Suite.runCommonSpecs()
|
||||
"End-to-End Specs": Suite.runE2ESpecs()
|
||||
"Karma Specs": Suite.runKarmaSpecs()
|
||||
|
||||
# Output summary report when tests are done.
|
||||
summarize: (results) ->
|
||||
anyFailed = 0
|
||||
sh.echo ""
|
||||
announce "Tests complete!\n\nSummary\n-------\n"
|
||||
for name, result of results
|
||||
if result is 0
|
||||
sh.echo '\x1b[36m%s\x1b[0m', "#{name}: \x1b[32mpassing"
|
||||
else
|
||||
anyFailed = 1
|
||||
sh.echo '\x1b[36m%s\x1b[0m', "#{name}: \x1b[31mfailing"
|
||||
sh.echo ""
|
||||
announce "Thanks for helping keep Habitica clean!"
|
||||
process.exit(anyFailed)
|
||||
|
||||
# Prepare files, db, and spin up servers.
|
||||
prepareEnvironment: (cb) ->
|
||||
sh.exec "grunt build:test"
|
||||
sh.exec "mongo \"#{TEST_DB}\" --eval \"db.dropDatabase()\""
|
||||
sh.exec "./node_modules/protractor/bin/webdriver-manager update"
|
||||
|
||||
# Spin this up even if we're not in a headless environment. Shouldn't matter.
|
||||
sh.exec "Xvfb :99 -screen 0 1024x768x24 -extension RANDR", silent: true, async: true
|
||||
|
||||
sh.exec "./node_modules/protractor/bin/webdriver-manager start", silent: true, async: true
|
||||
sh.exec "NODE_DB_URI=\"#{TEST_DB_URI}\" PORT=\"#{TEST_SERVER_PORT}\" node ./website/src/server.js", silent: true, async: true
|
||||
cb()
|
||||
|
||||
# Ensure both the selenium and node servers are available
|
||||
awaitServers: (cb) ->
|
||||
async.parallel [Suite.awaitSelenium, Suite.awaitNode], (err, results) ->
|
||||
throw err if err?
|
||||
cb()
|
||||
|
||||
awaitSelenium: (cb) ->
|
||||
waited = 0
|
||||
interval = setInterval ->
|
||||
if sh.exec('nc -z localhost 4444').code is 0
|
||||
clearInterval(interval)
|
||||
cb()
|
||||
waited += 1
|
||||
if waited > MAX_WAIT
|
||||
clearInterval(interval)
|
||||
cb(new Error("Timed out waiting for Selenium"))
|
||||
, 1000
|
||||
|
||||
awaitNode: (cb) ->
|
||||
waited = 0
|
||||
interval = setInterval ->
|
||||
if sh.exec('nc -z localhost 3001').code is 0
|
||||
clearInterval(interval)
|
||||
cb()
|
||||
waited += 1
|
||||
if waited > MAX_WAIT
|
||||
clearInterval(interval)
|
||||
cb(new Error("Timed out waiting for Node server"))
|
||||
, 1000
|
||||
|
||||
runApiSpecs: ->
|
||||
announce "Running API Specs (Mocha)"
|
||||
sh.exec("NODE_ENV=testing ./node_modules/mocha/bin/mocha test/api").code
|
||||
|
||||
runCommonSpecs: ->
|
||||
announce "Running Common Specs (Mocha)"
|
||||
sh.exec("NODE_ENV=testing ./node_modules/mocha/bin/mocha test/common").code
|
||||
|
||||
runE2ESpecs: ->
|
||||
announce "Running End-to-End Specs (Protractor)"
|
||||
sh.exec("DISPLAY=:99 NODE_ENV=testing ./node_modules/protractor/bin/protractor protractor.conf.js").code
|
||||
|
||||
runKarmaSpecs: ->
|
||||
announce "Running Karma Specs"
|
||||
sh.exec("NODE_ENV=testing grunt karma:continuous").code
|
||||
|
||||
Suite.run()
|
||||
Loading…
Reference in a new issue