mocha 5.1.0 → 6.0.0-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 +653 -981
- package/README.md +2 -1
- package/{images → assets/growl}/error.png +0 -0
- package/{images → assets/growl}/ok.png +0 -0
- package/bin/_mocha +4 -595
- package/bin/mocha +84 -58
- package/bin/options.js +6 -39
- package/browser-entry.js +21 -17
- package/lib/browser/growl.js +164 -2
- package/lib/browser/progress.js +11 -11
- package/lib/{template.html → browser/template.html} +0 -0
- package/lib/browser/tty.js +2 -2
- package/lib/cli/cli.js +68 -0
- package/lib/cli/commands.js +13 -0
- package/lib/cli/config.js +79 -0
- package/lib/cli/index.js +9 -0
- package/lib/cli/init.js +37 -0
- package/lib/cli/node-flags.js +48 -0
- package/lib/cli/one-and-dones.js +70 -0
- package/lib/cli/options.js +299 -0
- package/lib/cli/run-helpers.js +328 -0
- package/lib/cli/run-option-metadata.js +72 -0
- package/lib/cli/run.js +293 -0
- package/lib/context.js +14 -14
- package/lib/errors.js +139 -0
- package/lib/growl.js +135 -0
- package/lib/hook.js +5 -16
- package/lib/interfaces/bdd.js +14 -13
- package/lib/interfaces/common.js +59 -16
- package/lib/interfaces/exports.js +4 -7
- package/lib/interfaces/qunit.js +8 -10
- package/lib/interfaces/tdd.js +10 -11
- package/lib/mocha.js +442 -255
- package/lib/mocharc.json +10 -0
- package/lib/pending.js +1 -5
- package/lib/reporters/base.js +92 -117
- package/lib/reporters/doc.js +18 -9
- package/lib/reporters/dot.js +13 -13
- package/lib/reporters/html.js +76 -47
- package/lib/reporters/json-stream.js +38 -23
- package/lib/reporters/json.js +26 -23
- package/lib/reporters/landing.js +9 -8
- package/lib/reporters/list.js +11 -10
- package/lib/reporters/markdown.js +13 -12
- package/lib/reporters/min.js +4 -3
- package/lib/reporters/nyan.js +36 -35
- package/lib/reporters/progress.js +8 -7
- package/lib/reporters/spec.js +14 -11
- package/lib/reporters/tap.js +243 -32
- package/lib/reporters/xunit.js +52 -33
- package/lib/runnable.js +103 -90
- package/lib/runner.js +156 -107
- package/lib/stats-collector.js +81 -0
- package/lib/suite.js +57 -51
- package/lib/test.js +13 -13
- package/lib/utils.js +192 -103
- package/mocha.js +3836 -2046
- package/package.json +122 -38
- package/bin/.eslintrc.yml +0 -3
- package/lib/browser/.eslintrc.yml +0 -4
- package/lib/ms.js +0 -94
- package/lib/reporters/base.js.orig +0 -498
- package/lib/reporters/json.js.orig +0 -128
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Helper scripts for the `run` command
|
|
5
|
+
* @see module:lib/cli/run
|
|
6
|
+
* @module
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const debug = require('debug')('mocha:cli:run:helpers');
|
|
12
|
+
const Context = require('../context');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const utils = require('../utils');
|
|
15
|
+
const minimatch = require('minimatch');
|
|
16
|
+
const ansi = require('ansi-colors');
|
|
17
|
+
const symbols = require('log-symbols');
|
|
18
|
+
|
|
19
|
+
const cwd = (exports.cwd = process.cwd());
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Exits Mocha when tests + code under test has finished execution (default)
|
|
23
|
+
* @param {number} code - Exit code; typically # of failures
|
|
24
|
+
* @ignore
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
const exitMochaLater = code => {
|
|
28
|
+
process.on('exit', () => {
|
|
29
|
+
process.exit(Math.min(code, 255));
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Exits Mocha when Mocha itself has finished execution, regardless of
|
|
35
|
+
* what the tests or code under test is doing.
|
|
36
|
+
* @param {number} code - Exit code; typically # of failures
|
|
37
|
+
* @ignore
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
const exitMocha = code => {
|
|
41
|
+
const clampedCode = Math.min(code, 255);
|
|
42
|
+
let draining = 0;
|
|
43
|
+
|
|
44
|
+
// Eagerly set the process's exit code in case stream.write doesn't
|
|
45
|
+
// execute its callback before the process terminates.
|
|
46
|
+
process.exitCode = clampedCode;
|
|
47
|
+
|
|
48
|
+
// flush output for Node.js Windows pipe bug
|
|
49
|
+
// https://github.com/joyent/node/issues/6247 is just one bug example
|
|
50
|
+
// https://github.com/visionmedia/mocha/issues/333 has a good discussion
|
|
51
|
+
const done = () => {
|
|
52
|
+
if (!draining--) {
|
|
53
|
+
process.exit(clampedCode);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const streams = [process.stdout, process.stderr];
|
|
58
|
+
|
|
59
|
+
streams.forEach(stream => {
|
|
60
|
+
// submit empty write request and wait for completion
|
|
61
|
+
draining += 1;
|
|
62
|
+
stream.write('', done);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
done();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Hide the cursor.
|
|
70
|
+
* @ignore
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
const hideCursor = () => {
|
|
74
|
+
process.stdout.write('\u001b[?25l');
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Show the cursor.
|
|
79
|
+
* @ignore
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
const showCursor = () => {
|
|
83
|
+
process.stdout.write('\u001b[?25h');
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Stop cursor business
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
const stop = () => {
|
|
91
|
+
process.stdout.write('\u001b[2K');
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Coerce a comma-delimited string (or array thereof) into a flattened array of
|
|
96
|
+
* strings
|
|
97
|
+
* @param {string|string[]} str - Value to coerce
|
|
98
|
+
* @returns {string[]} Array of strings
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
101
|
+
exports.list = str =>
|
|
102
|
+
Array.isArray(str) ? exports.list(str.join(',')) : str.split(/ *, */);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* `require()` the modules as required by `--require <require>`
|
|
106
|
+
* @param {string[]} requires - Modules to require
|
|
107
|
+
* @private
|
|
108
|
+
*/
|
|
109
|
+
exports.handleRequires = (requires = []) => {
|
|
110
|
+
requires.forEach(mod => {
|
|
111
|
+
let modpath = mod;
|
|
112
|
+
if (fs.existsSync(mod, {cwd}) || fs.existsSync(`${mod}.js`, {cwd})) {
|
|
113
|
+
modpath = path.resolve(mod);
|
|
114
|
+
debug(`resolved ${mod} to ${modpath}`);
|
|
115
|
+
}
|
|
116
|
+
require(modpath);
|
|
117
|
+
debug(`loaded require "${mod}"`);
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Smash together an array of test files in the correct order
|
|
123
|
+
* @param {Object} [opts] - Options
|
|
124
|
+
* @param {string[]} [opts.extension] - File extensions to use
|
|
125
|
+
* @param {string[]} [opts.spec] - Files, dirs, globs to run
|
|
126
|
+
* @param {string[]} [opts.exclude] - Files, dirs, globs to exclude
|
|
127
|
+
* @param {boolean} [opts.recursive=false] - Find files recursively
|
|
128
|
+
* @param {boolean} [opts.sort=false] - Sort test files
|
|
129
|
+
* @returns {string[]} List of files to test
|
|
130
|
+
* @private
|
|
131
|
+
*/
|
|
132
|
+
exports.handleFiles = ({
|
|
133
|
+
exclude = [],
|
|
134
|
+
extension = [],
|
|
135
|
+
file = [],
|
|
136
|
+
recursive = false,
|
|
137
|
+
sort = false,
|
|
138
|
+
spec = []
|
|
139
|
+
} = {}) => {
|
|
140
|
+
let files = [];
|
|
141
|
+
spec.forEach(arg => {
|
|
142
|
+
let newFiles;
|
|
143
|
+
try {
|
|
144
|
+
newFiles = utils.lookupFiles(arg, extension, recursive);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') {
|
|
147
|
+
console.warn('Warning: %s: %O', err.message, err.pattern);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (typeof newFiles !== 'undefined') {
|
|
155
|
+
if (typeof newFiles === 'string') {
|
|
156
|
+
newFiles = [newFiles];
|
|
157
|
+
}
|
|
158
|
+
newFiles = newFiles.filter(fileName =>
|
|
159
|
+
exclude.every(pattern => !minimatch(fileName, pattern))
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
files = files.concat(newFiles);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (!files.length) {
|
|
167
|
+
console.error(ansi.red(`${symbols.error} No test files found`));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const fileArgs = file.map(filepath => path.resolve(filepath));
|
|
172
|
+
files = files.map(filepath => path.resolve(filepath));
|
|
173
|
+
|
|
174
|
+
// ensure we don't sort the stuff from fileArgs; order is important!
|
|
175
|
+
if (sort) {
|
|
176
|
+
files.sort();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// add files given through --file to be ran first
|
|
180
|
+
files = fileArgs.concat(files);
|
|
181
|
+
debug('files (in order): ', files);
|
|
182
|
+
return files;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Give Mocha files and tell it to run
|
|
187
|
+
* @param {Mocha} mocha - Mocha instance
|
|
188
|
+
* @param {Options} [opts] - Options
|
|
189
|
+
* @param {string[]} [opts.files] - List of test files
|
|
190
|
+
* @param {boolean} [opts.exit] - Whether or not to force-exit after tests are complete
|
|
191
|
+
* @returns {Runner}
|
|
192
|
+
* @private
|
|
193
|
+
*/
|
|
194
|
+
exports.singleRun = (mocha, {files = [], exit = false} = {}) => {
|
|
195
|
+
mocha.files = files;
|
|
196
|
+
return mocha.run(exit ? exitMocha : exitMochaLater);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Run Mocha in "watch" mode
|
|
201
|
+
* @param {Mocha} mocha - Mocha instance
|
|
202
|
+
* @param {Object} [opts] - Options
|
|
203
|
+
* @param {string[]} [opts.extension] - List of extensions to watch
|
|
204
|
+
* @param {string|RegExp} [opts.grep] - Grep for test titles
|
|
205
|
+
* @param {string} [opts.ui=bdd] - User interface
|
|
206
|
+
* @param {string[]} [files] - Array of test files
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
209
|
+
exports.watchRun = (
|
|
210
|
+
mocha,
|
|
211
|
+
{extension = ['js'], grep = '', ui = 'bdd', files = []} = {}
|
|
212
|
+
) => {
|
|
213
|
+
let runner;
|
|
214
|
+
|
|
215
|
+
console.log();
|
|
216
|
+
hideCursor();
|
|
217
|
+
process.on('SIGINT', () => {
|
|
218
|
+
showCursor();
|
|
219
|
+
console.log('\n');
|
|
220
|
+
process.exit(130);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const watchFiles = utils.files(cwd, extension);
|
|
224
|
+
let runAgain = false;
|
|
225
|
+
|
|
226
|
+
const loadAndRun = () => {
|
|
227
|
+
try {
|
|
228
|
+
mocha.files = files;
|
|
229
|
+
runAgain = false;
|
|
230
|
+
runner = mocha.run(() => {
|
|
231
|
+
runner = null;
|
|
232
|
+
if (runAgain) {
|
|
233
|
+
rerun();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
} catch (e) {
|
|
237
|
+
console.log(e.stack);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const purge = () => {
|
|
242
|
+
watchFiles.forEach(file => {
|
|
243
|
+
delete require.cache[file];
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
loadAndRun();
|
|
248
|
+
|
|
249
|
+
const rerun = () => {
|
|
250
|
+
purge();
|
|
251
|
+
stop();
|
|
252
|
+
if (!grep) {
|
|
253
|
+
mocha.grep(null);
|
|
254
|
+
}
|
|
255
|
+
mocha.suite = mocha.suite.clone();
|
|
256
|
+
mocha.suite.ctx = new Context();
|
|
257
|
+
mocha.ui(ui);
|
|
258
|
+
loadAndRun();
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
utils.watch(watchFiles, () => {
|
|
262
|
+
runAgain = true;
|
|
263
|
+
if (runner) {
|
|
264
|
+
runner.abort();
|
|
265
|
+
} else {
|
|
266
|
+
rerun();
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Actually run tests
|
|
273
|
+
* @param {Mocha} mocha - Mocha instance
|
|
274
|
+
* @param {Object} [opts] - Options
|
|
275
|
+
* @param {boolean} [opts.watch=false] - Enable watch mode
|
|
276
|
+
* @param {string[]} [opts.extension] - List of extensions to watch
|
|
277
|
+
* @param {string|RegExp} [opts.grep] - Grep for test titles
|
|
278
|
+
* @param {string} [opts.ui=bdd] - User interface
|
|
279
|
+
* @param {boolean} [opts.exit=false] - Force-exit Mocha when tests done
|
|
280
|
+
* @param {string[]} [files] - Array of test files
|
|
281
|
+
* @private
|
|
282
|
+
*/
|
|
283
|
+
exports.runMocha = (
|
|
284
|
+
mocha,
|
|
285
|
+
{watch = false, extension = ['js'], grep = '', ui = 'bdd', exit = false} = {},
|
|
286
|
+
files = []
|
|
287
|
+
) => {
|
|
288
|
+
if (watch) {
|
|
289
|
+
exports.watchRun(mocha, {extension, grep, ui});
|
|
290
|
+
} else {
|
|
291
|
+
exports.singleRun(mocha, {files, exit});
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Used for `--reporter` and `--ui`. Ensures there's only one, and asserts
|
|
297
|
+
* that it actually exists.
|
|
298
|
+
* @todo XXX This must get run after requires are processed, as it'll prevent
|
|
299
|
+
* interfaces from loading.
|
|
300
|
+
* @param {Object} opts - Options object
|
|
301
|
+
* @param {string} key - Resolvable module name or path
|
|
302
|
+
* @param {Object} [map] - An object perhaps having key `key`
|
|
303
|
+
* @private
|
|
304
|
+
*/
|
|
305
|
+
exports.validatePlugin = (opts, key, map = {}) => {
|
|
306
|
+
if (Array.isArray(opts[key])) {
|
|
307
|
+
throw new TypeError(`"--${key} <${key}>" can only be specified once`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const unknownError = () => new Error(`Unknown "${key}": ${opts[key]}`);
|
|
311
|
+
|
|
312
|
+
if (!map[opts[key]]) {
|
|
313
|
+
try {
|
|
314
|
+
opts[key] = require(opts[key]);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
317
|
+
// Try to load reporters from a path (absolute or relative)
|
|
318
|
+
try {
|
|
319
|
+
opts[key] = require(path.resolve(process.cwd(), opts[key]));
|
|
320
|
+
} catch (err) {
|
|
321
|
+
throw unknownError();
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
throw unknownError();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Metadata about various options of the `run` command
|
|
5
|
+
* @see module:lib/cli/run
|
|
6
|
+
* @module
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Dictionary of yargs option types to list of options having said type
|
|
12
|
+
* @type {{string:string[]}}
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
exports.types = {
|
|
16
|
+
array: [
|
|
17
|
+
'exclude',
|
|
18
|
+
'extension',
|
|
19
|
+
'file',
|
|
20
|
+
'global',
|
|
21
|
+
'require',
|
|
22
|
+
'reporter-option',
|
|
23
|
+
'spec'
|
|
24
|
+
],
|
|
25
|
+
boolean: [
|
|
26
|
+
'allow-uncaught',
|
|
27
|
+
'async-only',
|
|
28
|
+
'bail',
|
|
29
|
+
'check-leaks',
|
|
30
|
+
'color',
|
|
31
|
+
'diff',
|
|
32
|
+
'exit',
|
|
33
|
+
'forbid-only',
|
|
34
|
+
'forbid-pending',
|
|
35
|
+
'full-trace',
|
|
36
|
+
'growl',
|
|
37
|
+
'inline-diffs',
|
|
38
|
+
'invert',
|
|
39
|
+
'no-colors',
|
|
40
|
+
'recursive',
|
|
41
|
+
'watch'
|
|
42
|
+
],
|
|
43
|
+
number: ['retries', 'slow', 'timeout'],
|
|
44
|
+
string: ['fgrep', 'grep', 'package', 'reporter', 'ui']
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Option aliases keyed by canonical option name.
|
|
49
|
+
* Arrays used to reduce
|
|
50
|
+
* @type {{string:string[]}}
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
exports.aliases = {
|
|
54
|
+
'async-only': ['A'],
|
|
55
|
+
bail: ['b'],
|
|
56
|
+
color: ['c', 'colors'],
|
|
57
|
+
extension: ['watch-extensions'],
|
|
58
|
+
fgrep: ['f'],
|
|
59
|
+
global: ['globals'],
|
|
60
|
+
grep: ['g'],
|
|
61
|
+
growl: ['G'],
|
|
62
|
+
invert: ['i'],
|
|
63
|
+
'no-colors': ['C'],
|
|
64
|
+
reporter: ['R'],
|
|
65
|
+
'reporter-option': ['reporter-options', 'O'],
|
|
66
|
+
require: ['r'],
|
|
67
|
+
slow: ['s'],
|
|
68
|
+
sort: ['S'],
|
|
69
|
+
timeout: ['t', 'timeouts'],
|
|
70
|
+
ui: ['u'],
|
|
71
|
+
watch: ['w']
|
|
72
|
+
};
|
package/lib/cli/run.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Definition for Mocha's default ("run tests") command
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const Mocha = require('../mocha');
|
|
11
|
+
const ansi = require('ansi-colors');
|
|
12
|
+
const errors = require('../errors');
|
|
13
|
+
const createInvalidArgumentValueError = errors.createInvalidArgumentValueError;
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
list,
|
|
17
|
+
handleFiles,
|
|
18
|
+
handleRequires,
|
|
19
|
+
validatePlugin,
|
|
20
|
+
runMocha
|
|
21
|
+
} = require('./run-helpers');
|
|
22
|
+
const {ONE_AND_DONES, ONE_AND_DONE_ARGS} = require('./one-and-dones');
|
|
23
|
+
const debug = require('debug')('mocha:cli:run');
|
|
24
|
+
const defaults = require('../mocharc');
|
|
25
|
+
const {types, aliases} = require('./run-option-metadata');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Logical option groups
|
|
29
|
+
* @constant
|
|
30
|
+
*/
|
|
31
|
+
const GROUPS = {
|
|
32
|
+
FILES: 'File Handling',
|
|
33
|
+
FILTERS: 'Test Filters',
|
|
34
|
+
NODEJS: 'Node.js & V8',
|
|
35
|
+
OUTPUT: 'Reporting & Output',
|
|
36
|
+
RULES: 'Rules & Behavior',
|
|
37
|
+
CONFIG: 'Configuration'
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.command = ['$0 [spec..]', 'debug [spec..]'];
|
|
41
|
+
|
|
42
|
+
exports.describe = 'Run tests with Mocha';
|
|
43
|
+
|
|
44
|
+
exports.builder = yargs =>
|
|
45
|
+
yargs
|
|
46
|
+
.options({
|
|
47
|
+
'allow-uncaught': {
|
|
48
|
+
description: 'Allow uncaught errors to propagate',
|
|
49
|
+
group: GROUPS.RULES
|
|
50
|
+
},
|
|
51
|
+
'async-only': {
|
|
52
|
+
description:
|
|
53
|
+
'Require all tests to use a callback (async) or return a Promise',
|
|
54
|
+
group: GROUPS.RULES
|
|
55
|
+
},
|
|
56
|
+
bail: {
|
|
57
|
+
description: 'Abort ("bail") after first test failure',
|
|
58
|
+
group: GROUPS.RULES
|
|
59
|
+
},
|
|
60
|
+
'check-leaks': {
|
|
61
|
+
description: 'Check for global variable leaks',
|
|
62
|
+
group: GROUPS.RULES
|
|
63
|
+
},
|
|
64
|
+
color: {
|
|
65
|
+
description: 'Force-enable color output',
|
|
66
|
+
group: GROUPS.OUTPUT
|
|
67
|
+
},
|
|
68
|
+
config: {
|
|
69
|
+
config: true,
|
|
70
|
+
defaultDescription: '(nearest rc file)',
|
|
71
|
+
description: 'Path to config file',
|
|
72
|
+
group: GROUPS.CONFIG
|
|
73
|
+
},
|
|
74
|
+
delay: {
|
|
75
|
+
description: 'Delay initial execution of root suite',
|
|
76
|
+
group: GROUPS.RULES
|
|
77
|
+
},
|
|
78
|
+
diff: {
|
|
79
|
+
default: true,
|
|
80
|
+
description: 'Show diff on failure',
|
|
81
|
+
group: GROUPS.OUTPUT
|
|
82
|
+
},
|
|
83
|
+
exclude: {
|
|
84
|
+
defaultDescription: '(none)',
|
|
85
|
+
description: 'Ignore file(s) or glob pattern(s)',
|
|
86
|
+
group: GROUPS.FILES,
|
|
87
|
+
requiresArg: true
|
|
88
|
+
},
|
|
89
|
+
exit: {
|
|
90
|
+
description: 'Force Mocha to quit after tests complete',
|
|
91
|
+
group: GROUPS.RULES
|
|
92
|
+
},
|
|
93
|
+
extension: {
|
|
94
|
+
default: defaults.extension,
|
|
95
|
+
defaultDescription: 'js',
|
|
96
|
+
description: 'File extension(s) to load and/or watch',
|
|
97
|
+
group: GROUPS.FILES,
|
|
98
|
+
requiresArg: true,
|
|
99
|
+
coerce: list
|
|
100
|
+
},
|
|
101
|
+
fgrep: {
|
|
102
|
+
conflicts: 'grep',
|
|
103
|
+
description: 'Only run tests containing this string',
|
|
104
|
+
group: GROUPS.FILTERS,
|
|
105
|
+
requiresArg: true
|
|
106
|
+
},
|
|
107
|
+
file: {
|
|
108
|
+
defaultDescription: '(none)',
|
|
109
|
+
description:
|
|
110
|
+
'Specify file(s) to be loaded prior to root suite execution',
|
|
111
|
+
group: GROUPS.FILES,
|
|
112
|
+
normalize: true,
|
|
113
|
+
requiresArg: true
|
|
114
|
+
},
|
|
115
|
+
'forbid-only': {
|
|
116
|
+
description: 'Fail if exclusive test(s) encountered',
|
|
117
|
+
group: GROUPS.RULES
|
|
118
|
+
},
|
|
119
|
+
'forbid-pending': {
|
|
120
|
+
description: 'Fail if pending test(s) encountered',
|
|
121
|
+
group: GROUPS.RULES
|
|
122
|
+
},
|
|
123
|
+
'full-trace': {
|
|
124
|
+
description: 'Display full stack traces',
|
|
125
|
+
group: GROUPS.OUTPUT
|
|
126
|
+
},
|
|
127
|
+
global: {
|
|
128
|
+
coerce: list,
|
|
129
|
+
description: 'List of allowed global variables',
|
|
130
|
+
group: GROUPS.RULES,
|
|
131
|
+
requiresArg: true
|
|
132
|
+
},
|
|
133
|
+
grep: {
|
|
134
|
+
coerce: value => (!value ? null : value),
|
|
135
|
+
conflicts: 'fgrep',
|
|
136
|
+
description: 'Only run tests matching this string or regexp',
|
|
137
|
+
group: GROUPS.FILTERS,
|
|
138
|
+
requiresArg: true
|
|
139
|
+
},
|
|
140
|
+
growl: {
|
|
141
|
+
description: 'Enable Growl notifications',
|
|
142
|
+
group: GROUPS.OUTPUT
|
|
143
|
+
},
|
|
144
|
+
'inline-diffs': {
|
|
145
|
+
description:
|
|
146
|
+
'Display actual/expected differences inline within each string',
|
|
147
|
+
group: GROUPS.OUTPUT
|
|
148
|
+
},
|
|
149
|
+
interfaces: {
|
|
150
|
+
conflicts: Array.from(ONE_AND_DONE_ARGS),
|
|
151
|
+
description: 'List built-in user interfaces & exit'
|
|
152
|
+
},
|
|
153
|
+
invert: {
|
|
154
|
+
description: 'Inverts --grep and --fgrep matches',
|
|
155
|
+
group: GROUPS.FILTERS
|
|
156
|
+
},
|
|
157
|
+
'no-colors': {
|
|
158
|
+
description: 'Force-disable color output',
|
|
159
|
+
group: GROUPS.OUTPUT,
|
|
160
|
+
hidden: true
|
|
161
|
+
},
|
|
162
|
+
opts: {
|
|
163
|
+
default: defaults.opts,
|
|
164
|
+
description: 'Path to `mocha.opts`',
|
|
165
|
+
group: GROUPS.CONFIG,
|
|
166
|
+
normalize: true,
|
|
167
|
+
requiresArg: true
|
|
168
|
+
},
|
|
169
|
+
package: {
|
|
170
|
+
description: 'Path to package.json for config',
|
|
171
|
+
group: GROUPS.CONFIG,
|
|
172
|
+
normalize: true,
|
|
173
|
+
requiresArg: true
|
|
174
|
+
},
|
|
175
|
+
recursive: {
|
|
176
|
+
description: 'Look for tests in subdirectories',
|
|
177
|
+
group: GROUPS.FILES
|
|
178
|
+
},
|
|
179
|
+
reporter: {
|
|
180
|
+
default: defaults.reporter,
|
|
181
|
+
description: 'Specify reporter to use',
|
|
182
|
+
group: GROUPS.OUTPUT,
|
|
183
|
+
requiresArg: true
|
|
184
|
+
},
|
|
185
|
+
reporters: {
|
|
186
|
+
conflicts: Array.from(ONE_AND_DONE_ARGS),
|
|
187
|
+
description: 'List built-in reporters & exit'
|
|
188
|
+
},
|
|
189
|
+
'reporter-option': {
|
|
190
|
+
coerce: opts =>
|
|
191
|
+
opts.reduce((acc, opt) => {
|
|
192
|
+
const pair = opt.split('=');
|
|
193
|
+
|
|
194
|
+
if (pair.length > 2 || !pair.length) {
|
|
195
|
+
throw createInvalidArgumentValueError(
|
|
196
|
+
`invalid reporter option '${opt}'`,
|
|
197
|
+
'--reporter-option',
|
|
198
|
+
opt,
|
|
199
|
+
'expected "key=value" format'
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
acc[pair[0]] = pair.length === 2 ? pair[1] : true;
|
|
204
|
+
return acc;
|
|
205
|
+
}, {}),
|
|
206
|
+
description: 'Reporter-specific options (<k=v,[k1=v1,..]>)',
|
|
207
|
+
group: GROUPS.OUTPUT,
|
|
208
|
+
requiresArg: true
|
|
209
|
+
},
|
|
210
|
+
require: {
|
|
211
|
+
defaultDescription: '(none)',
|
|
212
|
+
description: 'Require module',
|
|
213
|
+
group: GROUPS.FILES,
|
|
214
|
+
requiresArg: true
|
|
215
|
+
},
|
|
216
|
+
retries: {
|
|
217
|
+
description: 'Retry failed tests this many times',
|
|
218
|
+
group: GROUPS.RULES
|
|
219
|
+
},
|
|
220
|
+
slow: {
|
|
221
|
+
default: defaults.slow,
|
|
222
|
+
description: 'Specify "slow" test threshold (in milliseconds)',
|
|
223
|
+
group: GROUPS.RULES
|
|
224
|
+
},
|
|
225
|
+
sort: {
|
|
226
|
+
description: 'Sort test files',
|
|
227
|
+
group: GROUPS.FILES
|
|
228
|
+
},
|
|
229
|
+
timeout: {
|
|
230
|
+
default: defaults.timeout,
|
|
231
|
+
description: 'Specify test timeout threshold (in milliseconds)',
|
|
232
|
+
group: GROUPS.RULES
|
|
233
|
+
},
|
|
234
|
+
ui: {
|
|
235
|
+
default: defaults.ui,
|
|
236
|
+
description: 'Specify user interface',
|
|
237
|
+
group: GROUPS.RULES,
|
|
238
|
+
requiresArg: true
|
|
239
|
+
},
|
|
240
|
+
watch: {
|
|
241
|
+
description: 'Watch files in the current working directory for changes',
|
|
242
|
+
group: GROUPS.FILES
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
.positional('spec', {
|
|
246
|
+
default: ['test/'],
|
|
247
|
+
description: 'One or more files, directories, or globs to test',
|
|
248
|
+
type: 'array'
|
|
249
|
+
})
|
|
250
|
+
.check(argv => {
|
|
251
|
+
// "one-and-dones"; let yargs handle help and version
|
|
252
|
+
Object.keys(ONE_AND_DONES).forEach(opt => {
|
|
253
|
+
if (argv[opt]) {
|
|
254
|
+
ONE_AND_DONES[opt].call(null, yargs);
|
|
255
|
+
process.exit();
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// yargs.implies() isn't flexible enough to handle this
|
|
260
|
+
if (argv.invert && !('fgrep' in argv || 'grep' in argv)) {
|
|
261
|
+
throw new Error(
|
|
262
|
+
'"--invert" requires one of "--fgrep <str>" or "--grep <regexp>"'
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (argv.compilers) {
|
|
267
|
+
throw new Error(
|
|
268
|
+
`--compilers is DEPRECATED and no longer supported.
|
|
269
|
+
See ${ansi.cyan('https://git.io/vdcSr')} for migration information.`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// load requires first, because it can impact "plugin" validation
|
|
274
|
+
handleRequires(argv.require);
|
|
275
|
+
validatePlugin(argv, 'reporter', Mocha.reporters);
|
|
276
|
+
validatePlugin(argv, 'ui', Mocha.interfaces);
|
|
277
|
+
|
|
278
|
+
return true;
|
|
279
|
+
})
|
|
280
|
+
.array(types.array)
|
|
281
|
+
.boolean(types.boolean)
|
|
282
|
+
.string(types.string)
|
|
283
|
+
.number(types.number)
|
|
284
|
+
.alias(aliases);
|
|
285
|
+
|
|
286
|
+
exports.handler = argv => {
|
|
287
|
+
debug('post-yargs config', argv);
|
|
288
|
+
const mocha = new Mocha(argv);
|
|
289
|
+
const files = handleFiles(argv);
|
|
290
|
+
|
|
291
|
+
debug('running tests with files', files);
|
|
292
|
+
runMocha(mocha, argv, files);
|
|
293
|
+
};
|