From b452e04e08fd6b915439f53046a802019a95ccca Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sat, 5 Jul 2014 19:34:17 -0400 Subject: [PATCH] Add a task to run the tests once with PhantomJS The test.js task starts the development server and runs the tests in PhantomJS. As mentioned in the readme, when running the tests continuously during development, it is more convenient to start the dev server and visit the root of the test directory in your browser. Later we can bring in Karma to drive PhantomJS and other browsers, but this simple "run once" task is useful for the CI job. --- .travis.yml | 2 - build.py | 3 +- package.json | 3 +- tasks/readme.md | 5 ++ tasks/serve.js | 134 +++++++++++++++++++++++++++++------------------- tasks/test.js | 68 ++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 59 deletions(-) create mode 100644 tasks/test.js diff --git a/.travis.yml b/.travis.yml index 8a9a661f7f..56346bd3b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,6 @@ before_install: - "npm install -g npm && npm install" before_script: - - "./build.py serve &" - "rm src/ol/renderer/webgl/*shader.js" - - "sleep 3" script: "./build.py ci" diff --git a/build.py b/build.py index f0763dc48b..006fe58b16 100755 --- a/build.py +++ b/build.py @@ -688,8 +688,7 @@ def proj4js_zip(t): @target('test', PROJ4JS, phony=True) def test(t): - t.run('%(PHANTOMJS)s', 'test/mocha-phantomjs.js', - 'http://localhost:3000/test/index.html') + t.run('node', 'tasks/test.js') @target('fixme', phony=True) diff --git a/package.json b/package.json index da8a8b18b7..a1c8336ac3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Mapping library", "scripts": { "postinstall": "node tasks/parse-examples.js", - "start": "node tasks/serve.js" + "start": "node tasks/serve.js", + "test": "node tasks/test.js" }, "repository": { "type": "git", diff --git a/tasks/readme.md b/tasks/readme.md index 2e6dcb99f9..5b1b902bdf 100644 --- a/tasks/readme.md +++ b/tasks/readme.md @@ -104,3 +104,8 @@ Called after install to generate an example index. After new examples are added Run a debug server that provides all library sources unminified. Provides a static server for examples and tests. See the `--help` option for more detail. node tasks/serve.js --help + + +## `test.js` + +Run the tests once in a headless browser. Note that you can also run the tests by running the `serve.js` task and then visiting the root of the test directory in your browser. diff --git a/tasks/serve.js b/tasks/serve.js index 23118a5959..219ce69a5f 100644 --- a/tasks/serve.js +++ b/tasks/serve.js @@ -12,62 +12,88 @@ var nomnom = require('nomnom'); var log = closure.log; -var options = nomnom.options({ - port: { - abbr: 'p', - default: 3000, - help: 'Port for incoming connections', - metavar: 'PORT' - }, - loglevel: { - abbr: 'l', - choices: ['silly', 'verbose', 'info', 'warn', 'error'], - default: 'info', - help: 'Log level', - metavar: 'LEVEL' - } -}).parse(); - -/** @type {string} */ -log.level = options.loglevel; - -log.info('ol', 'Parsing dependencies ...'); -var manager = new closure.Manager({ - closure: true, // use the bundled Closure Library - lib: [ - 'src/**/*.js', - 'test/spec/**/*.test.js' - ], - main: 'examples/*.js' -}); -manager.on('error', function(e) { - log.error('ol', e.message); -}); -manager.on('ready', function() { - var server = new closure.Server({ - manager: manager, - loader: /^\/\w+\/loader.js/, - getMain: function(req) { - var main; - var query = url.parse(req.url, true).query; - if (query.id) { - var referer = req.headers.referer; - if (referer) { - var from = path.join(process.cwd(), - path.dirname(url.parse(referer).pathname)); - main = path.resolve(from, query.id + '.js'); - } - } - return main; +/** + * Create a debug server for ol and Closure Library sources. + * @param {function(Error, closure.Server)} callback Callback. + */ +var createServer = exports.createServer = function(callback) { + var server; + var manager = new closure.Manager({ + lib: [ + 'src/**/*.js', + 'test/spec/**/*.test.js' + ], + main: 'examples/*.js' + }); + manager.on('error', function(err) { + if (server) { + log.error('serve', err.message); + } else { + callback(err); } }); - server.listen(options.port, function() { - log.info('ol', 'Listening on http://localhost:' + - options.port + '/ (Ctrl+C to stop)'); + manager.on('ready', function() { + server = new closure.Server({ + manager: manager, + loader: /^\/\w+\/loader.js/, + getMain: function(req) { + var main; + var query = url.parse(req.url, true).query; + if (query.id) { + var referer = req.headers.referer; + if (referer) { + var from = path.join(process.cwd(), + path.dirname(url.parse(referer).pathname)); + main = path.resolve(from, query.id + '.js'); + } + } + return main; + } + }); + callback(null, server); }); - server.on('error', function(err) { - log.error('ol', 'Server failed to start: ' + err.message); - process.exit(1); +}; + + +/** + * If running this module directly start the server. + */ +if (require.main === module) { + var options = nomnom.options({ + port: { + abbr: 'p', + default: 3000, + help: 'Port for incoming connections', + metavar: 'PORT' + }, + loglevel: { + abbr: 'l', + choices: ['silly', 'verbose', 'info', 'warn', 'error'], + default: 'info', + help: 'Log level', + metavar: 'LEVEL' + } + }).parse(); + + /** @type {string} */ + log.level = options.loglevel; + + log.info('serve', 'Parsing dependencies ...'); + createServer(function(err, server) { + if (err) { + log.error('serve', 'Parsing failed'); + log.error('serve', err.message); + process.exit(1); + } + server.listen(options.port, function() { + log.info('serve', 'Listening on http://localhost:' + + options.port + '/ (Ctrl+C to stop)'); + }); + server.on('error', function(err) { + log.error('serve', 'Server failed to start: ' + err.message); + process.exit(1); + }); + }); -}); +} diff --git a/tasks/test.js b/tasks/test.js new file mode 100644 index 0000000000..f082b468a5 --- /dev/null +++ b/tasks/test.js @@ -0,0 +1,68 @@ +/** + * This task starts a dev server that provides a script loader for OpenLayers + * and Closure Library and runs tests in PhantomJS. + */ + +var path = require('path'); +var spawn = require('child_process').spawn; + +var phantomjs = require('phantomjs'); + +var serve = require('./serve'); + +/** + * Try listening for incoming connections on a range of ports. + * @param {number} min Minimum port to try. + * @param {number} max Maximum port to try. + * @param {http.Server} server The server. + * @param {function(Error)} callback Callback called with any error. + */ +function listen(min, max, server, callback) { + function _listen(port) { + server.once('error', function(err) { + if (err.code === 'EADDRINUSE') { + ++port; + if (port < max) { + _listen(port); + } else { + callback(new Error('Could not find an open port')); + } + } else { + callback(err); + } + }); + server.listen(port, callback); + } + _listen(min); +} + + +/** + * Create the debug server and run tests. + */ +serve.createServer(function(err, server) { + if (err) { + console.error(err.message); + process.exit(1); + } + + listen(3001, 3005, server, function(err) { + if (err) { + console.error('Server failed to start: ' + err.message); + process.exit(1); + } + + var address = server.address(); + var url = 'http://' + address.address + ':' + address.port; + var args = [ + path.join(__dirname, '..', 'test', 'mocha-phantomjs.js'), + url + '/test/index.html' + ]; + + var child = spawn(phantomjs.path, args, {stdio: 'inherit'}); + child.on('exit', function(code) { + process.exit(code); + }); + }); + +});