mocha 7.2.0 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +116 -0
- package/bin/mocha +17 -2
- package/browser-entry.js +26 -9
- package/lib/browser/growl.js +2 -1
- package/lib/browser/highlight-tags.js +39 -0
- package/lib/browser/parse-query.js +24 -0
- package/lib/browser/progress.js +4 -0
- package/lib/browser/template.html +7 -5
- package/lib/cli/cli.js +2 -2
- package/lib/cli/collect-files.js +15 -9
- package/lib/cli/config.js +0 -1
- package/lib/cli/init.js +1 -2
- package/lib/cli/lookup-files.js +145 -0
- package/lib/cli/node-flags.js +2 -2
- package/lib/cli/options.js +11 -87
- package/lib/cli/run-helpers.js +54 -16
- package/lib/cli/run-option-metadata.js +4 -2
- package/lib/cli/run.js +61 -14
- package/lib/cli/watch-run.js +211 -51
- package/lib/context.js +0 -15
- package/lib/errors.js +26 -3
- package/lib/esm-utils.js +11 -6
- package/lib/hook.js +24 -0
- package/lib/interfaces/common.js +19 -11
- package/lib/mocha.js +137 -121
- package/lib/mocharc.json +0 -1
- package/lib/nodejs/buffered-worker-pool.js +174 -0
- package/lib/{growl.js → nodejs/growl.js} +3 -2
- package/lib/nodejs/parallel-buffered-runner.js +295 -0
- package/lib/nodejs/reporters/parallel-buffered.js +133 -0
- package/lib/nodejs/serializer.js +404 -0
- package/lib/nodejs/worker.js +154 -0
- package/lib/pending.js +4 -0
- package/lib/reporters/base.js +25 -12
- package/lib/reporters/landing.js +3 -3
- package/lib/reporters/tap.js +1 -2
- package/lib/reporters/xunit.js +3 -2
- package/lib/runnable.js +18 -30
- package/lib/runner.js +58 -64
- package/lib/suite.js +32 -24
- package/lib/test.js +28 -1
- package/lib/utils.js +19 -206
- package/mocha.js +25522 -18248
- package/mocha.js.map +1 -0
- package/package.json +52 -42
- package/lib/browser/tty.js +0 -13
package/lib/cli/options.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Main entry point for handling filesystem-based configuration,
|
|
5
|
-
* whether that's
|
|
5
|
+
* whether that's a config file or `package.json` or whatever.
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -15,7 +15,6 @@ const mocharc = require('../mocharc.json');
|
|
|
15
15
|
const {list} = require('./run-helpers');
|
|
16
16
|
const {loadConfig, findConfig} = require('./config');
|
|
17
17
|
const findUp = require('find-up');
|
|
18
|
-
const {deprecate} = require('../utils');
|
|
19
18
|
const debug = require('debug')('mocha:cli:options');
|
|
20
19
|
const {isNodeFlag} = require('./node-flags');
|
|
21
20
|
|
|
@@ -55,16 +54,19 @@ const configuration = Object.assign({}, YARGS_PARSER_CONFIG, {
|
|
|
55
54
|
|
|
56
55
|
/**
|
|
57
56
|
* This is a really fancy way to:
|
|
58
|
-
* - ensure unique values
|
|
59
|
-
* -
|
|
57
|
+
* - `array`-type options: ensure unique values and evtl. split comma-delimited lists
|
|
58
|
+
* - `boolean`/`number`/`string`- options: use last element when given multiple times
|
|
60
59
|
* This is passed as the `coerce` option to `yargs-parser`
|
|
61
60
|
* @private
|
|
62
61
|
* @ignore
|
|
63
62
|
*/
|
|
63
|
+
const globOptions = ['spec', 'ignore'];
|
|
64
64
|
const coerceOpts = Object.assign(
|
|
65
65
|
types.array.reduce(
|
|
66
66
|
(acc, arg) =>
|
|
67
|
-
Object.assign(acc, {
|
|
67
|
+
Object.assign(acc, {
|
|
68
|
+
[arg]: v => Array.from(new Set(globOptions.includes(arg) ? v : list(v)))
|
|
69
|
+
}),
|
|
68
70
|
{}
|
|
69
71
|
),
|
|
70
72
|
types.boolean
|
|
@@ -143,71 +145,6 @@ const parse = (args = [], defaultValues = {}, ...configObjects) => {
|
|
|
143
145
|
return result.argv;
|
|
144
146
|
};
|
|
145
147
|
|
|
146
|
-
/**
|
|
147
|
-
* - Replaces comments with empty strings
|
|
148
|
-
* - Replaces escaped spaces (e.g., 'xxx\ yyy') with HTML space
|
|
149
|
-
* - Splits on whitespace, creating array of substrings
|
|
150
|
-
* - Filters empty string elements from array
|
|
151
|
-
* - Replaces any HTML space with space
|
|
152
|
-
* @summary Parses options read from run-control file.
|
|
153
|
-
* @private
|
|
154
|
-
* @param {string} content - Content read from run-control file.
|
|
155
|
-
* @returns {string[]} cmdline options (and associated arguments)
|
|
156
|
-
* @ignore
|
|
157
|
-
*/
|
|
158
|
-
const parseMochaOpts = content =>
|
|
159
|
-
content
|
|
160
|
-
.replace(/^#.*$/gm, '')
|
|
161
|
-
.replace(/\\\s/g, '%20')
|
|
162
|
-
.split(/\s/)
|
|
163
|
-
.filter(Boolean)
|
|
164
|
-
.map(value => value.replace(/%20/g, ' '));
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Given filepath in `args.opts`, attempt to load and parse a `mocha.opts` file.
|
|
168
|
-
* @param {Object} [args] - Arguments object
|
|
169
|
-
* @param {string|boolean} [args.opts] - Filepath to mocha.opts; defaults to whatever's in `mocharc.opts`, or `false` to skip
|
|
170
|
-
* @returns {external:yargsParser.Arguments|void} If read, object containing parsed arguments
|
|
171
|
-
* @memberof module:lib/cli/options
|
|
172
|
-
* @see {@link /#mochaopts|mocha.opts}
|
|
173
|
-
* @public
|
|
174
|
-
*/
|
|
175
|
-
const loadMochaOpts = (args = {}) => {
|
|
176
|
-
let result;
|
|
177
|
-
let filepath = args.opts;
|
|
178
|
-
// /dev/null is backwards compat
|
|
179
|
-
if (filepath === false || filepath === '/dev/null') {
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
filepath = filepath || mocharc.opts;
|
|
183
|
-
result = {};
|
|
184
|
-
let mochaOpts;
|
|
185
|
-
try {
|
|
186
|
-
mochaOpts = fs.readFileSync(filepath, 'utf8');
|
|
187
|
-
debug(`read ${filepath}`);
|
|
188
|
-
} catch (err) {
|
|
189
|
-
if (args.opts) {
|
|
190
|
-
throw new Error(`Unable to read ${filepath}: ${err}`);
|
|
191
|
-
}
|
|
192
|
-
// ignore otherwise. we tried
|
|
193
|
-
debug(`No mocha.opts found at ${filepath}`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// real args should override `mocha.opts` which should override defaults.
|
|
197
|
-
// if there's an exception to catch here, I'm not sure what it is.
|
|
198
|
-
// by attaching the `no-opts` arg, we avoid re-parsing of `mocha.opts`.
|
|
199
|
-
if (mochaOpts) {
|
|
200
|
-
deprecate(
|
|
201
|
-
'Configuration via mocha.opts is DEPRECATED and will be removed from a future version of Mocha. Use RC files or package.json instead.'
|
|
202
|
-
);
|
|
203
|
-
result = parse(parseMochaOpts(mochaOpts));
|
|
204
|
-
debug(`${filepath} parsed succesfully`);
|
|
205
|
-
}
|
|
206
|
-
return result;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
module.exports.loadMochaOpts = loadMochaOpts;
|
|
210
|
-
|
|
211
148
|
/**
|
|
212
149
|
* Given path to config file in `args.config`, attempt to load & parse config file.
|
|
213
150
|
* @param {Object} [args] - Arguments object
|
|
@@ -267,11 +204,10 @@ module.exports.loadPkgRc = loadPkgRc;
|
|
|
267
204
|
* 1. Command-line args
|
|
268
205
|
* 2. RC file (`.mocharc.c?js`, `.mocharc.ya?ml`, `mocharc.json`)
|
|
269
206
|
* 3. `mocha` prop of `package.json`
|
|
270
|
-
* 4. `
|
|
271
|
-
* 5. default configuration (`lib/mocharc.json`)
|
|
207
|
+
* 4. default configuration (`lib/mocharc.json`)
|
|
272
208
|
*
|
|
273
209
|
* 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.
|
|
274
|
-
* @summary Parses options read from
|
|
210
|
+
* @summary Parses options read from `.mocharc.*` and `package.json`.
|
|
275
211
|
* @param {string|string[]} [argv] - Arguments to parse
|
|
276
212
|
* @public
|
|
277
213
|
* @memberof module:lib/cli/options
|
|
@@ -279,7 +215,7 @@ module.exports.loadPkgRc = loadPkgRc;
|
|
|
279
215
|
*/
|
|
280
216
|
const loadOptions = (argv = []) => {
|
|
281
217
|
let args = parse(argv);
|
|
282
|
-
// short-circuit: look for a flag that would abort loading of
|
|
218
|
+
// short-circuit: look for a flag that would abort loading of options
|
|
283
219
|
if (
|
|
284
220
|
Array.from(ONE_AND_DONE_ARGS).reduce(
|
|
285
221
|
(acc, arg) => acc || arg in args,
|
|
@@ -291,7 +227,6 @@ const loadOptions = (argv = []) => {
|
|
|
291
227
|
|
|
292
228
|
const rcConfig = loadRc(args);
|
|
293
229
|
const pkgConfig = loadPkgRc(args);
|
|
294
|
-
const optsConfig = loadMochaOpts(args);
|
|
295
230
|
|
|
296
231
|
if (rcConfig) {
|
|
297
232
|
args.config = false;
|
|
@@ -301,19 +236,8 @@ const loadOptions = (argv = []) => {
|
|
|
301
236
|
args.package = false;
|
|
302
237
|
args._ = args._.concat(pkgConfig._ || []);
|
|
303
238
|
}
|
|
304
|
-
if (optsConfig) {
|
|
305
|
-
args.opts = false;
|
|
306
|
-
args._ = args._.concat(optsConfig._ || []);
|
|
307
|
-
}
|
|
308
239
|
|
|
309
|
-
args = parse(
|
|
310
|
-
args._,
|
|
311
|
-
mocharc,
|
|
312
|
-
args,
|
|
313
|
-
rcConfig || {},
|
|
314
|
-
pkgConfig || {},
|
|
315
|
-
optsConfig || {}
|
|
316
|
-
);
|
|
240
|
+
args = parse(args._, mocharc, args, rcConfig || {}, pkgConfig || {});
|
|
317
241
|
|
|
318
242
|
// recombine positional arguments and "spec"
|
|
319
243
|
if (args.spec) {
|
package/lib/cli/run-helpers.js
CHANGED
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const debug = require('debug')('mocha:cli:run:helpers');
|
|
13
|
-
const watchRun = require('./watch-run');
|
|
13
|
+
const {watchRun, watchParallelRun} = require('./watch-run');
|
|
14
14
|
const collectFiles = require('./collect-files');
|
|
15
15
|
const {type} = require('../utils');
|
|
16
16
|
const {format} = require('util');
|
|
17
17
|
const {createInvalidPluginError, createUnsupportedError} = require('../errors');
|
|
18
|
+
const {requireOrImport} = require('../esm-utils');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Exits Mocha when tests + code under test has finished execution (default)
|
|
@@ -81,16 +82,21 @@ exports.list = str =>
|
|
|
81
82
|
* @returns {Promise<MochaRootHookObject|MochaRootHookFunction>} Any root hooks
|
|
82
83
|
* @private
|
|
83
84
|
*/
|
|
84
|
-
exports.handleRequires = async (requires = []) =>
|
|
85
|
-
|
|
85
|
+
exports.handleRequires = async (requires = []) => {
|
|
86
|
+
const acc = [];
|
|
87
|
+
for (const mod of requires) {
|
|
86
88
|
let modpath = mod;
|
|
87
89
|
// this is relative to cwd
|
|
88
90
|
if (fs.existsSync(mod) || fs.existsSync(`${mod}.js`)) {
|
|
89
91
|
modpath = path.resolve(mod);
|
|
90
92
|
debug('resolved required file %s to %s', mod, modpath);
|
|
91
93
|
}
|
|
92
|
-
const requiredModule =
|
|
93
|
-
if (
|
|
94
|
+
const requiredModule = await requireOrImport(modpath);
|
|
95
|
+
if (
|
|
96
|
+
requiredModule &&
|
|
97
|
+
typeof requiredModule === 'object' &&
|
|
98
|
+
requiredModule.mochaHooks
|
|
99
|
+
) {
|
|
94
100
|
const mochaHooksType = type(requiredModule.mochaHooks);
|
|
95
101
|
if (/function$/.test(mochaHooksType) || mochaHooksType === 'object') {
|
|
96
102
|
debug('found root hooks in required file %s', mod);
|
|
@@ -102,8 +108,9 @@ exports.handleRequires = async (requires = []) =>
|
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
debug('loaded required module "%s"', mod);
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
}
|
|
112
|
+
return acc;
|
|
113
|
+
};
|
|
107
114
|
|
|
108
115
|
/**
|
|
109
116
|
* Loads root hooks as exported via `mochaHooks` from required files.
|
|
@@ -151,24 +158,52 @@ const singleRun = async (mocha, {exit}, fileCollectParams) => {
|
|
|
151
158
|
};
|
|
152
159
|
|
|
153
160
|
/**
|
|
154
|
-
*
|
|
161
|
+
* Collect files and run tests (using `BufferedRunner`).
|
|
162
|
+
*
|
|
163
|
+
* This is `async` for consistency.
|
|
164
|
+
*
|
|
155
165
|
* @param {Mocha} mocha - Mocha instance
|
|
156
|
-
* @param {
|
|
166
|
+
* @param {Options} options - Command line options
|
|
167
|
+
* @param {Object} fileCollectParams - Parameters that control test
|
|
168
|
+
* file collection. See `lib/cli/collect-files.js`.
|
|
169
|
+
* @returns {Promise<BufferedRunner>}
|
|
170
|
+
* @ignore
|
|
157
171
|
* @private
|
|
158
|
-
|
|
172
|
+
*/
|
|
173
|
+
const parallelRun = async (mocha, options, fileCollectParams) => {
|
|
174
|
+
const files = collectFiles(fileCollectParams);
|
|
175
|
+
debug(
|
|
176
|
+
'executing %d test file(s) across %d concurrent jobs',
|
|
177
|
+
files.length,
|
|
178
|
+
options.jobs
|
|
179
|
+
);
|
|
180
|
+
mocha.files = files;
|
|
181
|
+
|
|
182
|
+
// note that we DO NOT load any files here; this is handled by the worker
|
|
183
|
+
return mocha.run(options.exit ? exitMocha : exitMochaLater);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Actually run tests. Delegates to one of four different functions:
|
|
188
|
+
* - `singleRun`: run tests in serial & exit
|
|
189
|
+
* - `watchRun`: run tests in serial, rerunning as files change
|
|
190
|
+
* - `parallelRun`: run tests in parallel & exit
|
|
191
|
+
* - `watchParallelRun`: run tests in parallel, rerunning as files change
|
|
192
|
+
* @param {Mocha} mocha - Mocha instance
|
|
193
|
+
* @param {Options} opts - Command line options
|
|
194
|
+
* @private
|
|
195
|
+
* @returns {Promise<Runner>}
|
|
159
196
|
*/
|
|
160
197
|
exports.runMocha = async (mocha, options) => {
|
|
161
198
|
const {
|
|
162
199
|
watch = false,
|
|
163
200
|
extension = [],
|
|
164
|
-
exit = false,
|
|
165
201
|
ignore = [],
|
|
166
202
|
file = [],
|
|
203
|
+
parallel = false,
|
|
167
204
|
recursive = false,
|
|
168
205
|
sort = false,
|
|
169
|
-
spec = []
|
|
170
|
-
watchFiles,
|
|
171
|
-
watchIgnore
|
|
206
|
+
spec = []
|
|
172
207
|
} = options;
|
|
173
208
|
|
|
174
209
|
const fileCollectParams = {
|
|
@@ -180,11 +215,14 @@ exports.runMocha = async (mocha, options) => {
|
|
|
180
215
|
spec
|
|
181
216
|
};
|
|
182
217
|
|
|
218
|
+
let run;
|
|
183
219
|
if (watch) {
|
|
184
|
-
|
|
220
|
+
run = parallel ? watchParallelRun : watchRun;
|
|
185
221
|
} else {
|
|
186
|
-
|
|
222
|
+
run = parallel ? parallelRun : singleRun;
|
|
187
223
|
}
|
|
224
|
+
|
|
225
|
+
return run(mocha, options, fileCollectParams);
|
|
188
226
|
};
|
|
189
227
|
|
|
190
228
|
/**
|
|
@@ -42,16 +42,16 @@ exports.types = {
|
|
|
42
42
|
'list-interfaces',
|
|
43
43
|
'list-reporters',
|
|
44
44
|
'no-colors',
|
|
45
|
+
'parallel',
|
|
45
46
|
'recursive',
|
|
46
47
|
'sort',
|
|
47
48
|
'watch'
|
|
48
49
|
],
|
|
49
|
-
number: ['retries'],
|
|
50
|
+
number: ['retries', 'jobs'],
|
|
50
51
|
string: [
|
|
51
52
|
'config',
|
|
52
53
|
'fgrep',
|
|
53
54
|
'grep',
|
|
54
|
-
'opts',
|
|
55
55
|
'package',
|
|
56
56
|
'reporter',
|
|
57
57
|
'ui',
|
|
@@ -76,7 +76,9 @@ exports.aliases = {
|
|
|
76
76
|
growl: ['G'],
|
|
77
77
|
ignore: ['exclude'],
|
|
78
78
|
invert: ['i'],
|
|
79
|
+
jobs: ['j'],
|
|
79
80
|
'no-colors': ['C'],
|
|
81
|
+
parallel: ['p'],
|
|
80
82
|
reporter: ['R'],
|
|
81
83
|
'reporter-option': ['reporter-options', 'O'],
|
|
82
84
|
require: ['r'],
|
package/lib/cli/run.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* @private
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
const symbols = require('log-symbols');
|
|
11
|
+
const ansi = require('ansi-colors');
|
|
10
12
|
const Mocha = require('../mocha');
|
|
11
13
|
const {
|
|
12
14
|
createUnsupportedError,
|
|
@@ -151,6 +153,13 @@ exports.builder = yargs =>
|
|
|
151
153
|
description: 'Inverts --grep and --fgrep matches',
|
|
152
154
|
group: GROUPS.FILTERS
|
|
153
155
|
},
|
|
156
|
+
jobs: {
|
|
157
|
+
description:
|
|
158
|
+
'Number of concurrent jobs for --parallel; use 1 to run in serial',
|
|
159
|
+
defaultDescription: '(number of CPU cores - 1)',
|
|
160
|
+
requiresArg: true,
|
|
161
|
+
group: GROUPS.RULES
|
|
162
|
+
},
|
|
154
163
|
'list-interfaces': {
|
|
155
164
|
conflicts: Array.from(ONE_AND_DONE_ARGS),
|
|
156
165
|
description: 'List built-in user interfaces & exit'
|
|
@@ -164,19 +173,16 @@ exports.builder = yargs =>
|
|
|
164
173
|
group: GROUPS.OUTPUT,
|
|
165
174
|
hidden: true
|
|
166
175
|
},
|
|
167
|
-
opts: {
|
|
168
|
-
default: defaults.opts,
|
|
169
|
-
description: 'Path to `mocha.opts` (DEPRECATED)',
|
|
170
|
-
group: GROUPS.CONFIG,
|
|
171
|
-
normalize: true,
|
|
172
|
-
requiresArg: true
|
|
173
|
-
},
|
|
174
176
|
package: {
|
|
175
177
|
description: 'Path to package.json for config',
|
|
176
178
|
group: GROUPS.CONFIG,
|
|
177
179
|
normalize: true,
|
|
178
180
|
requiresArg: true
|
|
179
181
|
},
|
|
182
|
+
parallel: {
|
|
183
|
+
description: 'Run tests in parallel',
|
|
184
|
+
group: GROUPS.RULES
|
|
185
|
+
},
|
|
180
186
|
recursive: {
|
|
181
187
|
description: 'Look for tests in subdirectories',
|
|
182
188
|
group: GROUPS.FILES
|
|
@@ -279,6 +285,40 @@ exports.builder = yargs =>
|
|
|
279
285
|
);
|
|
280
286
|
}
|
|
281
287
|
|
|
288
|
+
if (argv.parallel) {
|
|
289
|
+
// yargs.conflicts() can't deal with `--file foo.js --no-parallel`, either
|
|
290
|
+
if (argv.file) {
|
|
291
|
+
throw createUnsupportedError(
|
|
292
|
+
'--parallel runs test files in a non-deterministic order, and is mutually exclusive with --file'
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// or this
|
|
297
|
+
if (argv.sort) {
|
|
298
|
+
throw createUnsupportedError(
|
|
299
|
+
'--parallel runs test files in a non-deterministic order, and is mutually exclusive with --sort'
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (argv.reporter === 'progress') {
|
|
304
|
+
throw createUnsupportedError(
|
|
305
|
+
'--reporter=progress is mutually exclusive with --parallel'
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (argv.reporter === 'markdown') {
|
|
310
|
+
throw createUnsupportedError(
|
|
311
|
+
'--reporter=markdown is mutually exclusive with --parallel'
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (argv.reporter === 'json-stream') {
|
|
316
|
+
throw createUnsupportedError(
|
|
317
|
+
'--reporter=json-stream is mutually exclusive with --parallel'
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
282
322
|
if (argv.compilers) {
|
|
283
323
|
throw createUnsupportedError(
|
|
284
324
|
`--compilers is DEPRECATED and no longer supported.
|
|
@@ -295,14 +335,21 @@ exports.builder = yargs =>
|
|
|
295
335
|
|
|
296
336
|
return true;
|
|
297
337
|
})
|
|
298
|
-
.middleware(async argv => {
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
338
|
+
.middleware(async (argv, yargs) => {
|
|
339
|
+
// currently a failing middleware does not work nicely with yargs' `fail()`.
|
|
340
|
+
try {
|
|
341
|
+
// load requires first, because it can impact "plugin" validation
|
|
342
|
+
const rawRootHooks = await handleRequires(argv.require);
|
|
343
|
+
validatePlugin(argv, 'reporter', Mocha.reporters);
|
|
344
|
+
validatePlugin(argv, 'ui', Mocha.interfaces);
|
|
303
345
|
|
|
304
|
-
|
|
305
|
-
|
|
346
|
+
if (rawRootHooks && rawRootHooks.length) {
|
|
347
|
+
argv.rootHooks = await loadRootHooks(rawRootHooks);
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
// this could be a bad --require, bad reporter, ui, etc.
|
|
351
|
+
console.error(`\n${symbols.error} ${ansi.red('ERROR:')}`, err);
|
|
352
|
+
yargs.exit(1);
|
|
306
353
|
}
|
|
307
354
|
})
|
|
308
355
|
.array(types.array)
|