123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- '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);
- };
|