diff --git a/bin/options.js b/bin/options.js index a25a18e28e..7949d1db28 100644 --- a/bin/options.js +++ b/bin/options.js @@ -5,6 +5,7 @@ */ const fs = require('fs'); +const path = require('path'); /** * Export `getOptions`. @@ -24,10 +25,12 @@ function getOptions() { return; } - const optsPath = - process.argv.indexOf('--opts') === -1 - ? 'test/mocha.opts' - : process.argv[process.argv.indexOf('--opts') + 1]; + const optsIndex = process.argv.indexOf('--opts'); + const optsPathSpecified = optsIndex !== -1; + const defaultOptsPath = path.join('test', 'mocha.opts'); + const optsPath = optsPathSpecified + ? process.argv[optsIndex + 1] + : defaultOptsPath; try { const opts = fs @@ -38,12 +41,19 @@ function getOptions() { .filter(Boolean) .map(value => value.replace(/%20/g, ' ')); - process.argv = process.argv - .slice(0, 2) - .concat(opts.concat(process.argv.slice(2))); - } catch (ignore) { - // NOTE: should console.error() and throw the error + if (opts.length > 0) { + process.argv = process.argv + .slice(0, 2) + .concat(opts.concat(process.argv.slice(2))); + } + } 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..ed1bcff840 --- /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 23722ea43e..13dce1b49d 100644 --- a/test/integration/helpers.js +++ b/test/integration/helpers.js @@ -127,7 +127,7 @@ function invokeMocha(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 25775de615..981951fc25 100644 --- a/test/integration/options.spec.js +++ b/test/integration/options.spec.js @@ -440,6 +440,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.