diff --git a/bin/_mocha b/bin/_mocha index 19cc1c50da..3802e70b79 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -78,6 +78,11 @@ const exit = code => { */ const list = str => str.split(/ *, */); +/** + * Parse multiple flag. + */ +const collect = (val, memo) => memo.concat(val); + /** * Hide the cursor. */ @@ -199,7 +204,8 @@ program .option('--delay', 'wait for async suite definition') .option('--allow-uncaught', 'enable uncaught errors to propagate') .option('--forbid-only', 'causes test marked with only to fail the suite') - .option('--forbid-pending', 'causes pending tests and test marked with skip to fail the suite'); + .option('--forbid-pending', 'causes pending tests and test marked with skip to fail the suite') + .option('--file ', 'include a file to be ran during the suite', collect, []); program._name = 'mocha'; @@ -497,13 +503,16 @@ if (!files.length) { } // resolve - +let fileArgs = program.file.map(path => resolve(path)); files = files.map(path => resolve(path)); if (program.sort) { files.sort(); } +// add files given through --file to be ran first +files = fileArgs.concat(files); + // --watch let runner; diff --git a/docs/index.md b/docs/index.md index 7e59c44ddf..c8709fa2a2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -736,6 +736,7 @@ Mocha supports the `err.expected` and `err.actual` properties of any thrown `Ass --debug-brk enable node's debugger breaking on the first line --globals allow the given comma-delimited global [names] --es_staging enable all staged features + --file include a file to be ran during the suite [file] --harmony<_classes,_generators,...> all node --harmony* flags are available --preserve-symlinks Instructs the module loader to preserve symbolic links when resolving and caching modules --icu-data-dir include ICU data @@ -853,6 +854,10 @@ Disables timeouts. Equivalent to `--timeout 0`. Specify the "slow" test threshold, defaulting to 75ms. Mocha uses this to highlight test-cases that are taking too long. +### `--file ` + +Add a file you want included first in a test suite. This is useful if you have some generic setup code that must be included within the test suite. The file passed is not affected by any other flags (`--recursive` or `--sort` have no effect). Accepts multiple `--file` flags to include multiple files, the order in which the flags are given are the order in which the files are included in the test suite. Can also be used in `mocha.opts`. + ### `-g, --grep ` The `--grep` option when specified will trigger mocha to only run tests matching the given `pattern` which is internally compiled to a `RegExp`. diff --git a/test/integration/fixtures/options/file-alpha.fixture.js b/test/integration/fixtures/options/file-alpha.fixture.js new file mode 100644 index 0000000000..100d49aeb1 --- /dev/null +++ b/test/integration/fixtures/options/file-alpha.fixture.js @@ -0,0 +1,13 @@ +'use strict'; + +describe('alpha', function () { + it('should be executed first', function () { + if (global.beta !== undefined) { + throw new Error('alpha was not executed first'); + } + + if (global.theta !== undefined) { + throw new Error('alpha was not executed first'); + } + }); +}); diff --git a/test/integration/fixtures/options/file-beta.fixture.js b/test/integration/fixtures/options/file-beta.fixture.js new file mode 100644 index 0000000000..ce5dc3c0a8 --- /dev/null +++ b/test/integration/fixtures/options/file-beta.fixture.js @@ -0,0 +1,11 @@ +'use strict'; + +describe('beta', function () { + it('should be executed second', function () { + global.beta = 1; + + if (global.theta !== undefined) { + throw new Error('beta was not executed second'); + } + }); +}); diff --git a/test/integration/fixtures/options/file-theta.fixture.js b/test/integration/fixtures/options/file-theta.fixture.js new file mode 100644 index 0000000000..9d5c7d8c96 --- /dev/null +++ b/test/integration/fixtures/options/file-theta.fixture.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('theta', function () { + it('should be executed third', function () { + global.theta = 1; + }); +}); diff --git a/test/integration/helpers.js b/test/integration/helpers.js index ec50116920..09ca5deac9 100644 --- a/test/integration/helpers.js +++ b/test/integration/helpers.js @@ -129,7 +129,12 @@ module.exports = { * @param {Function} done - Callback * @param {string} cwd - Current working directory for mocha run, optional */ - invokeMocha: invokeMocha + invokeMocha: invokeMocha, + + /** + * Resolves the path to a fixture to the full path. + */ + resolveFixturePath: resolveFixturePath }; function invokeMocha (args, fn, cwd) { diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js index e4ecc96cd6..607af6083b 100644 --- a/test/integration/options.spec.js +++ b/test/integration/options.spec.js @@ -2,8 +2,10 @@ var path = require('path'); var assert = require('assert'); -var run = require('./helpers').runMochaJSON; -var directInvoke = require('./helpers').invokeMocha; +var helpers = require('./helpers'); +var run = helpers.runMochaJSON; +var directInvoke = helpers.invokeMocha; +var resolvePath = helpers.resolveFixturePath; var args = []; describe('options', function () { @@ -91,6 +93,53 @@ describe('options', function () { }); }); + describe('--file', function () { + it('should run tests passed via file first', function (done) { + args = ['--file', resolvePath('options/file-alpha.fixture.js')]; + + run('options/file-beta.fixture.js', args, function (err, res) { + if (err) { + done(err); + return; + } + assert.equal(res.stats.pending, 0); + assert.equal(res.stats.passes, 2); + assert.equal(res.stats.failures, 0); + + assert.equal(res.passes[0].fullTitle, + 'alpha should be executed first'); + assert.equal(res.code, 0); + done(); + }); + }); + + it('should run multiple tests passed via file first', function (done) { + args = [ + '--file', resolvePath('options/file-alpha.fixture.js'), + '--file', resolvePath('options/file-beta.fixture.js') + ]; + + run('options/file-theta.fixture.js', args, function (err, res) { + if (err) { + done(err); + return; + } + assert.equal(res.stats.pending, 0); + assert.equal(res.stats.passes, 3); + assert.equal(res.stats.failures, 0); + + assert.equal(res.passes[0].fullTitle, + 'alpha should be executed first'); + assert.equal(res.passes[1].fullTitle, + 'beta should be executed second'); + assert.equal(res.passes[2].fullTitle, + 'theta should be executed third'); + assert.equal(res.code, 0); + done(); + }); + }); + }); + describe('--delay', function () { before(function () { args = ['--delay'];