diff --git a/README.md b/README.md index 16bc32f..e632ea3 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,11 @@ # PhantomJS Runners for Mocha -[Mocha](http://mochajs.org/) is a feature-rich JavaScript test framework running on node and the browser. Along with the [Chai](http://chaijs.com) assertion library they make an impressive combo. [PhantomJS](http://phantomjs.org) is a headless WebKit with a JavaScript/CoffeeScript API. It has fast and native support for various web standards like DOM handling, CSS selectors, JSON, Canvas, and SVG. +[Mocha](http://mochajs.org/) is a feature-rich JavaScript test framework running on node and the browser. Along with the [Chai](http://chaijs.com) assertion library they make an impressive combo. [PhantomJS](http://phantomjs.org) is a headless WebKit with a JavaScript API. -The mocha-phantomjs project provides a `mocha-phantomjs.coffee` script file and extensions to drive PhantomJS while testing your HTML pages with Mocha from the console. The preferred usage is to install `mocha-phantomjs` via node's packaged modules and use the `mocha-phantomjs` binary wrapper. Tested with Mocha 1.12.x, Chai 1.7.x, and PhantomJS 1.9.1. - - * **Since version 3.0 of mocha-phantomjs, you must use PhantomJS 1.9.1 or higher.** +Since 4.0, the phantomjs code now is in [mocha-phantomjs-core](https://github.com/nathanboktae/mocha-phantomjs-core). If you need full control over which phantomjs version to use and where to get it, or want to use it more programatically like a build system plugin, please use that package directly. This project is a node.js CLI around it. [![Build Status](https://secure.travis-ci.org/nathanboktae/mocha-phantomjs.png)](http://travis-ci.org/nathanboktae/mocha-phantomjs) - # Key Features ### Standard Out @@ -21,21 +18,16 @@ Proper exit status codes from PhantomJS using Mocha's failures count. So in stan ### Mixed Mode Runs -You can use your existing Mocha HTML file reporters side by side with mocha-phantomjs. This gives you the option to run your tests both in a browser or with PhantomJS. Since mocha-phantomjs needs to control when the `run()` command is sent to the mocha object, we accomplish this by setting the `mochaPhantomJS` on the `window` object to `true`. Below, in the usage section, is an example of a HTML structure that can be used both by opening the file in your browser or choice or using mocha-phantomjs. - +You can use your existing Mocha HTML file reporters side by side with mocha-phantomjs. This gives you the option to run your tests both in a browser or with PhantomJS, with no changes needed to your existing test setup. # Installation -We distribute [mocha-phantomjs as an npm](https://npmjs.org/package/mocha-phantomjs) that is easy to install. Once done, you will have a `mocha-phantomjs` binary. See the next usage section for docs or use the `-h` flag. - -Since 3.4, we now declare phantomjs as a peer dependency, and it will be installed adjacent to `mocha-phantomjs` automatically. You may use `-p` to provide an explicit path to phantomjs, or call phantomjs directly yourself via `phantomjs lib/mocha-phantomjs.coffee `. The later approach is recommended for build system plugins to avoid another process fork. - -Due to [a bug in phantomjs 1.9.8+](https://github.com/nathanboktae/mocha-phantomjs/issues/167), mocha-phantomjs currnently caps its peer depedency to `1.9.7-15`. If you are having install errors due to peer depdendency resolution conflics, expliclity declare your dependency as `"phantomjs": "1.9.7-15"`, or expliclity install 1.9.7, like `npm install phantomjs@1.9.7-15`. +We distribute [mocha-phantomjs as an npm package](https://npmjs.org/package/mocha-phantomjs) that is easy to install. Once done, you will have a `mocha-phantomjs` binary. See the next usage section for docs or use the `-h` flag. # Usage ``` -Usage: mocha-phantomjs [options] page + Usage: mocha-phantomjs [options] page Options: @@ -56,6 +48,7 @@ Usage: mocha-phantomjs [options] page -C, --no-color disable color escape codes -p, --path path to PhantomJS binary + Any other options are passed to phantomjs (see `phantomjs --help`) Examples: @@ -67,7 +60,7 @@ Usage: mocha-phantomjs [options] page Now as an node package, using `mocha-phantomjs` has never been easier. The page argument can be either a local or fully qualified path or a http or file URL. `--reporter` may be a built-in reporter or a path to your own reporter (see below). See [phantomjs WebPage settings](https://github.com/ariya/phantomjs/wiki/API-Reference-WebPage#wiki-webpage-settings) for options that may be supplied to the `--setting` argument. -Your HTML file's structure should look something like this. The reporter set below to `html` is only needed for viewing the HTML page in your browser. The `mocha-phantomjs.coffee` script overrides that reporter value. The conditional run at the bottom allows the mixed mode feature described above. +Since 4.0, you need no modifications to your test harness markup file to run. Here is an example `test.html`: ```html @@ -81,14 +74,13 @@ Your HTML file's structure should look something like this. The reporter set bel + @@ -186,13 +178,7 @@ We also use Travis CI to run our tests too. The current build status: [![Build Status](https://secure.travis-ci.org/nathanboktae/mocha-phantomjs.png)](http://travis-ci.org/nathanboktae/mocha-phantomjs) -# Alternatives - -* OpenPhantomScripts - https://github.com/mark-rushakoff/OpenPhantomScripts -* Front Tests - https://github.com/Backbonist/front-tests - - # License -Released under the MIT license. Copyright (c) 2012 Ken Collins. +Released under the MIT license. Copyright (c) 2015 Ken Collins, Nathan Black, and many generous GitHub Contributors. diff --git a/bin/mocha-phantomjs b/bin/mocha-phantomjs index cb6082e..c670675 100755 --- a/bin/mocha-phantomjs +++ b/bin/mocha-phantomjs @@ -58,11 +58,12 @@ function resolveHooks(val) { } program + .allowUnknownOption() .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version) .usage('[options] page') .option('-R, --reporter ', 'specify the reporter to use', 'spec') .option('-f, --file ', 'specify the file to dump reporter output') - .option('-t, --timeout ', 'specify the test startup timeout to use', parseInt, 6000) + .option('-t, --timeout ', 'specify the test startup timeout to use', parseInt) .option('-g, --grep ', 'only run tests matching ') .option('-i, --invert', 'invert --grep matches') .option('-b, --bail', 'exit on the first test failure') @@ -77,6 +78,8 @@ program .option('--ignore-resource-errors', 'ignore resource errors'); program.on('--help', function(){ + console.log(' Any other options are passed to phantomjs (see `phantomjs --help`)'); + console.log(''); console.log(' Examples:'); console.log(''); console.log(' $ mocha-phantomjs -R dot /test/file.html'); @@ -90,7 +93,7 @@ program.parse(process.argv); if (!program.args.length) { program.outputHelp(); process.exit(1); }; if (program.agent) { settings.userAgent = program.agent; } -var script = fs.realpathSync(__dirname + '/../lib/mocha-phantomjs.coffee'); +var script = fs.realpathSync(__dirname + '/../node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js'); var reporter = program.reporter; var page = function(){ var arg = program.args[0]; @@ -103,7 +106,7 @@ var page = function(){ }(); var config = JSON.stringify({ hooks: program.hooks, - timeout: program.timeout, + timeout: program.timeout || 6000, cookies: cookies, headers: headers, settings: settings, @@ -148,8 +151,12 @@ function launchFailure(e) { process.exit(-2); } +var unknown = program.parseOptions(process.argv).unknown.filter(function(u) { + return u !== program.args[0] +}) + try { - var phantomjs = spawn(phantomPath, [script, page, reporter, config]); + var phantomjs = spawn(phantomPath, unknown.concat([script, page, reporter, config])) phantomjs.stdout.pipe(process.stdout); phantomjs.stderr.pipe(process.stderr); phantomjs.on('exit', function(code){ diff --git a/lib/mocha-phantomjs.coffee b/lib/mocha-phantomjs.coffee deleted file mode 100644 index 3c6af81..0000000 --- a/lib/mocha-phantomjs.coffee +++ /dev/null @@ -1,191 +0,0 @@ -system = require 'system' -webpage = require 'webpage' -fs = require 'fs' - -USAGE = """ - Usage: phantomjs mocha-phantomjs.coffee URL REPORTER [CONFIG] - """ - -class Reporter - - constructor: (@reporter, @config) -> - @url = system.args[1] - @columns = parseInt(system.env.COLUMNS or 75) * .75 | 0 - @mochaStartWait = @config.timeout || 6000 - @startTime = Date.now() - @output = if @config.file then fs.open(@config.file, 'w') else system.stdout - @fail(USAGE) unless @url - - run: -> - @initPage() - @loadPage() - - customizeMocha: (options) -> - Mocha.reporters.Base.window.width = options.columns - - customizeOptions: -> - columns: @columns - - # Private - - fail: (msg, errno) -> - @output.close() if @output and @config.file - console.log msg if msg - phantom.exit errno || 1 - - finish: -> - @output.close() if @config.file - phantom.exit @page.evaluate -> mochaPhantomJS.failures - - initPage: -> - @page = webpage.create - settings: @config.settings - @page.customHeaders = @config.headers if @config.headers - @page.addCookie(cookie) for cookie in @config.cookies or [] - @page.viewportSize = @config.viewportSize if @config.viewportSize - @page.onConsoleMessage = (msg) -> system.stdout.writeLine(msg) - @page.onResourceError = (resErr) => - if !@config.ignoreResourceErrors - system.stdout.writeLine "Error loading resource #{resErr.url} (#{resErr.errorCode}). Details: #{resErr.errorString}" - @page.onError = (msg, traces) => - return if @page.evaluate -> window.onerror? - for {line, file}, index in traces - traces[index] = " #{file}:#{line}" - @fail "#{msg}\n\n#{traces.join '\n'}" - @page.onInitialized = => - @page.evaluate (env)-> - window.mochaPhantomJS = - env: env - failures: 0 - ended: false - started: false - run: -> - mochaPhantomJS.runArgs = arguments - mochaPhantomJS.started = true - window.callPhantom 'mochaPhantomJS.run': true - mochaPhantomJS.runner - , system.env - - loadPage: -> - @page.open @url - @page.onLoadFinished = (status) => - @page.onLoadFinished = -> - @onLoadFailed() if status isnt 'success' - @waitForInitMocha() - @page.onCallback = (data) => - if data?.hasOwnProperty 'Mocha.process.stdout.write' - @output.write data['Mocha.process.stdout.write'] - else if data?.hasOwnProperty 'mochaPhantomJS.run' - @waitForRunMocha() if @injectJS() - else if typeof data?.screenshot is "string" - @page.render(data.screenshot + ".png") - true - - onLoadFailed: -> - @fail "Failed to load the page. Check the url: #{@url}" - - injectJS: -> - if @page.evaluate(-> window.mocha?) - @page.injectJs 'mocha-phantomjs/core_extensions.js' - @page.evaluate @customizeMocha, @customizeOptions() - true - else - @fail "Failed to find mocha on the page." - false - - runMocha: -> - @page.evaluate (config) -> - mocha.useColors config.useColors - mocha.bail config.bail - mocha.grep config.grep if config.grep - mocha.invert() if config.invert - , @config - - @config.hooks.beforeStart?(this) - - unless @page.evaluate(@setupReporter, @reporter) is true - customReporter = fs.read(@reporter) - wrapper = -> - require = (what) -> - what = what.replace /[^a-zA-Z0-9]/g, '' - for r of Mocha.reporters - return Mocha.reporters[r] if r.toLowerCase() is what - throw new Error "Your custom reporter tried to require '#{what}', but Mocha is not running in Node.js in mocha-phantomjs, so Node modules cannot be required - only other reporters" - - module = {} - exports = undefined - process = Mocha.process - - 'customreporter' - Mocha.reporters.Custom = exports or module.exports - - wrappedReporter = wrapper.toString().replace "'customreporter'", "(function() {#{customReporter.toString()}})()" - @page.evaluate wrappedReporter - - if @page.evaluate(-> !Mocha.reporters.Custom) or @page.evaluate(@setupReporter) isnt true - @fail "Failed to use load and use the custom reporter #{@reporter}" - - if @page.evaluate @runner - @mochaRunAt = new Date().getTime() - @waitForMocha() - else - @fail "Failed to start mocha." - - waitForMocha: => - ended = @page.evaluate -> mochaPhantomJS.ended - if ended - @config.hooks.afterEnd?(this) - @finish() - else - setTimeout @waitForMocha, 100 - - waitForInitMocha: => - setTimeout @waitForInitMocha, 100 unless @checkStarted() - - waitForRunMocha: => - if @checkStarted() then @runMocha() else setTimeout @waitForRunMocha, 100 - - checkStarted: => - started = @page.evaluate -> mochaPhantomJS.started - if !started && @mochaStartWait && @startTime + @mochaStartWait < Date.now() - @fail "Failed to start mocha: Init timeout", 255 - started - - setupReporter: (reporter) -> - try - mocha.setup - reporter: reporter or Mocha.reporters.Custom - true - catch error - error - - runner: -> - try - mochaPhantomJS.runner = mocha.run.apply mocha, mochaPhantomJS.runArgs - if mochaPhantomJS.runner - cleanup = -> - mochaPhantomJS.failures = mochaPhantomJS.runner.failures - mochaPhantomJS.ended = true - if mochaPhantomJS.runner?.stats?.end - cleanup() - else - mochaPhantomJS.runner.on 'end', cleanup - !!mochaPhantomJS.runner - catch error - false - -if phantom.version.major < 1 or (phantom.version.major is 1 and phantom.version.minor < 9) - console.log 'mocha-phantomjs requires PhantomJS > 1.9.1' - phantom.exit -1 - -reporter = system.args[2] || 'spec' - -config = JSON.parse system.args[3] || '{}' - -if config.hooks - config.hooks = require(config.hooks) -else - config.hooks = {} - -mocha = new Reporter reporter, config -mocha.run() diff --git a/lib/mocha-phantomjs/core_extensions.js b/lib/mocha-phantomjs/core_extensions.js deleted file mode 100644 index f44bccf..0000000 --- a/lib/mocha-phantomjs/core_extensions.js +++ /dev/null @@ -1,70 +0,0 @@ -(function(){ - - // A shim for non ES5 supporting browsers, like PhantomJS. Lovingly inspired by: - // http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.html - if (!('bind' in Function.prototype)) { - Function.prototype.bind = function() { - var funcObj = this; - var extraArgs = Array.prototype.slice.call(arguments); - var thisObj = extraArgs.shift(); - return function() { - return funcObj.apply(thisObj, extraArgs.concat(Array.prototype.slice.call(arguments))); - }; - }; - } - - // Mocha needs a process.stdout.write in order to change the cursor position. - Mocha.process = Mocha.process || {}; - Mocha.process.stdout = Mocha.process.stdout || process.stdout; - Mocha.process.stdout.write = function(s) { window.callPhantom({"Mocha.process.stdout.write":s}); } - - // Mocha needs the formating feature of console.log so copy node's format function and - // monkey-patch it into place. This code is copied from node's, links copyright applies. - // https://github.com/joyent/node/blob/master/lib/util.js - console.format = function(f) { - if (typeof f !== 'string') { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - try { - objects.push(JSON.stringify(arguments[i])); - } - catch (_) { - objects.push('[Circular]'); - } - } - return objects.join(' '); - } - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(/%[sdj%]/g, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (x === null || typeof x !== 'object') { - str += ' ' + x; - } else { - str += ' ' + JSON.stringify(x); - } - } - return str; - }; - var origError = console.error; - console.error = function(){ origError.call(console, console.format.apply(console, arguments)); }; - var origLog = console.log; - console.log = function(){ origLog.call(console, console.format.apply(console, arguments)); }; - -})(); diff --git a/package.json b/package.json index 8eff1c6..687e04b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha-phantomjs", - "description": "PhantomJS Runners for Mocha", + "description": "Run nocha browser tests in phantomjs via the command line", "keywords": [ "phantomjs", "mocha", @@ -9,43 +9,41 @@ "command line", "browser" ], - "version": "3.6.0", - "author": "Ken Collins (http://metaskills.net/)", + "version": "4.0.0", + "author": "Nathan Black (http://nathanblack.org)", "licenses": [ { "type": "MIT", - "url": "http://github.com/metaskills/mocha-phantomjs/blob/master/MIT-LICENSE" + "url": "http://github.com/nathanboktae/mocha-phantomjs/blob/master/MIT-LICENSE" } ], "contributors": [ "Jonathan Chapman (https://github.com/chafnan)", - "Nathan Black (https://github.com/nathanboktae)" + "Ken Collins (http://metaskills.net/)" ], "repository": { "type": "git", - "url": "http://github.com/metaskills/mocha-phantomjs.git" + "url": "http://github.com/nathanboktae/mocha-phantomjs.git" }, "bugs": { - "url": "http://github.com/metaskills/mocha-phantomjs/issues" + "url": "http://github.com/nathanboktae/mocha-phantomjs/issues" }, - "main": "./lib/mocha-phantomjs.coffee", + "main": "./bin/mocha-phantomjs", "bin": { "mocha-phantomjs": "./bin/mocha-phantomjs" }, "scripts": { - "test": "mocha --compilers coffee:coffee-script test/mocha-phantomjs.coffee -t 20000 -R spec" - }, - "peerDependencies": { - "phantomjs": "1.9.1 - 1.9.7-15" + "test": "mocha --harmony --compilers coffee:coffee-script/register test/mocha-phantomjs.coffee -t 5000" }, "dependencies": { - "mocha": "~1.20.1", - "commander": "~2.0.0" + "phantomjs": "1.9.7-15", + "mocha-phantomjs-core": "^1.1.0", + "commander": "^2.8.1" }, "devDependencies": { - "phantomjs": "1.9.1 - 1.9.7-15", - "chai": "1.8.x", - "coffee-script": "1.6.x", - "requirejs": "2.1.x" + "bluebird": "^2.9.25", + "chai": "^2.3.0", + "co-mocha": "^1.1.0", + "coffee-script": "^1.9.2" } } diff --git a/test/bad.html b/test/bad.html deleted file mode 100755 index ab85060..0000000 --- a/test/bad.html +++ /dev/null @@ -1,18 +0,0 @@ - - - Bad Mocha - - - - - - - diff --git a/test/blank.html b/test/blank.html deleted file mode 100755 index 3434a95..0000000 --- a/test/blank.html +++ /dev/null @@ -1,13 +0,0 @@ - - - Blank Page - - - - - - diff --git a/test/console-log.html b/test/console-log.html index ab4a0d6..8040a31 100644 --- a/test/console-log.html +++ b/test/console-log.html @@ -1,3 +1,4 @@ + Tests Passing @@ -15,11 +16,7 @@ diff --git a/test/cookie.html b/test/cookie.html index 70fdca6..2e15e0d 100644 --- a/test/cookie.html +++ b/test/cookie.html @@ -1,3 +1,4 @@ + Tests Cookie @@ -13,11 +14,7 @@ diff --git a/test/env.html b/test/env.html index 09f9299..e94424b 100644 --- a/test/env.html +++ b/test/env.html @@ -1,3 +1,4 @@ + Tests env @@ -12,12 +13,8 @@ mocha.reporter('html'); diff --git a/test/error.html b/test/error.html index 6f5f3c6..e2c0122 100644 --- a/test/error.html +++ b/test/error.html @@ -1,3 +1,4 @@ + Tests Cookie @@ -14,11 +15,7 @@ diff --git a/test/failing-async.html b/test/failing-async.html index 69429a2..31667e7 100644 --- a/test/failing-async.html +++ b/test/failing-async.html @@ -1,3 +1,4 @@ + Async Tests Failing @@ -15,11 +16,7 @@ diff --git a/test/failing.html b/test/failing.html index fce98c5..eb5f550 100644 --- a/test/failing.html +++ b/test/failing.html @@ -1,3 +1,4 @@ + Tests Failing @@ -15,11 +16,7 @@ diff --git a/test/file.html b/test/file.html index 2fc3af6..11b96dd 100644 --- a/test/file.html +++ b/test/file.html @@ -1,3 +1,4 @@ + Tests Reporter Output to File @@ -16,11 +17,7 @@ diff --git a/test/iframe.html b/test/iframe.html deleted file mode 100644 index cba9bc1..0000000 --- a/test/iframe.html +++ /dev/null @@ -1,45 +0,0 @@ - - - Tests Passing - - - - -
- - - - - - - - diff --git a/test/lib/requirejs-app.js b/test/lib/requirejs-app.js deleted file mode 100644 index cda76ea..0000000 --- a/test/lib/requirejs-app.js +++ /dev/null @@ -1,7 +0,0 @@ -define(['passing'], function(require) { - if (window.mochaPhantomJS) { - return mochaPhantomJS.run(); - } else { - return mocha.run(); - } -}); diff --git a/test/many.html b/test/many.html index f33fff7..4c82f27 100644 --- a/test/many.html +++ b/test/many.html @@ -1,3 +1,4 @@ + Many Tests @@ -15,11 +16,7 @@ diff --git a/test/mixed.html b/test/mixed.html index abad918..3d24c7b 100644 --- a/test/mixed.html +++ b/test/mixed.html @@ -1,3 +1,4 @@ + Tests Mixed @@ -15,11 +16,7 @@ diff --git a/test/mocha-phantomjs.coffee b/test/mocha-phantomjs.coffee index 4237e20..f773f94 100644 --- a/test/mocha-phantomjs.coffee +++ b/test/mocha-phantomjs.coffee @@ -1,9 +1,11 @@ describe 'mocha-phantomjs', -> - expect = require('chai').expect + chai = require 'chai' + expect = chai.expect + should = chai.should() spawn = require('child_process').spawn - url = require('url') - fs = require('fs') + url = require 'url' + fs = require 'fs' fileURL = (file) -> fullPath = fs.realpathSync "#{process.cwd()}/test/#{file}.html" @@ -11,8 +13,8 @@ describe 'mocha-phantomjs', -> urlString = fullPath urlString = url.format { protocol: 'file', hostname: '', pathname: fullPath } if process.platform isnt 'win32' - before -> - @runner = (done, args, callback) -> + run = (args) -> + new Promise (resolve, reject) -> stdout = '' stderr = '' spawnArgs = ["#{process.cwd()}/bin/mocha-phantomjs"].concat(args) @@ -20,409 +22,213 @@ describe 'mocha-phantomjs', -> mochaPhantomJS.stdout.on 'data', (data) -> stdout = stdout.concat data.toString() mochaPhantomJS.stderr.on 'data', (data) -> stderr = stderr.concat data.toString() mochaPhantomJS.on 'exit', (code) -> - callback?(code, stdout, stderr) - done?() - - it 'returns a failure code and shows usage when no args are given', (done) -> - @runner done, [], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /Usage: mocha-phantomjs/ - - it 'returns a failure code and notifies of bad url when given one', (done) -> - @runner done, ['foo/bar.html'], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /failed to load the page/i - expect(stdout).to.match /check the url/i - expect(stdout).to.match /foo\/bar.html/i - - it 'returns a failure code and notifies of no such runner class', (done) -> - @runner done, ['-R', 'nonesuch', fileURL('passing')], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /Unable to open file 'nonesuch'/ - - it 'returns a success code when a directory exists with the same name as a built-in runner', (done) -> - fs.mkdir 'spec' - @runner done, ['-R', 'spec', fileURL('passing')], (code, stdout, stderr) -> - fs.rmdir 'spec' - expect(code).to.equal 0 - - it 'returns a failure code when mocha can not be found on the page', (done) -> - @runner done, [fileURL('blank')], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /Failed to find mocha on the page/ - - it 'returns a failure code when mocha fails to start for any reason', (done) -> - @runner done, [fileURL('bad')], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /Failed to start mocha./ - - it 'returns a failure code when mocha is not started in a timely manner', (done) -> - @runner done, ['-t', 500, fileURL('timeout')], (code, stdout, stderr) -> - expect(code).to.equal 255 - expect(stdout).to.match /Failed to start mocha: Init timeout/ - - it 'returns a failure code when there is a page error', (done) -> - @runner done, [fileURL('error')], (code, stdout, stderr) -> - expect(code).to.equal 1 - expect(stdout).to.match /ReferenceError/ - - it 'does not fail when an iframe is used', (done) -> - @runner done, [fileURL('iframe')], (code, stdout, stderr) -> - expect(stdout).to.not.match /Failed to load the page\./m - expect(code).to.equal 0 - - it 'does not fail when console.log is used with circular reference object', (done) -> - @runner done, [fileURL('console-log')], (code, stdout, stderr) -> - expect(stdout).to.not.match /cannot serialize cyclic structures\./m - expect(code).to.equal 0 - - it 'returns the mocha runner from run() and allows modification of it', (done) -> - @runner done, [fileURL('mocha-runner')], (code, stdout, stderr) -> - expect(stdout).to.not.match /Failed via an Event/m - expect(code).to.equal 1 - - it 'passes the arguments along to mocha.run', (done) -> - @runner done, [fileURL('mocha-runner')], (code, stdout, stderr) -> - expect(stdout).to.match /Run callback fired/m - - passRegExp = (n) -> ///\u001b\[32m\s\s[✔✓]\u001b\[0m\u001b\[90m\spasses\s#{n}/// - skipRegExp = (n) -> ///\u001b\[36m\s\s-\sskips\s#{n}\u001b\[0m/// - failRegExp = (n) -> ///\u001b\[31m\s\s#{n}\)\sfails\s#{n}\u001b\[0m/// - passComplete = (n) -> ///\u001b\[0m\n\n\n\u001b\[92m\s\s[✔✓]\u001b\[0m\u001b\[32m\s#{n}\stests\scomplete/// - pendComplete = (n) -> ///\u001b\[36m\s+•\u001b\[0m\u001b\[36m\s#{n}\stests\spending/// - failComplete = (x,y) -> ///\u001b\[31m\s\s#{x}\sfailing\u001b\[0m/// - - describe 'spec', -> - - describe 'passing', -> - - ### - $ ./bin/mocha-phantomjs -R spec test/passing.html - $ mocha -r chai/chai.js -R spec --globals chai.expect test/lib/passing.js - ### - - before -> - @args = [fileURL('passing')] - - it 'returns a passing code', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(code).to.equal 0 - - it 'writes all output in color', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Passing/ - expect(stdout).to.match passRegExp(1) - expect(stdout).to.match passRegExp(2) - expect(stdout).to.match passRegExp(3) - expect(stdout).to.match skipRegExp(1) - expect(stdout).to.match skipRegExp(2) - expect(stdout).to.match skipRegExp(3) - - describe 'failing', -> - - ### - $ ./bin/mocha-phantomjs -R spec test/failing.html - $ mocha -r chai/chai.js -R spec --globals chai.expect test/lib/failing.js - ### - - before -> - @args = [fileURL('failing')] - - it 'returns a failing code equal to the number of mocha failures', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(code).to.equal 3 - - it 'writes all output in color', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Failing/ - expect(stdout).to.match passRegExp(1) - expect(stdout).to.match passRegExp(2) - expect(stdout).to.match passRegExp(3) - expect(stdout).to.match failRegExp(1) - expect(stdout).to.match failRegExp(2) - expect(stdout).to.match failRegExp(3) - expect(stdout).to.match failComplete(3,6) - - describe 'failing async', -> - - ### - $ ./bin/mocha-phantomjs -R spec test/failing-async.html - $ mocha -r chai/chai.js -R spec --globals chai.expect test/lib/failing-async.js - ### - - before -> - @args = [fileURL('failing-async')] - - it 'returns a failing code equal to the number of mocha failures', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(code).to.equal 3 - - it 'writes all output in color', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Failing/ - expect(stdout).to.match passRegExp(1) - expect(stdout).to.match passRegExp(2) - expect(stdout).to.match passRegExp(3) - expect(stdout).to.match failRegExp(1) - expect(stdout).to.match failRegExp(2) - expect(stdout).to.match failRegExp(3) - expect(stdout).to.match failComplete(3,6) - - describe 'screenshot', -> - - ### - $ ./bin/mocha-phantomjs -R spec test/screenshot.html - $ mocha -r chai/chai.js -R spec --globals chai.expect test/lib/screenshot.js - ### - - before -> - @args = [fileURL('screenshot')] - - it 'takes a screenshot into given file, suffixed with .png', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(code).to.equal 0 - fileName = "screenshot.png" - expect(fs.existsSync(fileName)).to.equal(true) - fs.unlinkSync(fileName) - - describe 'requirejs', -> - - before -> - @args = [fileURL('requirejs')] - - it 'returns a passing code', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(code).to.equal 0 - - it 'writes all output in color', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Passing/ - expect(stdout).to.match passRegExp(1) - expect(stdout).to.match passRegExp(2) - expect(stdout).to.match passRegExp(3) - expect(stdout).to.match skipRegExp(1) - expect(stdout).to.match skipRegExp(2) - expect(stdout).to.match skipRegExp(3) - - describe 'dot', -> - - ### - $ ./bin/mocha-phantomjs -R dot test/mixed.html - $ mocha -r chai/chai.js -R dot --globals chai.expect test/lib/mixed.js - ### - - before -> - @args = ['-R', 'dot', fileURL('mixed')] - - it 'uses dot reporter', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /\u001b\[90m\․\u001b\[0m/ # grey - expect(stdout).to.match /\u001b\[36m\․\u001b\[0m/ # cyan - expect(stdout).to.match /\u001b\[31m\․\u001b\[0m/ # red - - ### - $ ./bin/mocha-phantomjs -R dot test/many.html - $ mocha -r chai/chai.js -R dot --globals chai.expect test/lib/many.js - ### - - before -> - @args = ['-R', 'dot', fileURL('many')] - - it 'wraps lines correctly and has only one double space for the last dot', (done) -> - @runner done, @args, (code, stdout, stderr) -> - matches = stdout.match /\d\dm\․\u001b\[0m(\r\n\r\n|\n\n)/g - expect(matches.length).to.equal 1 - - describe 'tap', -> - - ### - $ ./bin/mocha-phantomjs -R tap test/mixed.html - $ mocha -r chai/chai.js -R tap --globals chai.expect test/lib/mixed.js - ### - - before -> - @args = ['-R', 'tap', fileURL('mixed')] - - it 'basically works', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Mixed/ - - describe 'list', -> - - ### - $ ./bin/mocha-phantomjs -R list test/mixed.html - $ mocha -r chai/chai.js -R list --globals chai.expect test/lib/mixed.js - ### - - before -> - @args = ['-R', 'list', fileURL('mixed')] - - it 'basically works', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /Tests Mixed/ - - describe 'doc', -> - - ### - $ ./bin/mocha-phantomjs -R doc test/mixed.html - $ mocha -r chai/chai.js -R doc --globals chai.expect test/lib/mixed.js - ### - - before -> - @args = ['-R', 'doc', fileURL('mixed')] - - it 'basically works', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match /

