From 924e63c3b3f773b9d8233bd0e7f96b7d0ddd23a8 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sat, 12 May 2018 12:17:42 -0500 Subject: [PATCH] fix(cli): Throw error if unable to parse Mocha options file Code now throws an error for any problems (except nonexistent default "test/mocha.opts"). Includes tests. Fixes #3363 Fixes #2576 --- bin/options.js | 42 ++++++++++++++----- .../fixtures/options/opts.fixture.js | 5 +++ test/integration/helpers.js | 2 +- test/integration/options.spec.js | 36 ++++++++++++++++ 4 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 test/integration/fixtures/options/opts.fixture.js diff --git a/bin/options.js b/bin/options.js index 0c27ae5fa9..69dbe64a77 100644 --- a/bin/options.js +++ b/bin/options.js @@ -5,6 +5,7 @@ */ const fs = require('fs'); +const path = require('path'); /** * Export `getOptions`. @@ -13,13 +14,22 @@ const fs = require('fs'); module.exports = getOptions; /** - * Default pathname for run-control file. + * Default test directory. * * @constant * @type {string} * @default */ -const defaultPathname = 'test/mocha.opts'; +const DEFAULT_TEST_DIRECTORY = 'test'; + +/** + * Default filename of run-control file. + * + * @constant + * @type {string} + * @default + */ +const DEFAULT_OPTS_FILENAME = 'mocha.opts'; /** * Reads contents of the run-control file. @@ -69,20 +79,32 @@ function getOptions() { return; } - const optsPath = - process.argv.indexOf('--opts') === -1 - ? defaultPathname - : process.argv[process.argv.indexOf('--opts') + 1]; + const optsIndex = process.argv.indexOf('--opts'); + const optsPathSpecified = optsIndex !== -1; + const defaultOptsPath = path.join( + DEFAULT_TEST_DIRECTORY, + DEFAULT_OPTS_FILENAME + ); + const optsPath = optsPathSpecified + ? process.argv[optsIndex + 1] + : defaultOptsPath; try { const opts = parseOptions(readOptionsFile(optsPath)); + if (opts.length > 0) { process.argv = process.argv .slice(0, 2) .concat(opts.concat(process.argv.slice(2))); - } catch (ignore) { - // NOTE: should console.error() and throw the error + } + } catch (err) { + // Default options file may not exist - rethrow anything else + if (optsPathSpecified || err.code !== 'ENOENT') { + console.error(`failed to load Mocha options file: ${optsPath}`); + throw err; + } + } finally { + // Despite its name, signifies loading was attempted and should not be again + process.env.LOADED_MOCHA_OPTS = '1'; } - - process.env.LOADED_MOCHA_OPTS = true; } diff --git a/test/integration/fixtures/options/opts.fixture.js b/test/integration/fixtures/options/opts.fixture.js new file mode 100644 index 0000000000..359dc1302b --- /dev/null +++ b/test/integration/fixtures/options/opts.fixture.js @@ -0,0 +1,5 @@ +'use strict'; + +describe('opts', function () { + it('should display this spec', function () {}); +}); diff --git a/test/integration/helpers.js b/test/integration/helpers.js index 0c55362046..8d73c247bb 100644 --- a/test/integration/helpers.js +++ b/test/integration/helpers.js @@ -150,7 +150,7 @@ function _spawnMochaWithListeners(args, fn, cwd) { } function resolveFixturePath(fixture) { - return path.join('./test/integration/fixtures', fixture); + return path.join('test', 'integration', 'fixtures', fixture); } function getSummary(res) { diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js index 0088b08ceb..ce68782ffc 100644 --- a/test/integration/options.spec.js +++ b/test/integration/options.spec.js @@ -558,6 +558,42 @@ describe('options', function() { }); }); + describe('--opts', function() { + var testFile = path.join('options', 'opts.fixture.js'); + + it('works despite nonexistent default options file', function(done) { + args = []; + run(testFile, args, function(err, res) { + if (err) { + return done(err); + } + expect(res, 'to have passed').and('to have passed test count', 1); + return done(); + }); + }); + + it('should throw an error due to nonexistent options file', function(done) { + args = ['--opts', 'nosuchoptionsfile', testFile]; + directInvoke( + args, + function(err, res) { + if (err) { + return done(err); + } + expect( + res.output, + 'to contain', + 'failed to load Mocha options file', + 'ENOENT:' + ); + expect(res.code, 'to be', 1); // failed + return done(); + }, + path.join(__dirname, 'fixtures') + ); + }); + }); + describe('--exclude', function() { /* * Runs mocha in {path} with the given args.