added unit testing, and started implementing unit tests...phew
This commit is contained in:
68
node_modules/mocha/lib/cli/cli.js
generated
vendored
Executable file
68
node_modules/mocha/lib/cli/cli.js
generated
vendored
Executable file
@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This is where we finally parse and handle arguments passed to the `mocha` executable.
|
||||
* Option parsing is handled by {@link https://npm.im/yargs yargs}.
|
||||
* If executed via `node`, this module will run {@linkcode module:lib/cli/cli.main main()}.
|
||||
*
|
||||
* @private
|
||||
* @module
|
||||
*/
|
||||
|
||||
const debug = require('debug')('mocha:cli:cli');
|
||||
const symbols = require('log-symbols');
|
||||
const yargs = require('yargs');
|
||||
const path = require('path');
|
||||
const {loadOptions} = require('./options');
|
||||
const commands = require('./commands');
|
||||
const ansi = require('ansi-colors');
|
||||
const {repository, homepage, version, gitter} = require('../../package.json');
|
||||
|
||||
/**
|
||||
* - Accepts an `Array` of arguments
|
||||
* - Modifies {@link https://nodejs.org/api/modules.html#modules_module_paths Node.js' search path} for easy loading of consumer modules
|
||||
* - Sets {@linkcode https://nodejs.org/api/errors.html#errors_error_stacktracelimit Error.stackTraceLimit} to `Infinity`
|
||||
* @summary Mocha's main entry point from the command-line.
|
||||
* @param {string[]} argv - Array of arguments to parse, or by default the lovely `process.argv.slice(2)`
|
||||
*/
|
||||
exports.main = (argv = process.argv.slice(2)) => {
|
||||
debug('entered main with raw args', argv);
|
||||
// ensure we can require() from current working directory
|
||||
module.paths.push(process.cwd(), path.resolve('node_modules'));
|
||||
|
||||
Error.stackTraceLimit = Infinity; // configurable via --stack-trace-limit?
|
||||
|
||||
yargs
|
||||
.scriptName('mocha')
|
||||
.command(commands.run)
|
||||
.command(commands.init)
|
||||
.updateStrings({
|
||||
'Positionals:': 'Positional Arguments',
|
||||
'Options:': 'Other Options',
|
||||
'Commands:': 'Commands'
|
||||
})
|
||||
.fail((msg, err, yargs) => {
|
||||
debug(err);
|
||||
yargs.showHelp();
|
||||
console.error(`\n${symbols.error} ${ansi.red('ERROR:')} ${msg}`);
|
||||
process.exit(1);
|
||||
})
|
||||
.help('help', 'Show usage information & exit')
|
||||
.alias('help', 'h')
|
||||
.version('version', 'Show version number & exit', version)
|
||||
.alias('version', 'V')
|
||||
.wrap(process.stdout.columns ? Math.min(process.stdout.columns, 80) : 80)
|
||||
.epilog(
|
||||
`Mocha Resources
|
||||
Chat: ${ansi.magenta(gitter)}
|
||||
GitHub: ${ansi.blue(repository.url)}
|
||||
Docs: ${ansi.yellow(homepage)}
|
||||
`
|
||||
)
|
||||
.parse(argv, loadOptions(argv));
|
||||
};
|
||||
|
||||
// allow direct execution
|
||||
if (require.main === module) {
|
||||
exports.main();
|
||||
}
|
13
node_modules/mocha/lib/cli/commands.js
generated
vendored
Normal file
13
node_modules/mocha/lib/cli/commands.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Exports Yargs commands
|
||||
* @see https://git.io/fpJ0G
|
||||
* @private
|
||||
* @module
|
||||
*/
|
||||
|
||||
exports.init = require('./init');
|
||||
|
||||
// default command
|
||||
exports.run = require('./run');
|
79
node_modules/mocha/lib/cli/config.js
generated
vendored
Normal file
79
node_modules/mocha/lib/cli/config.js
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Responsible for loading / finding Mocha's "rc" files.
|
||||
* This doesn't have anything to do with `mocha.opts`.
|
||||
*
|
||||
* @private
|
||||
* @module
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const findUp = require('findup-sync');
|
||||
const path = require('path');
|
||||
const debug = require('debug')('mocha:cli:config');
|
||||
|
||||
/**
|
||||
* These are the valid config files, in order of precedence;
|
||||
* e.g., if `.mocharc.js` is present, then `.mocharc.yaml` and the rest
|
||||
* will be ignored.
|
||||
* The user should still be able to explicitly specify a file.
|
||||
* @private
|
||||
*/
|
||||
exports.CONFIG_FILES = [
|
||||
'.mocharc.js',
|
||||
'.mocharc.yaml',
|
||||
'.mocharc.yml',
|
||||
'.mocharc.json'
|
||||
];
|
||||
|
||||
/**
|
||||
* Parsers for various config filetypes. Each accepts a filepath and
|
||||
* returns an object (but could throw)
|
||||
*/
|
||||
const parsers = (exports.parsers = {
|
||||
yaml: filepath =>
|
||||
require('js-yaml').safeLoad(fs.readFileSync(filepath, 'utf8')),
|
||||
js: filepath => require(filepath),
|
||||
json: filepath =>
|
||||
JSON.parse(
|
||||
require('strip-json-comments')(fs.readFileSync(filepath, 'utf8'))
|
||||
)
|
||||
});
|
||||
|
||||
/**
|
||||
* Loads and parses, based on file extension, a config file.
|
||||
* "JSON" files may have comments.
|
||||
* @param {string} filepath - Config file path to load
|
||||
* @returns {Object} Parsed config object
|
||||
* @private
|
||||
*/
|
||||
exports.loadConfig = filepath => {
|
||||
let config = {};
|
||||
const ext = path.extname(filepath);
|
||||
try {
|
||||
if (/\.ya?ml/.test(ext)) {
|
||||
config = parsers.yaml(filepath);
|
||||
} else if (ext === '.js') {
|
||||
config = parsers.js(filepath);
|
||||
} else {
|
||||
config = parsers.json(filepath);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`failed to parse ${filepath}: ${err}`);
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find ("find up") config file starting at `cwd`
|
||||
* @param {string} [cwd] - Current working directory
|
||||
* @returns {string|null} Filepath to config, if found
|
||||
*/
|
||||
exports.findConfig = (cwd = process.cwd()) => {
|
||||
const filepath = findUp(exports.CONFIG_FILES, {cwd});
|
||||
if (filepath) {
|
||||
debug(`found config at ${filepath}`);
|
||||
}
|
||||
return filepath;
|
||||
};
|
9
node_modules/mocha/lib/cli/index.js
generated
vendored
Normal file
9
node_modules/mocha/lib/cli/index.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Just exports {@link module:lib/cli/cli} for convenience.
|
||||
* @private
|
||||
* @module lib/cli
|
||||
* @exports module:lib/cli/cli
|
||||
*/
|
||||
module.exports = require('./cli');
|
37
node_modules/mocha/lib/cli/init.js
generated
vendored
Normal file
37
node_modules/mocha/lib/cli/init.js
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Command module for "init" command
|
||||
*
|
||||
* @private
|
||||
* @module
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
|
||||
exports.command = 'init <path>';
|
||||
|
||||
exports.description = 'create a client-side Mocha setup at <path>';
|
||||
|
||||
exports.builder = yargs =>
|
||||
yargs.positional('path', {
|
||||
type: 'string',
|
||||
normalize: true
|
||||
});
|
||||
|
||||
exports.handler = argv => {
|
||||
const destdir = argv.path;
|
||||
const srcdir = path.join(__dirname, '..', '..');
|
||||
mkdirp.sync(destdir);
|
||||
const css = fs.readFileSync(path.join(srcdir, 'mocha.css'));
|
||||
const js = fs.readFileSync(path.join(srcdir, 'mocha.js'));
|
||||
const tmpl = fs.readFileSync(
|
||||
path.join(srcdir, 'lib', 'browser', 'template.html')
|
||||
);
|
||||
fs.writeFileSync(path.join(destdir, 'mocha.css'), css);
|
||||
fs.writeFileSync(path.join(destdir, 'mocha.js'), js);
|
||||
fs.writeFileSync(path.join(destdir, 'tests.spec.js'), '');
|
||||
fs.writeFileSync(path.join(destdir, 'index.html'), tmpl);
|
||||
};
|
85
node_modules/mocha/lib/cli/node-flags.js
generated
vendored
Normal file
85
node_modules/mocha/lib/cli/node-flags.js
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Some settings and code related to Mocha's handling of Node.js/V8 flags.
|
||||
* @private
|
||||
* @module
|
||||
*/
|
||||
|
||||
const nodeFlags = require('node-environment-flags');
|
||||
const unparse = require('yargs-unparser');
|
||||
|
||||
/**
|
||||
* These flags are considered "debug" flags.
|
||||
* @see {@link impliesNoTimeouts}
|
||||
* @private
|
||||
*/
|
||||
const debugFlags = new Set(['debug', 'debug-brk', 'inspect', 'inspect-brk']);
|
||||
|
||||
/**
|
||||
* Mocha has historical support for various `node` and V8 flags which might not
|
||||
* appear in `process.allowedNodeEnvironmentFlags`.
|
||||
* These include:
|
||||
* - `--preserve-symlinks`
|
||||
* - `--harmony-*`
|
||||
* - `--gc-global`
|
||||
* - `--trace-*`
|
||||
* - `--es-staging`
|
||||
* - `--use-strict`
|
||||
* - `--v8-*` (but *not* `--v8-options`)
|
||||
* @summary Whether or not to pass a flag along to the `node` executable.
|
||||
* @param {string} flag - Flag to test
|
||||
* @param {boolean} [bareword=true] - If `false`, we expect `flag` to have one or two leading dashes.
|
||||
* @returns {boolean} If the flag is considered a "Node" flag.
|
||||
* @private
|
||||
*/
|
||||
exports.isNodeFlag = (flag, bareword = true) => {
|
||||
if (!bareword) {
|
||||
// check if the flag begins with dashes; if not, not a node flag.
|
||||
if (!/^--?/.test(flag)) {
|
||||
return false;
|
||||
}
|
||||
// strip the leading dashes to match against subsequent checks
|
||||
flag = flag.replace(/^--?/, '');
|
||||
}
|
||||
return (
|
||||
// treat --require/-r as Mocha flag even though it's also a node flag
|
||||
!(flag === 'require' || flag === 'r') &&
|
||||
// check actual node flags from `process.allowedNodeEnvironmentFlags`,
|
||||
// then historical support for various V8 and non-`NODE_OPTIONS` flags
|
||||
// and also any V8 flags with `--v8-` prefix
|
||||
(nodeFlags.has(flag) ||
|
||||
debugFlags.has(flag) ||
|
||||
/(?:preserve-symlinks(?:-main)?|harmony(?:[_-]|$)|(?:trace[_-].+$)|gc(?:[_-]global)?$|es[_-]staging$|use[_-]strict$|v8[_-](?!options).+?$)/.test(
|
||||
flag
|
||||
))
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns `true` if the flag is a "debug-like" flag. These require timeouts
|
||||
* to be suppressed, or pausing the debugger on breakpoints will cause test failures.
|
||||
* @param {string} flag - Flag to test
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
exports.impliesNoTimeouts = flag => debugFlags.has(flag);
|
||||
|
||||
/**
|
||||
* All non-strictly-boolean arguments to node--those with values--must specify those values using `=`, e.g., `--inspect=0.0.0.0`.
|
||||
* Unparse these arguments using `yargs-unparser` (which would result in `--inspect 0.0.0.0`), then supply `=` where we have values.
|
||||
* There's probably an easier or more robust way to do this; fixes welcome
|
||||
* @param {Object} opts - Arguments object
|
||||
* @returns {string[]} Unparsed arguments using `=` to specify values
|
||||
* @private
|
||||
*/
|
||||
exports.unparseNodeFlags = opts => {
|
||||
var args = unparse(opts);
|
||||
return args.length
|
||||
? args
|
||||
.join(' ')
|
||||
.split(/\b/)
|
||||
.map(arg => (arg === ' ' ? '=' : arg))
|
||||
.join('')
|
||||
: [];
|
||||
};
|
70
node_modules/mocha/lib/cli/one-and-dones.js
generated
vendored
Normal file
70
node_modules/mocha/lib/cli/one-and-dones.js
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Contains "command" code for "one-and-dones"--options passed
|
||||
* to Mocha which cause it to just dump some info and exit.
|
||||
* See {@link module:lib/cli/one-and-dones.ONE_AND_DONE_ARGS ONE_AND_DONE_ARGS} for more info.
|
||||
* @module
|
||||
* @private
|
||||
*/
|
||||
|
||||
const align = require('wide-align');
|
||||
const Mocha = require('../mocha');
|
||||
|
||||
/**
|
||||
* Dumps a sorted list of the enumerable, lower-case keys of some object
|
||||
* to `STDOUT`.
|
||||
* @param {Object} obj - Object, ostensibly having some enumerable keys
|
||||
* @ignore
|
||||
* @private
|
||||
*/
|
||||
const showKeys = obj => {
|
||||
console.log();
|
||||
const keys = Object.keys(obj);
|
||||
const maxKeyLength = keys.reduce((max, key) => Math.max(max, key.length), 0);
|
||||
keys
|
||||
.filter(
|
||||
key => /^[a-z]/.test(key) && !obj[key].browserOnly && !obj[key].abstract
|
||||
)
|
||||
.sort()
|
||||
.forEach(key => {
|
||||
const description = obj[key].description;
|
||||
console.log(
|
||||
` ${align.left(key, maxKeyLength + 1)}${
|
||||
description ? `- ${description}` : ''
|
||||
}`
|
||||
);
|
||||
});
|
||||
console.log();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handlers for one-and-done options
|
||||
* @namespace
|
||||
* @private
|
||||
*/
|
||||
exports.ONE_AND_DONES = {
|
||||
/**
|
||||
* Dump list of built-in interfaces
|
||||
* @private
|
||||
*/
|
||||
interfaces: () => {
|
||||
showKeys(Mocha.interfaces);
|
||||
},
|
||||
/**
|
||||
* Dump list of built-in reporters
|
||||
* @private
|
||||
*/
|
||||
reporters: () => {
|
||||
showKeys(Mocha.reporters);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A Set of all one-and-done options
|
||||
* @type Set<string>
|
||||
* @private
|
||||
*/
|
||||
exports.ONE_AND_DONE_ARGS = new Set(
|
||||
['help', 'h', 'version', 'V'].concat(Object.keys(exports.ONE_AND_DONES))
|
||||
);
|
337
node_modules/mocha/lib/cli/options.js
generated
vendored
Normal file
337
node_modules/mocha/lib/cli/options.js
generated
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Main entry point for handling filesystem-based configuration,
|
||||
* whether that's `mocha.opts` or a config file or `package.json` or whatever.
|
||||
* @module
|
||||
*/
|
||||
|
||||
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');
|
||||
const mocharc = require('../mocharc.json');
|
||||
const yargsParserConfig = require('../../package.json').yargs;
|
||||
const {list} = require('./run-helpers');
|
||||
const {loadConfig, findConfig} = require('./config');
|
||||
const findup = require('findup-sync');
|
||||
const {deprecate} = require('../utils');
|
||||
const debug = require('debug')('mocha:cli:options');
|
||||
const {createMissingArgumentError} = require('../errors');
|
||||
const {isNodeFlag} = require('./node-flags');
|
||||
|
||||
/**
|
||||
* The `yargs-parser` namespace
|
||||
* @external yargsParser
|
||||
* @see {@link https://npm.im/yargs-parser}
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object returned by a configured `yargs-parser` representing arguments
|
||||
* @memberof external:yargsParser
|
||||
* @interface Arguments
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the config pulled from the `yargs` property of Mocha's
|
||||
* `package.json`, but it also disables camel case expansion as to
|
||||
* avoid outputting non-canonical keynames, as we need to do some
|
||||
* lookups.
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
const configuration = Object.assign({}, yargsParserConfig, {
|
||||
'camel-case-expansion': false
|
||||
});
|
||||
|
||||
/**
|
||||
* This is a really fancy way to ensure unique values for `array`-type
|
||||
* options.
|
||||
* This is passed as the `coerce` option to `yargs-parser`
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
const coerceOpts = types.array.reduce(
|
||||
(acc, arg) => Object.assign(acc, {[arg]: v => Array.from(new Set(list(v)))}),
|
||||
{}
|
||||
);
|
||||
|
||||
/**
|
||||
* We do not have a case when multiple arguments are ever allowed after a flag
|
||||
* (e.g., `--foo bar baz quux`), so we fix the number of arguments to 1 across
|
||||
* the board of non-boolean options.
|
||||
* This is passed as the `narg` option to `yargs-parser`
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
const nargOpts = types.array
|
||||
.concat(types.string, types.number)
|
||||
.reduce((acc, arg) => Object.assign(acc, {[arg]: 1}), {});
|
||||
|
||||
/**
|
||||
* Wrapper around `yargs-parser` which applies our settings
|
||||
* @param {string|string[]} args - Arguments to parse
|
||||
* @param {...Object} configObjects - `configObjects` for yargs-parser
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
const parse = (args = [], ...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
|
||||
// 3. to avoid explicitly defining the set of them, we tell yargs-parser they
|
||||
// are ALL boolean flags.
|
||||
// 4. we can then reapply the values after yargs-parser is done.
|
||||
const nodeArgs = (Array.isArray(args) ? args : args.split(' ')).reduce(
|
||||
(acc, arg) => {
|
||||
const pair = arg.split('=');
|
||||
let flag = pair[0];
|
||||
if (isNodeFlag(flag, false)) {
|
||||
flag = flag.replace(/^--?/, '');
|
||||
return arg.includes('=')
|
||||
? acc.concat([[flag, pair[1]]])
|
||||
: acc.concat([[flag, true]]);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const result = yargsParser.detailed(args, {
|
||||
configuration,
|
||||
configObjects,
|
||||
coerce: coerceOpts,
|
||||
narg: nargOpts,
|
||||
alias: aliases,
|
||||
string: types.string,
|
||||
array: types.array,
|
||||
number: types.number,
|
||||
boolean: types.boolean.concat(nodeArgs.map(pair => pair[0]))
|
||||
});
|
||||
if (result.error) {
|
||||
throw createMissingArgumentError(result.error.message);
|
||||
}
|
||||
|
||||
// reapply "=" arg values from above
|
||||
nodeArgs.forEach(([key, value]) => {
|
||||
result.argv[key] = value;
|
||||
});
|
||||
|
||||
return result.argv;
|
||||
};
|
||||
|
||||
/**
|
||||
* - Replaces comments with empty strings
|
||||
* - Replaces escaped spaces (e.g., 'xxx\ yyy') with HTML space
|
||||
* - Splits on whitespace, creating array of substrings
|
||||
* - Filters empty string elements from array
|
||||
* - Replaces any HTML space with space
|
||||
* @summary Parses options read from run-control file.
|
||||
* @private
|
||||
* @param {string} content - Content read from run-control file.
|
||||
* @returns {string[]} cmdline options (and associated arguments)
|
||||
* @ignore
|
||||
*/
|
||||
const parseMochaOpts = content =>
|
||||
content
|
||||
.replace(/^#.*$/gm, '')
|
||||
.replace(/\\\s/g, '%20')
|
||||
.split(/\s/)
|
||||
.filter(Boolean)
|
||||
.map(value => value.replace(/%20/g, ' '));
|
||||
|
||||
/**
|
||||
* Prepends options from run-control file to the command line arguments.
|
||||
*
|
||||
* @deprecated Deprecated in v6.0.0; This function is no longer used internally and will be removed in a future version.
|
||||
* @public
|
||||
* @alias module:lib/cli/options
|
||||
* @see {@link https://mochajs.org/#mochaopts|mocha.opts}
|
||||
*/
|
||||
module.exports = function getOptions() {
|
||||
deprecate(
|
||||
'getOptions() is DEPRECATED and will be removed from a future version of Mocha. Use loadOptions() instead'
|
||||
);
|
||||
if (process.argv.length === 3 && ONE_AND_DONE_ARGS.has(process.argv[2])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const optsPath =
|
||||
process.argv.indexOf('--opts') === -1
|
||||
? mocharc.opts
|
||||
: process.argv[process.argv.indexOf('--opts') + 1];
|
||||
|
||||
try {
|
||||
const options = parseMochaOpts(fs.readFileSync(optsPath, 'utf8'));
|
||||
|
||||
process.argv = process.argv
|
||||
.slice(0, 2)
|
||||
.concat(options.concat(process.argv.slice(2)));
|
||||
} catch (ignore) {
|
||||
// NOTE: should console.error() and throw the error
|
||||
}
|
||||
|
||||
process.env.LOADED_MOCHA_OPTS = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given filepath in `args.opts`, attempt to load and parse a `mocha.opts` file.
|
||||
* @param {Object} [args] - Arguments object
|
||||
* @param {string|boolean} [args.opts] - Filepath to mocha.opts; defaults to whatever's in `mocharc.opts`, or `false` to skip
|
||||
* @returns {external:yargsParser.Arguments|void} If read, object containing parsed arguments
|
||||
* @memberof module:lib/cli/options
|
||||
* @public
|
||||
*/
|
||||
const loadMochaOpts = (args = {}) => {
|
||||
let result;
|
||||
let filepath = args.opts;
|
||||
// /dev/null is backwards compat
|
||||
if (filepath === false || filepath === '/dev/null') {
|
||||
return result;
|
||||
}
|
||||
filepath = filepath || mocharc.opts;
|
||||
result = {};
|
||||
let mochaOpts;
|
||||
try {
|
||||
mochaOpts = fs.readFileSync(filepath, 'utf8');
|
||||
debug(`read ${filepath}`);
|
||||
} catch (err) {
|
||||
if (args.opts) {
|
||||
throw new Error(`Unable to read ${filepath}: ${err}`);
|
||||
}
|
||||
// ignore otherwise. we tried
|
||||
debug(`No mocha.opts found at ${filepath}`);
|
||||
}
|
||||
|
||||
// real args should override `mocha.opts` which should override defaults.
|
||||
// if there's an exception to catch here, I'm not sure what it is.
|
||||
// by attaching the `no-opts` arg, we avoid re-parsing of `mocha.opts`.
|
||||
if (mochaOpts) {
|
||||
result = parse(parseMochaOpts(mochaOpts));
|
||||
debug(`${filepath} parsed succesfully`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports.loadMochaOpts = loadMochaOpts;
|
||||
|
||||
/**
|
||||
* Given path to config file in `args.config`, attempt to load & parse config file.
|
||||
* @param {Object} [args] - Arguments object
|
||||
* @param {string|boolean} [args.config] - Path to config file or `false` to skip
|
||||
* @public
|
||||
* @memberof module:lib/cli/options
|
||||
* @returns {external:yargsParser.Arguments|void} Parsed config, or nothing if `args.config` is `false`
|
||||
*/
|
||||
const loadRc = (args = {}) => {
|
||||
if (args.config !== false) {
|
||||
const config = args.config || findConfig();
|
||||
return config ? loadConfig(config) : {};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.loadRc = loadRc;
|
||||
|
||||
/**
|
||||
* Given path to `package.json` in `args.package`, attempt to load config from `mocha` prop.
|
||||
* @param {Object} [args] - Arguments object
|
||||
* @param {string|boolean} [args.config] - Path to `package.json` or `false` to skip
|
||||
* @public
|
||||
* @memberof module:lib/cli/options
|
||||
* @returns {external:yargsParser.Arguments|void} Parsed config, or nothing if `args.package` is `false`
|
||||
*/
|
||||
const loadPkgRc = (args = {}) => {
|
||||
let result;
|
||||
if (args.package === false) {
|
||||
return result;
|
||||
}
|
||||
result = {};
|
||||
const filepath = args.package || findup(mocharc.package);
|
||||
if (filepath) {
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
if (pkg.mocha) {
|
||||
debug(`'mocha' prop of package.json parsed:`, pkg.mocha);
|
||||
result = pkg.mocha;
|
||||
} else {
|
||||
debug(`no config found in ${filepath}`);
|
||||
}
|
||||
} catch (err) {
|
||||
if (args.package) {
|
||||
throw new Error(`Unable to read/parse ${filepath}: ${err}`);
|
||||
}
|
||||
debug(`failed to read default package.json at ${filepath}; ignoring`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports.loadPkgRc = loadPkgRc;
|
||||
|
||||
/**
|
||||
* Priority list:
|
||||
*
|
||||
* 1. Command-line args
|
||||
* 2. RC file (`.mocharc.js`, `.mocharc.ya?ml`, `mocharc.json`)
|
||||
* 3. `mocha` prop of `package.json`
|
||||
* 4. `mocha.opts`
|
||||
* 5. default configuration (`lib/mocharc.json`)
|
||||
*
|
||||
* If a {@link module:lib/cli/one-and-dones.ONE_AND_DONE_ARGS "one-and-done" option} is present in the `argv` array, no external config files will be read.
|
||||
* @summary Parses options read from `mocha.opts`, `.mocharc.*` and `package.json`.
|
||||
* @param {string|string[]} [argv] - Arguments to parse
|
||||
* @public
|
||||
* @memberof module:lib/cli/options
|
||||
* @returns {external:yargsParser.Arguments} Parsed args from everything
|
||||
*/
|
||||
const loadOptions = (argv = []) => {
|
||||
let args = parse(argv);
|
||||
// short-circuit: look for a flag that would abort loading of mocha.opts
|
||||
if (
|
||||
Array.from(ONE_AND_DONE_ARGS).reduce(
|
||||
(acc, arg) => acc || arg in args,
|
||||
false
|
||||
)
|
||||
) {
|
||||
return args;
|
||||
}
|
||||
|
||||
const rcConfig = loadRc(args);
|
||||
const pkgConfig = loadPkgRc(args);
|
||||
const optsConfig = loadMochaOpts(args);
|
||||
|
||||
if (rcConfig) {
|
||||
args.config = false;
|
||||
args._ = args._.concat(rcConfig._ || []);
|
||||
}
|
||||
if (pkgConfig) {
|
||||
args.package = false;
|
||||
args._ = args._.concat(pkgConfig._ || []);
|
||||
}
|
||||
if (optsConfig) {
|
||||
args.opts = false;
|
||||
args._ = args._.concat(optsConfig._ || []);
|
||||
}
|
||||
|
||||
args = parse(
|
||||
args._,
|
||||
args,
|
||||
rcConfig || {},
|
||||
pkgConfig || {},
|
||||
optsConfig || {},
|
||||
mocharc
|
||||
);
|
||||
|
||||
// recombine positional arguments and "spec"
|
||||
if (args.spec) {
|
||||
args._ = args._.concat(args.spec);
|
||||
delete args.spec;
|
||||
}
|
||||
|
||||
// make unique
|
||||
args._ = Array.from(new Set(args._));
|
||||
|
||||
return args;
|
||||
};
|
||||
|
||||
module.exports.loadOptions = loadOptions;
|
337
node_modules/mocha/lib/cli/run-helpers.js
generated
vendored
Normal file
337
node_modules/mocha/lib/cli/run-helpers.js
generated
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Helper scripts for the `run` command
|
||||
* @see module:lib/cli/run
|
||||
* @module
|
||||
* @private
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const ansi = require('ansi-colors');
|
||||
const debug = require('debug')('mocha:cli:run:helpers');
|
||||
const minimatch = require('minimatch');
|
||||
const Context = require('../context');
|
||||
const Mocha = require('../mocha');
|
||||
const utils = require('../utils');
|
||||
|
||||
const cwd = (exports.cwd = process.cwd());
|
||||
|
||||
/**
|
||||
* Exits Mocha when tests + code under test has finished execution (default)
|
||||
* @param {number} code - Exit code; typically # of failures
|
||||
* @ignore
|
||||
* @private
|
||||
*/
|
||||
const exitMochaLater = code => {
|
||||
process.on('exit', () => {
|
||||
process.exitCode = Math.min(code, 255);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Exits Mocha when Mocha itself has finished execution, regardless of
|
||||
* what the tests or code under test is doing.
|
||||
* @param {number} code - Exit code; typically # of failures
|
||||
* @ignore
|
||||
* @private
|
||||
*/
|
||||
const exitMocha = code => {
|
||||
const clampedCode = Math.min(code, 255);
|
||||
let draining = 0;
|
||||
|
||||
// Eagerly set the process's exit code in case stream.write doesn't
|
||||
// execute its callback before the process terminates.
|
||||
process.exitCode = clampedCode;
|
||||
|
||||
// flush output for Node.js Windows pipe bug
|
||||
// https://github.com/joyent/node/issues/6247 is just one bug example
|
||||
// https://github.com/visionmedia/mocha/issues/333 has a good discussion
|
||||
const done = () => {
|
||||
if (!draining--) {
|
||||
process.exit(clampedCode);
|
||||
}
|
||||
};
|
||||
|
||||
const streams = [process.stdout, process.stderr];
|
||||
|
||||
streams.forEach(stream => {
|
||||
// submit empty write request and wait for completion
|
||||
draining += 1;
|
||||
stream.write('', done);
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the cursor.
|
||||
* @ignore
|
||||
* @private
|
||||
*/
|
||||
const hideCursor = () => {
|
||||
process.stdout.write('\u001b[?25l');
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the cursor.
|
||||
* @ignore
|
||||
* @private
|
||||
*/
|
||||
const showCursor = () => {
|
||||
process.stdout.write('\u001b[?25h');
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop cursor business
|
||||
* @private
|
||||
*/
|
||||
const stop = () => {
|
||||
process.stdout.write('\u001b[2K');
|
||||
};
|
||||
|
||||
/**
|
||||
* Coerce a comma-delimited string (or array thereof) into a flattened array of
|
||||
* strings
|
||||
* @param {string|string[]} str - Value to coerce
|
||||
* @returns {string[]} Array of strings
|
||||
* @private
|
||||
*/
|
||||
exports.list = str =>
|
||||
Array.isArray(str) ? exports.list(str.join(',')) : str.split(/ *, */);
|
||||
|
||||
/**
|
||||
* `require()` the modules as required by `--require <require>`
|
||||
* @param {string[]} requires - Modules to require
|
||||
* @private
|
||||
*/
|
||||
exports.handleRequires = (requires = []) => {
|
||||
requires.forEach(mod => {
|
||||
let modpath = mod;
|
||||
if (fs.existsSync(mod, {cwd}) || fs.existsSync(`${mod}.js`, {cwd})) {
|
||||
modpath = path.resolve(mod);
|
||||
debug(`resolved ${mod} to ${modpath}`);
|
||||
}
|
||||
require(modpath);
|
||||
debug(`loaded require "${mod}"`);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Smash together an array of test files in the correct order
|
||||
* @param {Object} [opts] - Options
|
||||
* @param {string[]} [opts.extension] - File extensions to use
|
||||
* @param {string[]} [opts.spec] - Files, dirs, globs to run
|
||||
* @param {string[]} [opts.exclude] - Files, dirs, globs to exclude
|
||||
* @param {boolean} [opts.recursive=false] - Find files recursively
|
||||
* @param {boolean} [opts.sort=false] - Sort test files
|
||||
* @returns {string[]} List of files to test
|
||||
* @private
|
||||
*/
|
||||
exports.handleFiles = ({
|
||||
exclude = [],
|
||||
extension = [],
|
||||
file = [],
|
||||
recursive = false,
|
||||
sort = false,
|
||||
spec = []
|
||||
} = {}) => {
|
||||
let files = [];
|
||||
const unmatched = [];
|
||||
spec.forEach(arg => {
|
||||
let newFiles;
|
||||
try {
|
||||
newFiles = utils.lookupFiles(arg, extension, recursive);
|
||||
} catch (err) {
|
||||
if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') {
|
||||
unmatched.push({message: err.message, pattern: err.pattern});
|
||||
return;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (typeof newFiles !== 'undefined') {
|
||||
if (typeof newFiles === 'string') {
|
||||
newFiles = [newFiles];
|
||||
}
|
||||
newFiles = newFiles.filter(fileName =>
|
||||
exclude.every(pattern => !minimatch(fileName, pattern))
|
||||
);
|
||||
}
|
||||
|
||||
files = files.concat(newFiles);
|
||||
});
|
||||
|
||||
if (!files.length) {
|
||||
// give full message details when only 1 file is missing
|
||||
const noneFoundMsg =
|
||||
unmatched.length === 1
|
||||
? `Error: No test files found: ${JSON.stringify(unmatched[0].pattern)}` // stringify to print escaped characters raw
|
||||
: 'Error: No test files found';
|
||||
console.error(ansi.red(noneFoundMsg));
|
||||
process.exit(1);
|
||||
} else {
|
||||
// print messages as an warning
|
||||
unmatched.forEach(warning => {
|
||||
console.warn(ansi.yellow(`Warning: ${warning.message}`));
|
||||
});
|
||||
}
|
||||
|
||||
const fileArgs = file.map(filepath => path.resolve(filepath));
|
||||
files = files.map(filepath => path.resolve(filepath));
|
||||
|
||||
// ensure we don't sort the stuff from fileArgs; order is important!
|
||||
if (sort) {
|
||||
files.sort();
|
||||
}
|
||||
|
||||
// add files given through --file to be ran first
|
||||
files = fileArgs.concat(files);
|
||||
debug('files (in order): ', files);
|
||||
return files;
|
||||
};
|
||||
|
||||
/**
|
||||
* Give Mocha files and tell it to run
|
||||
* @param {Mocha} mocha - Mocha instance
|
||||
* @param {Options} [opts] - Options
|
||||
* @param {string[]} [opts.files] - List of test files
|
||||
* @param {boolean} [opts.exit] - Whether or not to force-exit after tests are complete
|
||||
* @returns {Runner}
|
||||
* @private
|
||||
*/
|
||||
exports.singleRun = (mocha, {files = [], exit = false} = {}) => {
|
||||
mocha.files = files;
|
||||
return mocha.run(exit ? exitMocha : exitMochaLater);
|
||||
};
|
||||
|
||||
/**
|
||||
* Run Mocha in "watch" mode
|
||||
* @param {Mocha} mocha - Mocha instance
|
||||
* @param {Object} [opts] - Options
|
||||
* @param {string[]} [opts.extension] - List of extensions to watch
|
||||
* @param {string|RegExp} [opts.grep] - Grep for test titles
|
||||
* @param {string} [opts.ui=bdd] - User interface
|
||||
* @param {string[]} [files] - Array of test files
|
||||
* @private
|
||||
*/
|
||||
exports.watchRun = (
|
||||
mocha,
|
||||
{extension = ['js'], grep = '', ui = 'bdd', files = []} = {}
|
||||
) => {
|
||||
let runner;
|
||||
|
||||
console.log();
|
||||
hideCursor();
|
||||
process.on('SIGINT', () => {
|
||||
showCursor();
|
||||
console.log('\n');
|
||||
process.exit(130);
|
||||
});
|
||||
|
||||
const watchFiles = utils.files(cwd, extension);
|
||||
let runAgain = false;
|
||||
|
||||
const loadAndRun = () => {
|
||||
try {
|
||||
mocha.files = files;
|
||||
runAgain = false;
|
||||
runner = mocha.run(() => {
|
||||
runner = null;
|
||||
if (runAgain) {
|
||||
rerun();
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.stack);
|
||||
}
|
||||
};
|
||||
|
||||
const purge = () => {
|
||||
watchFiles.forEach(Mocha.unloadFile);
|
||||
};
|
||||
|
||||
loadAndRun();
|
||||
|
||||
const rerun = () => {
|
||||
purge();
|
||||
stop();
|
||||
if (!grep) {
|
||||
mocha.grep(null);
|
||||
}
|
||||
mocha.suite = mocha.suite.clone();
|
||||
mocha.suite.ctx = new Context();
|
||||
mocha.ui(ui);
|
||||
loadAndRun();
|
||||
};
|
||||
|
||||
utils.watch(watchFiles, () => {
|
||||
runAgain = true;
|
||||
if (runner) {
|
||||
runner.abort();
|
||||
} else {
|
||||
rerun();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Actually run tests
|
||||
* @param {Mocha} mocha - Mocha instance
|
||||
* @param {Object} [opts] - Options
|
||||
* @param {boolean} [opts.watch=false] - Enable watch mode
|
||||
* @param {string[]} [opts.extension] - List of extensions to watch
|
||||
* @param {string|RegExp} [opts.grep] - Grep for test titles
|
||||
* @param {string} [opts.ui=bdd] - User interface
|
||||
* @param {boolean} [opts.exit=false] - Force-exit Mocha when tests done
|
||||
* @param {string[]} [files] - Array of test files
|
||||
* @private
|
||||
*/
|
||||
exports.runMocha = (
|
||||
mocha,
|
||||
{watch = false, extension = ['js'], grep = '', ui = 'bdd', exit = false} = {},
|
||||
files = []
|
||||
) => {
|
||||
if (watch) {
|
||||
exports.watchRun(mocha, {extension, grep, ui, files});
|
||||
} else {
|
||||
exports.singleRun(mocha, {files, exit});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for `--reporter` and `--ui`. Ensures there's only one, and asserts
|
||||
* that it actually exists.
|
||||
* @todo XXX This must get run after requires are processed, as it'll prevent
|
||||
* interfaces from loading.
|
||||
* @param {Object} opts - Options object
|
||||
* @param {string} key - Resolvable module name or path
|
||||
* @param {Object} [map] - An object perhaps having key `key`
|
||||
* @private
|
||||
*/
|
||||
exports.validatePlugin = (opts, key, map = {}) => {
|
||||
if (Array.isArray(opts[key])) {
|
||||
throw new TypeError(`"--${key} <${key}>" can only be specified once`);
|
||||
}
|
||||
|
||||
const unknownError = () => new Error(`Unknown "${key}": ${opts[key]}`);
|
||||
|
||||
if (!map[opts[key]]) {
|
||||
try {
|
||||
opts[key] = require(opts[key]);
|
||||
} catch (err) {
|
||||
if (err.code === 'MODULE_NOT_FOUND') {
|
||||
// Try to load reporters from a path (absolute or relative)
|
||||
try {
|
||||
opts[key] = require(path.resolve(process.cwd(), opts[key]));
|
||||
} catch (err) {
|
||||
throw unknownError();
|
||||
}
|
||||
} else {
|
||||
throw unknownError();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
76
node_modules/mocha/lib/cli/run-option-metadata.js
generated
vendored
Normal file
76
node_modules/mocha/lib/cli/run-option-metadata.js
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Metadata about various options of the `run` command
|
||||
* @see module:lib/cli/run
|
||||
* @module
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dictionary of yargs option types to list of options having said type
|
||||
* @type {{string:string[]}}
|
||||
* @private
|
||||
*/
|
||||
exports.types = {
|
||||
array: [
|
||||
'exclude',
|
||||
'extension',
|
||||
'file',
|
||||
'global',
|
||||
'require',
|
||||
'reporter-option',
|
||||
'spec'
|
||||
],
|
||||
boolean: [
|
||||
'allow-uncaught',
|
||||
'async-only',
|
||||
'bail',
|
||||
'check-leaks',
|
||||
'color',
|
||||
'delay',
|
||||
'diff',
|
||||
'exit',
|
||||
'forbid-only',
|
||||
'forbid-pending',
|
||||
'full-trace',
|
||||
'growl',
|
||||
'inline-diffs',
|
||||
'interfaces',
|
||||
'invert',
|
||||
'no-colors',
|
||||
'recursive',
|
||||
'reporters',
|
||||
'sort',
|
||||
'watch'
|
||||
],
|
||||
number: ['retries', 'slow', 'timeout'],
|
||||
string: ['fgrep', 'grep', 'package', 'reporter', 'ui']
|
||||
};
|
||||
|
||||
/**
|
||||
* Option aliases keyed by canonical option name.
|
||||
* Arrays used to reduce
|
||||
* @type {{string:string[]}}
|
||||
* @private
|
||||
*/
|
||||
exports.aliases = {
|
||||
'async-only': ['A'],
|
||||
bail: ['b'],
|
||||
color: ['c', 'colors'],
|
||||
extension: ['watch-extensions'],
|
||||
fgrep: ['f'],
|
||||
global: ['globals'],
|
||||
grep: ['g'],
|
||||
growl: ['G'],
|
||||
invert: ['i'],
|
||||
'no-colors': ['C'],
|
||||
reporter: ['R'],
|
||||
'reporter-option': ['reporter-options', 'O'],
|
||||
require: ['r'],
|
||||
slow: ['s'],
|
||||
sort: ['S'],
|
||||
timeout: ['t', 'timeouts'],
|
||||
ui: ['u'],
|
||||
watch: ['w']
|
||||
};
|
297
node_modules/mocha/lib/cli/run.js
generated
vendored
Normal file
297
node_modules/mocha/lib/cli/run.js
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Definition for Mocha's default ("run tests") command
|
||||
*
|
||||
* @module
|
||||
* @private
|
||||
*/
|
||||
|
||||
const Mocha = require('../mocha');
|
||||
const {
|
||||
createUnsupportedError,
|
||||
createInvalidArgumentValueError,
|
||||
createMissingArgumentError
|
||||
} = require('../errors');
|
||||
|
||||
const {
|
||||
list,
|
||||
handleFiles,
|
||||
handleRequires,
|
||||
validatePlugin,
|
||||
runMocha
|
||||
} = require('./run-helpers');
|
||||
const {ONE_AND_DONES, ONE_AND_DONE_ARGS} = require('./one-and-dones');
|
||||
const debug = require('debug')('mocha:cli:run');
|
||||
const defaults = require('../mocharc');
|
||||
const {types, aliases} = require('./run-option-metadata');
|
||||
|
||||
/**
|
||||
* Logical option groups
|
||||
* @constant
|
||||
*/
|
||||
const GROUPS = {
|
||||
FILES: 'File Handling',
|
||||
FILTERS: 'Test Filters',
|
||||
NODEJS: 'Node.js & V8',
|
||||
OUTPUT: 'Reporting & Output',
|
||||
RULES: 'Rules & Behavior',
|
||||
CONFIG: 'Configuration'
|
||||
};
|
||||
|
||||
exports.command = ['$0 [spec..]', 'debug [spec..]'];
|
||||
|
||||
exports.describe = 'Run tests with Mocha';
|
||||
|
||||
exports.builder = yargs =>
|
||||
yargs
|
||||
.options({
|
||||
'allow-uncaught': {
|
||||
description: 'Allow uncaught errors to propagate',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
'async-only': {
|
||||
description:
|
||||
'Require all tests to use a callback (async) or return a Promise',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
bail: {
|
||||
description: 'Abort ("bail") after first test failure',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
'check-leaks': {
|
||||
description: 'Check for global variable leaks',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
color: {
|
||||
description: 'Force-enable color output',
|
||||
group: GROUPS.OUTPUT
|
||||
},
|
||||
config: {
|
||||
config: true,
|
||||
defaultDescription: '(nearest rc file)',
|
||||
description: 'Path to config file',
|
||||
group: GROUPS.CONFIG
|
||||
},
|
||||
delay: {
|
||||
description: 'Delay initial execution of root suite',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
diff: {
|
||||
default: true,
|
||||
description: 'Show diff on failure',
|
||||
group: GROUPS.OUTPUT
|
||||
},
|
||||
exclude: {
|
||||
defaultDescription: '(none)',
|
||||
description: 'Ignore file(s) or glob pattern(s)',
|
||||
group: GROUPS.FILES,
|
||||
requiresArg: true
|
||||
},
|
||||
exit: {
|
||||
description: 'Force Mocha to quit after tests complete',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
extension: {
|
||||
default: defaults.extension,
|
||||
defaultDescription: 'js',
|
||||
description: 'File extension(s) to load and/or watch',
|
||||
group: GROUPS.FILES,
|
||||
requiresArg: true,
|
||||
coerce: list
|
||||
},
|
||||
fgrep: {
|
||||
conflicts: 'grep',
|
||||
description: 'Only run tests containing this string',
|
||||
group: GROUPS.FILTERS,
|
||||
requiresArg: true
|
||||
},
|
||||
file: {
|
||||
defaultDescription: '(none)',
|
||||
description:
|
||||
'Specify file(s) to be loaded prior to root suite execution',
|
||||
group: GROUPS.FILES,
|
||||
normalize: true,
|
||||
requiresArg: true
|
||||
},
|
||||
'forbid-only': {
|
||||
description: 'Fail if exclusive test(s) encountered',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
'forbid-pending': {
|
||||
description: 'Fail if pending test(s) encountered',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
'full-trace': {
|
||||
description: 'Display full stack traces',
|
||||
group: GROUPS.OUTPUT
|
||||
},
|
||||
global: {
|
||||
coerce: list,
|
||||
description: 'List of allowed global variables',
|
||||
group: GROUPS.RULES,
|
||||
requiresArg: true
|
||||
},
|
||||
grep: {
|
||||
coerce: value => (!value ? null : value),
|
||||
conflicts: 'fgrep',
|
||||
description: 'Only run tests matching this string or regexp',
|
||||
group: GROUPS.FILTERS,
|
||||
requiresArg: true
|
||||
},
|
||||
growl: {
|
||||
description: 'Enable Growl notifications',
|
||||
group: GROUPS.OUTPUT
|
||||
},
|
||||
'inline-diffs': {
|
||||
description:
|
||||
'Display actual/expected differences inline within each string',
|
||||
group: GROUPS.OUTPUT
|
||||
},
|
||||
interfaces: {
|
||||
conflicts: Array.from(ONE_AND_DONE_ARGS),
|
||||
description: 'List built-in user interfaces & exit'
|
||||
},
|
||||
invert: {
|
||||
description: 'Inverts --grep and --fgrep matches',
|
||||
group: GROUPS.FILTERS
|
||||
},
|
||||
'no-colors': {
|
||||
description: 'Force-disable color output',
|
||||
group: GROUPS.OUTPUT,
|
||||
hidden: true
|
||||
},
|
||||
opts: {
|
||||
default: defaults.opts,
|
||||
description: 'Path to `mocha.opts`',
|
||||
group: GROUPS.CONFIG,
|
||||
normalize: true,
|
||||
requiresArg: true
|
||||
},
|
||||
package: {
|
||||
description: 'Path to package.json for config',
|
||||
group: GROUPS.CONFIG,
|
||||
normalize: true,
|
||||
requiresArg: true
|
||||
},
|
||||
recursive: {
|
||||
description: 'Look for tests in subdirectories',
|
||||
group: GROUPS.FILES
|
||||
},
|
||||
reporter: {
|
||||
default: defaults.reporter,
|
||||
description: 'Specify reporter to use',
|
||||
group: GROUPS.OUTPUT,
|
||||
requiresArg: true
|
||||
},
|
||||
reporters: {
|
||||
conflicts: Array.from(ONE_AND_DONE_ARGS),
|
||||
description: 'List built-in reporters & exit'
|
||||
},
|
||||
'reporter-option': {
|
||||
coerce: opts =>
|
||||
list(opts).reduce((acc, opt) => {
|
||||
const pair = opt.split('=');
|
||||
|
||||
if (pair.length > 2 || !pair.length) {
|
||||
throw createInvalidArgumentValueError(
|
||||
`invalid reporter option '${opt}'`,
|
||||
'--reporter-option',
|
||||
opt,
|
||||
'expected "key=value" format'
|
||||
);
|
||||
}
|
||||
|
||||
acc[pair[0]] = pair.length === 2 ? pair[1] : true;
|
||||
return acc;
|
||||
}, {}),
|
||||
description: 'Reporter-specific options (<k=v,[k1=v1,..]>)',
|
||||
group: GROUPS.OUTPUT,
|
||||
requiresArg: true
|
||||
},
|
||||
require: {
|
||||
defaultDescription: '(none)',
|
||||
description: 'Require module',
|
||||
group: GROUPS.FILES,
|
||||
requiresArg: true
|
||||
},
|
||||
retries: {
|
||||
description: 'Retry failed tests this many times',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
slow: {
|
||||
default: defaults.slow,
|
||||
description: 'Specify "slow" test threshold (in milliseconds)',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
sort: {
|
||||
description: 'Sort test files',
|
||||
group: GROUPS.FILES
|
||||
},
|
||||
timeout: {
|
||||
default: defaults.timeout,
|
||||
description: 'Specify test timeout threshold (in milliseconds)',
|
||||
group: GROUPS.RULES
|
||||
},
|
||||
ui: {
|
||||
default: defaults.ui,
|
||||
description: 'Specify user interface',
|
||||
group: GROUPS.RULES,
|
||||
requiresArg: true
|
||||
},
|
||||
watch: {
|
||||
description: 'Watch files in the current working directory for changes',
|
||||
group: GROUPS.FILES
|
||||
}
|
||||
})
|
||||
.positional('spec', {
|
||||
default: ['test'],
|
||||
description: 'One or more files, directories, or globs to test',
|
||||
type: 'array'
|
||||
})
|
||||
.check(argv => {
|
||||
// "one-and-dones"; let yargs handle help and version
|
||||
Object.keys(ONE_AND_DONES).forEach(opt => {
|
||||
if (argv[opt]) {
|
||||
ONE_AND_DONES[opt].call(null, yargs);
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// yargs.implies() isn't flexible enough to handle this
|
||||
if (argv.invert && !('fgrep' in argv || 'grep' in argv)) {
|
||||
throw createMissingArgumentError(
|
||||
'"--invert" requires one of "--fgrep <str>" or "--grep <regexp>"',
|
||||
'--fgrep|--grep',
|
||||
'string|regexp'
|
||||
);
|
||||
}
|
||||
|
||||
if (argv.compilers) {
|
||||
throw createUnsupportedError(
|
||||
`--compilers is DEPRECATED and no longer supported.
|
||||
See https://git.io/vdcSr for migration information.`
|
||||
);
|
||||
}
|
||||
|
||||
// load requires first, because it can impact "plugin" validation
|
||||
handleRequires(argv.require);
|
||||
validatePlugin(argv, 'reporter', Mocha.reporters);
|
||||
validatePlugin(argv, 'ui', Mocha.interfaces);
|
||||
|
||||
return true;
|
||||
})
|
||||
.array(types.array)
|
||||
.boolean(types.boolean)
|
||||
.string(types.string)
|
||||
.number(types.number)
|
||||
.alias(aliases);
|
||||
|
||||
exports.handler = argv => {
|
||||
debug('post-yargs config', argv);
|
||||
const mocha = new Mocha(argv);
|
||||
const files = handleFiles(argv);
|
||||
|
||||
debug('running tests with files', files);
|
||||
runMocha(mocha, argv, files);
|
||||
};
|
Reference in New Issue
Block a user