Tests Mixed<\/h1>/ - - - describe 'xunit', -> - - ### - $ ./bin/mocha-phantomjs -R xunit test/mixed.html - $ mocha -r chai/chai.js -R xunit --globals chai.expect test/lib/mixed.js - ### - - before -> - @args = ['-R', 'xunit', fileURL('mixed')] - - it 'basically works', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.match // - - describe 'third party', -> - - it 'loads and wraps node-style reporters to run in the browser', (done) -> - @runner done, ['-R', 'test/reporters/3rd-party', fileURL('mixed')], (code, stdout, stderr) -> - expect(stdout).to.match /
/ - expect(stdout).to.match /

Tests Mixed<\/h1>/ - - it 'gives a useful error when trying to require a node module', (done) -> - @runner done, ['-R', 'test/reporters/node-only', fileURL('mixed')], (code, stdout, stderr) -> - expect(stdout).to.match /Node modules cannot be required/ - + resolve { code, stdout, stderr } + mochaPhantomJS.on 'error', (err) -> reject err + + it 'returns a failure code and shows usage when no args are given', -> + { code, stdout } = yield run [] + code.should.equal 1 + stdout.should.match /Usage: mocha-phantomjs/ + + it 'returns a failure code and notifies of bad url when given one', -> + { code, stderr } = yield run ['foo/bar.html'] + code.should.equal 1 + stderr.should.match /failed to load the page/i + stderr.should.match /check the url/i + stderr.should.match /foo\/bar.html/i + + it 'returns a failure code and notifies of no such runner class', -> + { code, stderr } = yield run ['-R', 'nonesuch', fileURL('passing')] + code.should.equal 1 + stderr.should.match /Unable to open file 'nonesuch'/ + + it 'returns a failure code when mocha fails to run any tests', -> + { code, stderr } = yield run [fileURL('no-tests')] + code.should.equal 1 + stderr.should.match /mocha.run\(\) was called with no tests/ + + it 'returns a failure code when mocha is not started in a timely manner', -> + { code, stderr } = yield run ['-t', 500, fileURL('timeout')] + stderr.should.match /mocha.run\(\) was not called within 500ms of the page loading/ + code.should.not.equal 0 + + it 'returns a failure code when there is a page error', -> + { code, stderr } = yield run [fileURL('error')] + code.should.equal 1 + stderr.should.match /ReferenceError/ + + it 'does not fail when console.log is used with circular reference object', -> + { code, stdout, stderr } = yield run [fileURL('console-log')] + code.should.equal 0 + stderr.should.not.match /cannot serialize cyclic structures\./m + stdout.should.not.match /cannot serialize cyclic structures\./m + stdout.should.contain '[Circular]' + + it 'returns the mocha runner from run() and allows modification of it', -> + { code, stdout } = yield run [fileURL('mocha-runner')] + stdout.should.not.match /Failed via an Event/m + code.should.equal 1 + + it 'returns the mocha runner from run() and allows modification of it', -> + { code, stdout } = yield run [fileURL('mocha-runner')] + stdout.should.not.match /Failed via an Event/m + code.should.equal 1 + + it 'passes the arguments along to mocha.run', -> + { stdout } = yield run [fileURL('mocha-runner')] + stdout.should.match /Run callback fired/m + + it 'passes all unknown arguments to phantomjs', -> + { stderr } = yield run ['--unknown=true', fileURL('mocha-runner')] + stderr.should.match /Error: Unknown option: unknown/m + + it 'can use a different reporter', -> + { stdout } = yield run ['-R', 'xunit', fileURL('mixed')] + stdout.should.match // + + describe 'exit code', -> + it 'returns 0 when all tests pass', -> + { code } = yield run fileURL('passing') + code.should.equal 0 + + it 'returns a failing code equal to the number of mocha failures', -> + { code } = yield run fileURL('failing') + code.should.equal 3 + + it 'returns a failing code correctly even with async failing tests', -> + { code } = yield run fileURL('failing-async') + code.should.equal 3 + + describe 'screenshot', -> + it 'takes a screenshot into given file, suffixed with .png', -> + { code } = yield run fileURL('screenshot') + code.should.equal 0 + fileName = 'screenshot.png' + fs.existsSync(fileName).should.be.true + fs.unlinkSync(fileName) + + describe 'third party reporters', -> + it 'loads and wraps node-style reporters to run in the browser', -> + { stdout } = yield run ['-R', 'test/reporters/3rd-party', fileURL('mixed')] + + stdout.should.match /
/ + stdout.should.match /

