diff --git a/lib/cli/options.js b/lib/cli/options.js index 8ca16d88c2..340fb01e86 100644 --- a/lib/cli/options.js +++ b/lib/cli/options.js @@ -10,8 +10,7 @@ const fs = require('fs'); const yargsParser = require('yargs-parser'); const {types, aliases} = require('./run-option-metadata'); const {ONE_AND_DONE_ARGS} = require('./one-and-dones'); -// paranoia -const mocharc = Object.freeze(require('../mocharc.json')); +const mocharc = require('../mocharc.json'); const {list} = require('./run-helpers'); const {loadConfig, findConfig} = require('./config'); const findUp = require('find-up'); @@ -81,11 +80,12 @@ const nargOpts = types.array /** * Wrapper around `yargs-parser` which applies our settings * @param {string|string[]} args - Arguments to parse + * @param {Object} defaultValues - Default values of mocharc.json * @param {...Object} configObjects - `configObjects` for yargs-parser * @private * @ignore */ -const parse = (args = [], ...configObjects) => { +const parse = (args = [], defaultValues = {}, ...configObjects) => { // save node-specific args for special handling. // 1. when these args have a "=" they should be considered to have values // 2. if they don't, they just boolean flags @@ -110,6 +110,7 @@ const parse = (args = [], ...configObjects) => { const result = yargsParser.detailed(args, { configuration, configObjects, + default: defaultValues, coerce: coerceOpts, narg: nargOpts, alias: aliases, @@ -322,38 +323,14 @@ const loadOptions = (argv = []) => { args.opts = false; args._ = args._.concat(optsConfig._ || []); } - // special case: "extension" option should not combine with default value. - // normally we want to combine "array"-type options, and we _do_ with "extension", but only - // within user-defined configuration (args or anything else). - // we must also search through any aliases of "extension" because while the arguments are /// - // normalized by this point, the config file values are not. - // only the "canonical" option name is used in `mocharc`, so we needn't worry about clearing - // multiple options. - // NOTE: as of this writing, "extension" is the only default value which is of an "array" type; - // it's unknown whether the the below strategy should be generalized to any other future - // "array"-type default option. - const processedMocharc = Object.assign({}, mocharc); - if ( - args.extension || - ['extension'] - .concat(aliases.extension) - .some( - opt => - Object.hasOwnProperty(rcConfig, opt) || - Object.hasOwnProperty(pkgConfig, opt) || - Object.hasOwnProperty(optsConfig, opt) - ) - ) { - delete processedMocharc.extension; - } args = parse( args._, + mocharc, args, rcConfig || {}, pkgConfig || {}, - optsConfig || {}, - processedMocharc + optsConfig || {} ); // recombine positional arguments and "spec" diff --git a/lib/cli/run-helpers.js b/lib/cli/run-helpers.js index 732161b146..ed4a96da40 100644 --- a/lib/cli/run-helpers.js +++ b/lib/cli/run-helpers.js @@ -219,7 +219,7 @@ exports.singleRun = (mocha, {files = [], exit = false} = {}) => { */ exports.watchRun = ( mocha, - {extension = ['js'], grep = '', ui = 'bdd', files = []} = {} + {extension = [], grep = '', ui = 'bdd', files = []} = {} ) => { let runner; @@ -291,7 +291,7 @@ exports.watchRun = ( */ exports.runMocha = ( mocha, - {watch = false, extension = ['js'], grep = '', ui = 'bdd', exit = false} = {}, + {watch = false, extension = [], grep = '', ui = 'bdd', exit = false} = {}, files = [] ) => { if (watch) { diff --git a/lib/utils.js b/lib/utils.js index 14c5ce126d..987b6c5adc 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -562,7 +562,6 @@ function isHiddenOnUnix(pathname) { * * @public * @memberof Mocha.utils - * @todo Fix extension handling * @param {string} filepath - Base path to start searching from. * @param {string[]} extensions - File extensions to look for. * @param {boolean} recursive - Whether to recurse into subdirectories. @@ -571,6 +570,7 @@ function isHiddenOnUnix(pathname) { * @throws {TypeError} if `filepath` is directory and `extensions` not provided. */ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) { + extensions = extensions || []; var files = []; var stat; @@ -624,7 +624,7 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) { // ignore error return; } - if (!extensions) { + if (!extensions.length) { throw createMissingArgumentError( util.format( 'Argument %s required when argument %s is a directory', diff --git a/test/integration/file-utils.spec.js b/test/integration/file-utils.spec.js index 3fe030ee46..f09018871b 100644 --- a/test/integration/file-utils.spec.js +++ b/test/integration/file-utils.spec.js @@ -58,7 +58,7 @@ describe('file utils', function() { ex.and('to have length', expectedLength); }); - it('should parse extensions from extnsions parameter', function() { + it('should parse extensions from extensions parameter', function() { var nonJsFile = tmpFile('mocha-utils-text.txt'); fs.writeFileSync(nonJsFile, 'yippy skippy ying yang yow'); @@ -66,9 +66,14 @@ describe('file utils', function() { expect(res, 'to contain', nonJsFile).and('to have length', 1); }); - it('should not require the extensions parameter when looking up a file', function() { - var res = utils.lookupFiles(tmpFile('mocha-utils'), undefined, false); - expect(res, 'to be', tmpFile('mocha-utils.js')); + it('should require the extensions parameter when looking up a file', function() { + var dirLookup = function() { + return utils.lookupFiles(tmpFile('mocha-utils'), undefined, false); + }; + expect(dirLookup, 'to throw', { + name: 'Error', + code: 'ERR_MOCHA_NO_FILES_MATCH_PATTERN' + }); }); it('should require the extensions parameter when looking up a directory', function() {