Tests Mixed<\/h1>/ + + it 'gives a useful error when trying to require a node module', -> + { code, stderr } = yield run ['-R', 'test/reporters/node-only', fileURL('mixed')] + + stderr.should.match /Node modules cannot be required/ + code.should.not.equal 0 describe 'hooks', -> - - ### - $ ./bin/mocha-phantomjs -k test/before-start.js test/passing.html - ### - - describe 'before start', -> - - before -> - @args = ['-k', 'test/hooks/before-start.js', fileURL('passing')] - - it 'is called', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.contain 'Before start called!' - - describe 'after end', -> - - ### - $ ./bin/mocha-phantomjs -k test/after-end.js test/passing.html - ### - - before -> - @args = ['-k', 'test/hooks/after-end.js', fileURL('passing')] - - it 'is called', (done) -> - @runner done, @args, (code, stdout, stderr) -> - expect(stdout).to.contain 'After end called!' + it 'should fail gracefully if they do not exist', -> + { code, stderr } = yield run ['-k', 'nonexistant-file.js', fileURL('passing')] + code.should.not.equal 0 + stderr.should.contain('Error loading hooks').and.contain "nonexistant-file.js" + + it 'has a hook for before tests are started', -> + { code, stdout } = yield run ['-k', 'test/hooks/before-start.js', fileURL('passing')] - describe 'config', -> + stdout.should.contain 'Before start called!' + code.should.equal 0 + + it 'has a hook for after the test run finishes', -> + { code, stdout } = yield run ['-k', 'test/hooks/after-end.js', fileURL('passing')] + + stdout.should.contain 'After end called!' + code.should.equal 0 + describe 'parameters', -> describe 'user-agent', -> + it 'has the default user agent', -> + { stdout } = yield run [fileURL('user-agent')] + stdout.should.match /PhantomJS\// - it 'has the default user agent', (done) -> - @runner done, [fileURL('user-agent')], (code, stdout, stderr) -> - expect(stdout).to.match /PhantomJS\// - - it 'has a custom user agent', (done) -> - @runner done, ['-A', 'mochaUserAgent', fileURL('user-agent')], (code, stdout, stderr) -> - expect(stdout).to.match /^mochaUserAgent/ + it 'has a custom user agent', -> + { stdout } = yield run ['-A', 'mochaUserAgent', fileURL('user-agent')] + stdout.should.match /^mochaUserAgent/ - it 'has a custom user agent via setting flag and 2 equal signs', (done) -> - @runner done, ['-s', 'userAgent=mocha=UserAgent', fileURL('user-agent')], (code, stdout, stderr) -> - expect(stdout).to.match /^mocha=UserAgent/ + it 'has a custom user agent via setting flag and 2 equal signs', -> + { stdout } = yield run ['-s', 'userAgent=mocha=UserAgent', fileURL('user-agent')] + stdout.should.match /^mocha=UserAgent/ describe 'cookies', -> - - it 'has passed cookies', (done) -> + it 'has passed cookies', -> c1Opt = '{"name":"foo","value":"bar"}' c2Opt = '{"name":"baz","value":"bat","path":"/"}' - @runner done, ['-c', c1Opt, '--cookies', c2Opt, fileURL('cookie')], (code, stdout, stderr) -> - expect(stdout).to.match /foo=bar; baz=bat/ + { stdout } = yield run ['-c', c1Opt, '--cookies', c2Opt, fileURL('cookie')] + stdout.should.match /foo=bar; baz=bat/ describe 'viewport', -> - - it 'has passed cookies', (done) -> - @runner done, ['-v', '123x456', fileURL('viewport')], (code, stdout, stderr) -> - expect(stdout).to.match /123x456/ + it 'has the specified dimensions', -> + { stdout } = yield run ['-v', '123x456', fileURL('viewport')] + stdout.should.match /123x456/ describe 'grep', -> + it 'filters tests to match the criteria', -> + { code, stdout } = yield run ['-g', 'pass', fileURL('mixed')] + code.should.equal 0 + stdout.should.not.match /fail/ - it 'filters tests to match the criteria', (done) -> - @runner done, ['-g', 'pass', fileURL('mixed')], (code, stdout, stderr) -> - expect(code).to.equal 0 - expect(stdout).to.not.match /fail/ - - it 'can be inverted to filter out tests matching the criteria', (done) -> - @runner done, ['-g', 'pass', '-i', fileURL('mixed')], (code, stdout, stderr) -> - expect(code).to.equal 6 - expect(stdout).to.not.match /passes/ + it 'can be inverted to filter out tests matching the criteria', -> + { code, stdout } = yield run ['--grep', 'pass', '-i', fileURL('mixed')] + code.should.equal 6 + stdout.should.not.match /passes/ describe 'no-colors', -> + it 'by default will output in color', -> + { stdout } = yield run ['-R', 'dot', fileURL('mixed')] + + stdout.should.match /\u001b\[90m\․\u001b\[0m/ # grey + stdout.should.match /\u001b\[36m\․\u001b\[0m/ # cyan + stdout.should.match /\u001b\[31m\․\u001b\[0m/ # red - it 'suppresses color output', (done) -> - @runner done, ['-C', fileURL('mixed')], (code, stdout, stderr) -> - expect(stdout).to.not.match /\u001b\[\d\dm/ + it 'suppresses color output', -> + { stdout } = yield run ['-C', fileURL('mixed')] + stdout.should.not.match /\u001b\[\d\dm/ - it 'suppresses color output plural long form', (done) -> - @runner done, ['--no-colors', fileURL('mixed')], (code, stdout, stderr) -> - expect(stdout).to.not.match /\u001b\[\d\dm/ + it 'suppresses color output plural long form', -> + { stdout } = yield run ['--no-colors', fileURL('mixed')] + stdout.should.not.match /\u001b\[\d\dm/ describe 'bail', -> - - it 'should bail on the first error', (done) -> - @runner done, ['-b', fileURL('mixed')], (code, stdout, stderr) -> - expect(stdout).to.match failRegExp 1 + it 'should bail on the first error', -> + { stdout } = yield run ['-b', fileURL('mixed')] + stdout.should.contain '1 failing' describe 'path', -> + it 'will use the custom path to phantomjs', -> + { stderr } = yield run ['-p', 'fake/path/to/phantomjs', fileURL('passing')] + stderr.should.contain "PhantomJS does not exist at 'fake/path/to/phantomjs'" - it 'has used custom path', (done) -> - @runner done, ['-p', 'fake/path/to/phantomjs', fileURL('passing')], (code, stdout, stderr) -> - expect(stderr).to.contain "PhantomJS does not exist at 'fake/path/to/phantomjs'" - - it 'provides a useful error when phantomjs cannot be launched', (done) -> - @runner done, ['-p', 'package.json', fileURL('passing')], (code, stdout, stderr) -> - expect(stderr).to.contain "An error occurred trying to launch phantomjs" + it 'provides a useful error when phantomjs cannot be launched', -> + { stderr } = yield run ['-p', 'package.json', fileURL('passing')] + stderr.should.contain "An error occurred trying to launch phantomjs" describe 'file', -> - - it 'pipes reporter output to a file', (done) -> - @runner done, ['-f', 'reporteroutput.json', '-R', 'json', fileURL('file')], (code, stdout, stderr) -> - expect(stdout).to.contain 'Extraneous' - results = JSON.parse fs.readFileSync 'reporteroutput.json', { encoding: 'utf8' } - expect(results.passes.length).to.equal 6 - expect(results.failures.length).to.equal 6 + it 'pipes reporter output to a file', -> + { stdout } = yield run ['-f', 'reporteroutput.json', '-R', 'json', fileURL('file')] + stdout.should.contain 'Extraneous' + results = JSON.parse fs.readFileSync 'reporteroutput.json', { encoding: 'utf8' } + results.passes.length.should.equal 6 + results.failures.length.should.equal 6 after -> fs.unlinkSync 'reporteroutput.json' describe 'ignore resource errors', -> + it 'by default shows resource errors', -> + { code, stderr } = yield run [fileURL('resource-errors')] + stderr.should.contain('Error loading resource').and.contain('nonexistant-file.css') + code.should.equal 0 - it 'by default shows resource errors', (done) -> - @runner done, [fileURL('resource-errors')], (code, stdout, stderr) -> - expect(stdout).to.contain('Error loading resource').and.contain('nonexistant-file.css') - - it 'can suppress resource errors', (done) -> - @runner done, ['--ignore-resource-errors', fileURL('resource-errors')], (code, stdout, stderr) -> - expect(stdout).to.not.contain('Error loading resource') + it 'can suppress resource errors', -> + { stderr } = yield run ['--ignore-resource-errors', fileURL('resource-errors')] + stderr.should.be.empty describe 'env', -> - it 'has passed environment variables', (done) -> - process.env.FOO = 'bar' - @runner done, [fileURL('env')], (code, stdout, stderr) -> - expect(stdout).to.match /^bar/ + it 'has passed environment variables', -> + process.env.FOO = 'yowzer' + { stdout } = yield run [fileURL('env')] + stdout.should.match /^yowzer/ diff --git a/test/mocha-runner.html b/test/mocha-runner.html index 7ff1af6..836252e 100644 --- a/test/mocha-runner.html +++ b/test/mocha-runner.html @@ -1,3 +1,4 @@ + Tests Failing @@ -23,14 +24,10 @@ }); + + + diff --git a/test/passing.html b/test/passing.html index 8a1d282..1a138a5 100755 --- a/test/passing.html +++ b/test/passing.html @@ -1,3 +1,4 @@ + Tests Passing @@ -15,11 +16,7 @@ diff --git a/test/requirejs.html b/test/requirejs.html deleted file mode 100755 index 5053ae9..0000000 --- a/test/requirejs.html +++ /dev/null @@ -1,19 +0,0 @@ - - - Tests RequireJS - - - - -
- - - - - - - diff --git a/test/resource-errors.html b/test/resource-errors.html index 5b0946d..a53a2c9 100644 --- a/test/resource-errors.html +++ b/test/resource-errors.html @@ -1,3 +1,4 @@ + Resource Errors @@ -8,16 +9,14 @@
+ + diff --git a/test/screenshot.html b/test/screenshot.html index 73d7415..da59fcc 100644 --- a/test/screenshot.html +++ b/test/screenshot.html @@ -1,3 +1,4 @@ + Many Tests @@ -15,11 +16,7 @@ diff --git a/test/slow.html b/test/slow.html index 696b959..1f5814e 100644 --- a/test/slow.html +++ b/test/slow.html @@ -1,3 +1,4 @@ + Slow tests @@ -15,11 +16,7 @@ diff --git a/test/timeout.html b/test/timeout.html index 81f5220..acbae86 100644 --- a/test/timeout.html +++ b/test/timeout.html @@ -1,9 +1,15 @@ + Tests Start Timeout + + + + + diff --git a/test/user-agent.html b/test/user-agent.html index 4db6a3a..b6844c5 100644 --- a/test/user-agent.html +++ b/test/user-agent.html @@ -1,3 +1,4 @@ + Tests UserAgent @@ -13,11 +14,7 @@ diff --git a/test/viewport.html b/test/viewport.html index 73f6301..4f19a5d 100644 --- a/test/viewport.html +++ b/test/viewport.html @@ -1,3 +1,4 @@ + Tests Viewport @@ -13,11 +14,7 @@