mocha 7.0.0 → 7.1.2
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 +71 -1344
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/browser-entry.js +2 -2
- package/lib/cli/config.js +2 -1
- package/lib/cli/options.js +1 -1
- package/lib/cli/run-helpers.js +8 -7
- package/lib/cli/run.js +8 -3
- package/lib/esm-utils.js +31 -0
- package/lib/mocha.js +59 -5
- package/lib/mocharc.json +1 -1
- package/lib/runnable.js +10 -26
- package/lib/runner.js +37 -59
- package/lib/test.js +13 -0
- package/lib/utils.js +22 -32
- package/mocha.js +150 -132
- package/package.json +18 -517
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(The MIT License)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2011-
|
|
3
|
+
Copyright (c) 2011-2020 OpenJS Foundation and contributors, https://openjsf.org
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
a copy of this software and associated documentation files (the
|
package/README.md
CHANGED
|
@@ -100,6 +100,6 @@ Finally, come [chat with the maintainers](https://gitter.im/mochajs/contributors
|
|
|
100
100
|
|
|
101
101
|
## License
|
|
102
102
|
|
|
103
|
-
[MIT](LICENSE)
|
|
103
|
+
Copyright 2011-2020 OpenJS Foundation and contributors. Licensed [MIT](https://github.com/mochajs/mocha/blob/master/LICENSE).
|
|
104
104
|
|
|
105
105
|
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_large)
|
package/browser-entry.js
CHANGED
|
@@ -60,7 +60,7 @@ process.on = function(e, fn) {
|
|
|
60
60
|
if (e === 'uncaughtException') {
|
|
61
61
|
global.onerror = function(err, url, line) {
|
|
62
62
|
fn(new Error(err + ' (' + url + ':' + line + ')'));
|
|
63
|
-
return !mocha.allowUncaught;
|
|
63
|
+
return !mocha.options.allowUncaught;
|
|
64
64
|
};
|
|
65
65
|
uncaughtExceptionHandlers.push(fn);
|
|
66
66
|
}
|
|
@@ -129,7 +129,7 @@ mocha.setup = function(opts) {
|
|
|
129
129
|
opts = {ui: opts};
|
|
130
130
|
}
|
|
131
131
|
for (var opt in opts) {
|
|
132
|
-
if (
|
|
132
|
+
if (Object.prototype.hasOwnProperty.call(opts, opt)) {
|
|
133
133
|
this[opt](opts[opt]);
|
|
134
134
|
}
|
|
135
135
|
}
|
package/lib/cli/config.js
CHANGED
|
@@ -21,6 +21,7 @@ const findUp = require('find-up');
|
|
|
21
21
|
* @private
|
|
22
22
|
*/
|
|
23
23
|
exports.CONFIG_FILES = [
|
|
24
|
+
'.mocharc.cjs',
|
|
24
25
|
'.mocharc.js',
|
|
25
26
|
'.mocharc.yaml',
|
|
26
27
|
'.mocharc.yml',
|
|
@@ -75,7 +76,7 @@ exports.loadConfig = filepath => {
|
|
|
75
76
|
try {
|
|
76
77
|
if (ext === '.yml' || ext === '.yaml') {
|
|
77
78
|
config = parsers.yaml(filepath);
|
|
78
|
-
} else if (ext === '.js') {
|
|
79
|
+
} else if (ext === '.js' || ext === '.cjs') {
|
|
79
80
|
config = parsers.js(filepath);
|
|
80
81
|
} else {
|
|
81
82
|
config = parsers.json(filepath);
|
package/lib/cli/options.js
CHANGED
|
@@ -265,7 +265,7 @@ module.exports.loadPkgRc = loadPkgRc;
|
|
|
265
265
|
* Priority list:
|
|
266
266
|
*
|
|
267
267
|
* 1. Command-line args
|
|
268
|
-
* 2. RC file (`.mocharc.js`, `.mocharc.ya?ml`, `mocharc.json`)
|
|
268
|
+
* 2. RC file (`.mocharc.c?js`, `.mocharc.ya?ml`, `mocharc.json`)
|
|
269
269
|
* 3. `mocha` prop of `package.json`
|
|
270
270
|
* 4. `mocha.opts`
|
|
271
271
|
* 5. default configuration (`lib/mocharc.json`)
|
package/lib/cli/run-helpers.js
CHANGED
|
@@ -15,8 +15,6 @@ const collectFiles = require('./collect-files');
|
|
|
15
15
|
|
|
16
16
|
const cwd = (exports.cwd = process.cwd());
|
|
17
17
|
|
|
18
|
-
exports.watchRun = watchRun;
|
|
19
|
-
|
|
20
18
|
/**
|
|
21
19
|
* Exits Mocha when tests + code under test has finished execution (default)
|
|
22
20
|
* @param {number} code - Exit code; typically # of failures
|
|
@@ -92,19 +90,21 @@ exports.handleRequires = (requires = []) => {
|
|
|
92
90
|
};
|
|
93
91
|
|
|
94
92
|
/**
|
|
95
|
-
* Collect test files
|
|
93
|
+
* Collect and load test files, then run mocha instance.
|
|
96
94
|
* @param {Mocha} mocha - Mocha instance
|
|
97
95
|
* @param {Options} [opts] - Command line options
|
|
98
96
|
* @param {boolean} [opts.exit] - Whether or not to force-exit after tests are complete
|
|
99
97
|
* @param {Object} fileCollectParams - Parameters that control test
|
|
100
98
|
* file collection. See `lib/cli/collect-files.js`.
|
|
101
|
-
* @returns {Runner}
|
|
99
|
+
* @returns {Promise<Runner>}
|
|
102
100
|
* @private
|
|
103
101
|
*/
|
|
104
|
-
|
|
102
|
+
const singleRun = async (mocha, {exit}, fileCollectParams) => {
|
|
105
103
|
const files = collectFiles(fileCollectParams);
|
|
106
104
|
debug('running tests with files', files);
|
|
107
105
|
mocha.files = files;
|
|
106
|
+
|
|
107
|
+
await mocha.loadFilesAsync();
|
|
108
108
|
return mocha.run(exit ? exitMocha : exitMochaLater);
|
|
109
109
|
};
|
|
110
110
|
|
|
@@ -113,8 +113,9 @@ exports.singleRun = (mocha, {exit}, fileCollectParams) => {
|
|
|
113
113
|
* @param {Mocha} mocha - Mocha instance
|
|
114
114
|
* @param {Object} opts - Command line options
|
|
115
115
|
* @private
|
|
116
|
+
* @returns {Promise}
|
|
116
117
|
*/
|
|
117
|
-
exports.runMocha = (mocha, options) => {
|
|
118
|
+
exports.runMocha = async (mocha, options) => {
|
|
118
119
|
const {
|
|
119
120
|
watch = false,
|
|
120
121
|
extension = [],
|
|
@@ -140,7 +141,7 @@ exports.runMocha = (mocha, options) => {
|
|
|
140
141
|
if (watch) {
|
|
141
142
|
watchRun(mocha, {watchFiles, watchIgnore}, fileCollectParams);
|
|
142
143
|
} else {
|
|
143
|
-
|
|
144
|
+
await singleRun(mocha, {exit}, fileCollectParams);
|
|
144
145
|
}
|
|
145
146
|
};
|
|
146
147
|
|
package/lib/cli/run.js
CHANGED
|
@@ -87,7 +87,6 @@ exports.builder = yargs =>
|
|
|
87
87
|
},
|
|
88
88
|
extension: {
|
|
89
89
|
default: defaults.extension,
|
|
90
|
-
defaultDescription: 'js',
|
|
91
90
|
description: 'File extension(s) to load',
|
|
92
91
|
group: GROUPS.FILES,
|
|
93
92
|
requiresArg: true,
|
|
@@ -299,8 +298,14 @@ exports.builder = yargs =>
|
|
|
299
298
|
.number(types.number)
|
|
300
299
|
.alias(aliases);
|
|
301
300
|
|
|
302
|
-
exports.handler = argv
|
|
301
|
+
exports.handler = async function(argv) {
|
|
303
302
|
debug('post-yargs config', argv);
|
|
304
303
|
const mocha = new Mocha(argv);
|
|
305
|
-
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
await runMocha(mocha, argv);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
console.error('\n' + (err.stack || `Error: ${err.message || err}`));
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
306
311
|
};
|
package/lib/esm-utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const url = require('url');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const requireOrImport = async file => {
|
|
5
|
+
file = path.resolve(file);
|
|
6
|
+
|
|
7
|
+
if (path.extname(file) === '.mjs') {
|
|
8
|
+
return import(url.pathToFileURL(file));
|
|
9
|
+
}
|
|
10
|
+
// This is currently the only known way of figuring out whether a file is CJS or ESM.
|
|
11
|
+
// If Node.js or the community establish a better procedure for that, we can fix this code.
|
|
12
|
+
// Another option here would be to always use `import()`, as this also supports CJS, but I would be
|
|
13
|
+
// wary of using it for _all_ existing test files, till ESM is fully stable.
|
|
14
|
+
try {
|
|
15
|
+
return require(file);
|
|
16
|
+
} catch (err) {
|
|
17
|
+
if (err.code === 'ERR_REQUIRE_ESM') {
|
|
18
|
+
return import(url.pathToFileURL(file));
|
|
19
|
+
} else {
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
exports.loadFilesAsync = async (files, preLoadFunc, postLoadFunc) => {
|
|
26
|
+
for (const file of files) {
|
|
27
|
+
preLoadFunc(file);
|
|
28
|
+
const result = await requireOrImport(file);
|
|
29
|
+
postLoadFunc(file, result);
|
|
30
|
+
}
|
|
31
|
+
};
|
package/lib/mocha.js
CHANGED
|
@@ -14,6 +14,7 @@ var utils = require('./utils');
|
|
|
14
14
|
var mocharc = require('./mocharc.json');
|
|
15
15
|
var errors = require('./errors');
|
|
16
16
|
var Suite = require('./suite');
|
|
17
|
+
var esmUtils = utils.supportsEsModules() ? require('./esm-utils') : undefined;
|
|
17
18
|
var createStatsCollector = require('./stats-collector');
|
|
18
19
|
var createInvalidReporterError = errors.createInvalidReporterError;
|
|
19
20
|
var createInvalidInterfaceError = errors.createInvalidInterfaceError;
|
|
@@ -100,7 +101,10 @@ function Mocha(options) {
|
|
|
100
101
|
this.grep(options.grep)
|
|
101
102
|
.fgrep(options.fgrep)
|
|
102
103
|
.ui(options.ui)
|
|
103
|
-
.reporter(
|
|
104
|
+
.reporter(
|
|
105
|
+
options.reporter,
|
|
106
|
+
options.reporterOption || options.reporterOptions // reporterOptions was previously the only way to specify options to reporter
|
|
107
|
+
)
|
|
104
108
|
.slow(options.slow)
|
|
105
109
|
.global(options.global);
|
|
106
110
|
|
|
@@ -287,16 +291,18 @@ Mocha.prototype.ui = function(ui) {
|
|
|
287
291
|
};
|
|
288
292
|
|
|
289
293
|
/**
|
|
290
|
-
* Loads `files` prior to execution.
|
|
294
|
+
* Loads `files` prior to execution. Does not support ES Modules.
|
|
291
295
|
*
|
|
292
296
|
* @description
|
|
293
297
|
* The implementation relies on Node's `require` to execute
|
|
294
298
|
* the test interface functions and will be subject to its cache.
|
|
299
|
+
* Supports only CommonJS modules. To load ES modules, use Mocha#loadFilesAsync.
|
|
295
300
|
*
|
|
296
301
|
* @private
|
|
297
302
|
* @see {@link Mocha#addFile}
|
|
298
303
|
* @see {@link Mocha#run}
|
|
299
304
|
* @see {@link Mocha#unloadFiles}
|
|
305
|
+
* @see {@link Mocha#loadFilesAsync}
|
|
300
306
|
* @param {Function} [fn] - Callback invoked upon completion.
|
|
301
307
|
*/
|
|
302
308
|
Mocha.prototype.loadFiles = function(fn) {
|
|
@@ -311,6 +317,49 @@ Mocha.prototype.loadFiles = function(fn) {
|
|
|
311
317
|
fn && fn();
|
|
312
318
|
};
|
|
313
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Loads `files` prior to execution. Supports Node ES Modules.
|
|
322
|
+
*
|
|
323
|
+
* @description
|
|
324
|
+
* The implementation relies on Node's `require` and `import` to execute
|
|
325
|
+
* the test interface functions and will be subject to its cache.
|
|
326
|
+
* Supports both CJS and ESM modules.
|
|
327
|
+
*
|
|
328
|
+
* @public
|
|
329
|
+
* @see {@link Mocha#addFile}
|
|
330
|
+
* @see {@link Mocha#run}
|
|
331
|
+
* @see {@link Mocha#unloadFiles}
|
|
332
|
+
* @returns {Promise}
|
|
333
|
+
* @example
|
|
334
|
+
*
|
|
335
|
+
* // loads ESM (and CJS) test files asynchronously, then runs root suite
|
|
336
|
+
* mocha.loadFilesAsync()
|
|
337
|
+
* .then(() => mocha.run(failures => process.exitCode = failures ? 1 : 0))
|
|
338
|
+
* .catch(() => process.exitCode = 1);
|
|
339
|
+
*/
|
|
340
|
+
Mocha.prototype.loadFilesAsync = function() {
|
|
341
|
+
var self = this;
|
|
342
|
+
var suite = this.suite;
|
|
343
|
+
this.loadAsync = true;
|
|
344
|
+
|
|
345
|
+
if (!esmUtils) {
|
|
346
|
+
return new Promise(function(resolve) {
|
|
347
|
+
self.loadFiles(resolve);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return esmUtils.loadFilesAsync(
|
|
352
|
+
this.files,
|
|
353
|
+
function(file) {
|
|
354
|
+
suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
|
|
355
|
+
},
|
|
356
|
+
function(file, resultModule) {
|
|
357
|
+
suite.emit(EVENT_FILE_REQUIRE, resultModule, file, self);
|
|
358
|
+
suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
|
|
314
363
|
/**
|
|
315
364
|
* Removes a previously loaded file from Node's `require` cache.
|
|
316
365
|
*
|
|
@@ -327,8 +376,9 @@ Mocha.unloadFile = function(file) {
|
|
|
327
376
|
* Unloads `files` from Node's `require` cache.
|
|
328
377
|
*
|
|
329
378
|
* @description
|
|
330
|
-
* This allows files to be "freshly" reloaded, providing the ability
|
|
379
|
+
* This allows required files to be "freshly" reloaded, providing the ability
|
|
331
380
|
* to reuse a Mocha instance programmatically.
|
|
381
|
+
* Note: does not clear ESM module files from the cache
|
|
332
382
|
*
|
|
333
383
|
* <strong>Intended for consumers — not used internally</strong>
|
|
334
384
|
*
|
|
@@ -839,10 +889,14 @@ Object.defineProperty(Mocha.prototype, 'version', {
|
|
|
839
889
|
* @see {@link Mocha#unloadFiles}
|
|
840
890
|
* @see {@link Runner#run}
|
|
841
891
|
* @param {DoneCB} [fn] - Callback invoked when test execution completed.
|
|
842
|
-
* @
|
|
892
|
+
* @returns {Runner} runner instance
|
|
893
|
+
* @example
|
|
894
|
+
*
|
|
895
|
+
* // exit with non-zero status if there were test failures
|
|
896
|
+
* mocha.run(failures => process.exitCode = failures ? 1 : 0);
|
|
843
897
|
*/
|
|
844
898
|
Mocha.prototype.run = function(fn) {
|
|
845
|
-
if (this.files.length) {
|
|
899
|
+
if (this.files.length && !this.loadAsync) {
|
|
846
900
|
this.loadFiles();
|
|
847
901
|
}
|
|
848
902
|
var suite = this.suite;
|
package/lib/mocharc.json
CHANGED
package/lib/runnable.js
CHANGED
|
@@ -222,31 +222,6 @@ Runnable.prototype.clearTimeout = function() {
|
|
|
222
222
|
clearTimeout(this.timer);
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
-
/**
|
|
226
|
-
* Inspect the runnable void of private properties.
|
|
227
|
-
*
|
|
228
|
-
* @private
|
|
229
|
-
* @return {string}
|
|
230
|
-
*/
|
|
231
|
-
Runnable.prototype.inspect = function() {
|
|
232
|
-
return JSON.stringify(
|
|
233
|
-
this,
|
|
234
|
-
function(key, val) {
|
|
235
|
-
if (key[0] === '_') {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (key === 'parent') {
|
|
239
|
-
return '#<Suite>';
|
|
240
|
-
}
|
|
241
|
-
if (key === 'ctx') {
|
|
242
|
-
return '#<Context>';
|
|
243
|
-
}
|
|
244
|
-
return val;
|
|
245
|
-
},
|
|
246
|
-
2
|
|
247
|
-
);
|
|
248
|
-
};
|
|
249
|
-
|
|
250
225
|
/**
|
|
251
226
|
* Reset the timeout.
|
|
252
227
|
*
|
|
@@ -335,9 +310,18 @@ Runnable.prototype.run = function(fn) {
|
|
|
335
310
|
fn(err);
|
|
336
311
|
}
|
|
337
312
|
|
|
338
|
-
// for .resetTimeout()
|
|
313
|
+
// for .resetTimeout() and Runner#uncaught()
|
|
339
314
|
this.callback = done;
|
|
340
315
|
|
|
316
|
+
if (this.fn && typeof this.fn.call !== 'function') {
|
|
317
|
+
done(
|
|
318
|
+
new TypeError(
|
|
319
|
+
'A runnable must be passed a function as its second argument.'
|
|
320
|
+
)
|
|
321
|
+
);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
341
325
|
// explicit async with `done` argument
|
|
342
326
|
if (this.async) {
|
|
343
327
|
this.resetTimeout();
|
package/lib/runner.js
CHANGED
|
@@ -19,7 +19,6 @@ var EVENT_ROOT_SUITE_RUN = Suite.constants.EVENT_ROOT_SUITE_RUN;
|
|
|
19
19
|
var STATE_FAILED = Runnable.constants.STATE_FAILED;
|
|
20
20
|
var STATE_PASSED = Runnable.constants.STATE_PASSED;
|
|
21
21
|
var dQuote = utils.dQuote;
|
|
22
|
-
var ngettext = utils.ngettext;
|
|
23
22
|
var sQuote = utils.sQuote;
|
|
24
23
|
var stackFilter = utils.stackTraceFilter();
|
|
25
24
|
var stringify = utils.stringify;
|
|
@@ -135,6 +134,11 @@ function Runner(suite, delay) {
|
|
|
135
134
|
this.total = suite.total();
|
|
136
135
|
this.failures = 0;
|
|
137
136
|
this.on(constants.EVENT_TEST_END, function(test) {
|
|
137
|
+
if (test.type === 'test' && test.retriedTest() && test.parent) {
|
|
138
|
+
var idx =
|
|
139
|
+
test.parent.tests && test.parent.tests.indexOf(test.retriedTest());
|
|
140
|
+
if (idx > -1) test.parent.tests[idx] = test;
|
|
141
|
+
}
|
|
138
142
|
self.checkGlobals(test);
|
|
139
143
|
});
|
|
140
144
|
this.on(constants.EVENT_HOOK_END, function(hook) {
|
|
@@ -266,12 +270,8 @@ Runner.prototype.checkGlobals = function(test) {
|
|
|
266
270
|
this._globals = this._globals.concat(leaks);
|
|
267
271
|
|
|
268
272
|
if (leaks.length) {
|
|
269
|
-
var
|
|
270
|
-
|
|
271
|
-
'global leak detected: %s',
|
|
272
|
-
'global leaks detected: %s'
|
|
273
|
-
);
|
|
274
|
-
var error = new Error(util.format(format, leaks.map(sQuote).join(', ')));
|
|
273
|
+
var msg = 'global leak(s) detected: %s';
|
|
274
|
+
var error = new Error(util.format(msg, leaks.map(sQuote).join(', ')));
|
|
275
275
|
this.fail(test, error);
|
|
276
276
|
}
|
|
277
277
|
};
|
|
@@ -654,7 +654,7 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
654
654
|
self.emit(constants.EVENT_TEST_END, test);
|
|
655
655
|
// skip inner afterEach hooks below errSuite level
|
|
656
656
|
var origSuite = self.suite;
|
|
657
|
-
self.suite = errSuite;
|
|
657
|
+
self.suite = errSuite || self.suite;
|
|
658
658
|
return self.hookUp(HOOK_TYPE_AFTER_EACH, function(e, eSuite) {
|
|
659
659
|
self.suite = origSuite;
|
|
660
660
|
next(e, eSuite);
|
|
@@ -724,7 +724,6 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
724
724
|
var i = 0;
|
|
725
725
|
var self = this;
|
|
726
726
|
var total = this.grepTotal(suite);
|
|
727
|
-
var afterAllHookCalled = false;
|
|
728
727
|
|
|
729
728
|
debug('run suite %s', suite.fullTitle());
|
|
730
729
|
|
|
@@ -772,21 +771,13 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
772
771
|
self.suite = suite;
|
|
773
772
|
self.nextSuite = next;
|
|
774
773
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
} else {
|
|
778
|
-
// mark that the afterAll block has been called once
|
|
779
|
-
// and so can be skipped if there is an error in it.
|
|
780
|
-
afterAllHookCalled = true;
|
|
774
|
+
// remove reference to test
|
|
775
|
+
delete self.test;
|
|
781
776
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
self.emit(constants.EVENT_SUITE_END, suite);
|
|
787
|
-
fn(errSuite);
|
|
788
|
-
});
|
|
789
|
-
}
|
|
777
|
+
self.hook(HOOK_TYPE_AFTER_ALL, function() {
|
|
778
|
+
self.emit(constants.EVENT_SUITE_END, suite);
|
|
779
|
+
fn(errSuite);
|
|
780
|
+
});
|
|
790
781
|
}
|
|
791
782
|
|
|
792
783
|
this.nextSuite = next;
|
|
@@ -800,7 +791,7 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
800
791
|
};
|
|
801
792
|
|
|
802
793
|
/**
|
|
803
|
-
* Handle uncaught exceptions.
|
|
794
|
+
* Handle uncaught exceptions within runner.
|
|
804
795
|
*
|
|
805
796
|
* @param {Error} err
|
|
806
797
|
* @private
|
|
@@ -809,7 +800,8 @@ Runner.prototype.uncaught = function(err) {
|
|
|
809
800
|
if (err instanceof Pending) {
|
|
810
801
|
return;
|
|
811
802
|
}
|
|
812
|
-
|
|
803
|
+
// browser does not exit script when throwing in global.onerror()
|
|
804
|
+
if (this.allowUncaught && !process.browser) {
|
|
813
805
|
throw err;
|
|
814
806
|
}
|
|
815
807
|
|
|
@@ -861,36 +853,24 @@ Runner.prototype.uncaught = function(err) {
|
|
|
861
853
|
|
|
862
854
|
// we cannot recover gracefully if a Runnable has already passed
|
|
863
855
|
// then fails asynchronously
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
// recover from test
|
|
869
|
-
if (runnable.type === constants.EVENT_TEST_BEGIN) {
|
|
870
|
-
this.emit(constants.EVENT_TEST_END, runnable);
|
|
871
|
-
this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
|
|
872
|
-
return;
|
|
873
|
-
}
|
|
856
|
+
if (runnable.isPassed()) {
|
|
857
|
+
this.fail(runnable, err);
|
|
858
|
+
this.abort();
|
|
859
|
+
} else {
|
|
874
860
|
debug(runnable);
|
|
875
|
-
|
|
876
|
-
// recover from hooks
|
|
877
|
-
var errSuite = this.suite;
|
|
878
|
-
|
|
879
|
-
// XXX how about a less awful way to determine this?
|
|
880
|
-
// if hook failure is in afterEach block
|
|
881
|
-
if (runnable.fullTitle().indexOf('after each') > -1) {
|
|
882
|
-
return this.hookErr(err, errSuite, true);
|
|
883
|
-
}
|
|
884
|
-
// if hook failure is in beforeEach block
|
|
885
|
-
if (runnable.fullTitle().indexOf('before each') > -1) {
|
|
886
|
-
return this.hookErr(err, errSuite, false);
|
|
887
|
-
}
|
|
888
|
-
// if hook failure is in after or before blocks
|
|
889
|
-
return this.nextSuite(errSuite);
|
|
861
|
+
return runnable.callback(err);
|
|
890
862
|
}
|
|
863
|
+
};
|
|
891
864
|
|
|
892
|
-
|
|
893
|
-
|
|
865
|
+
/**
|
|
866
|
+
* Handle uncaught exceptions after runner's end event.
|
|
867
|
+
*
|
|
868
|
+
* @param {Error} err
|
|
869
|
+
* @private
|
|
870
|
+
*/
|
|
871
|
+
Runner.prototype.uncaughtEnd = function uncaughtEnd(err) {
|
|
872
|
+
if (err instanceof Pending) return;
|
|
873
|
+
throw err;
|
|
894
874
|
};
|
|
895
875
|
|
|
896
876
|
/**
|
|
@@ -940,16 +920,12 @@ Runner.prototype.run = function(fn) {
|
|
|
940
920
|
this.on(constants.EVENT_RUN_END, function() {
|
|
941
921
|
debug(constants.EVENT_RUN_END);
|
|
942
922
|
process.removeListener('uncaughtException', uncaught);
|
|
943
|
-
process.on('uncaughtException',
|
|
944
|
-
if (err instanceof Pending) {
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
throw err;
|
|
948
|
-
});
|
|
923
|
+
process.on('uncaughtException', self.uncaughtEnd);
|
|
949
924
|
fn(self.failures);
|
|
950
925
|
});
|
|
951
926
|
|
|
952
927
|
// uncaught exception
|
|
928
|
+
process.removeListener('uncaughtException', self.uncaughtEnd);
|
|
953
929
|
process.on('uncaughtException', uncaught);
|
|
954
930
|
|
|
955
931
|
if (this._delay) {
|
|
@@ -958,7 +934,9 @@ Runner.prototype.run = function(fn) {
|
|
|
958
934
|
this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
|
|
959
935
|
rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
|
|
960
936
|
} else {
|
|
961
|
-
|
|
937
|
+
Runner.immediately(function() {
|
|
938
|
+
start();
|
|
939
|
+
});
|
|
962
940
|
}
|
|
963
941
|
|
|
964
942
|
return this;
|
package/lib/test.js
CHANGED
|
@@ -36,6 +36,18 @@ function Test(title, fn) {
|
|
|
36
36
|
*/
|
|
37
37
|
utils.inherits(Test, Runnable);
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Set or get retried test
|
|
41
|
+
*
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
Test.prototype.retriedTest = function(n) {
|
|
45
|
+
if (!arguments.length) {
|
|
46
|
+
return this._retriedTest;
|
|
47
|
+
}
|
|
48
|
+
this._retriedTest = n;
|
|
49
|
+
};
|
|
50
|
+
|
|
39
51
|
Test.prototype.clone = function() {
|
|
40
52
|
var test = new Test(this.title, this.fn);
|
|
41
53
|
test.timeout(this.timeout());
|
|
@@ -43,6 +55,7 @@ Test.prototype.clone = function() {
|
|
|
43
55
|
test.enableTimeouts(this.enableTimeouts());
|
|
44
56
|
test.retries(this.retries());
|
|
45
57
|
test.currentRetry(this.currentRetry());
|
|
58
|
+
test.retriedTest(this.retriedTest() || this);
|
|
46
59
|
test.globals(this.globals());
|
|
47
60
|
test.parent = this.parent;
|
|
48
61
|
test.file = this.file;
|
package/lib/utils.js
CHANGED
|
@@ -753,38 +753,6 @@ exports.dQuote = function(str) {
|
|
|
753
753
|
return '"' + str + '"';
|
|
754
754
|
};
|
|
755
755
|
|
|
756
|
-
/**
|
|
757
|
-
* Provides simplistic message translation for dealing with plurality.
|
|
758
|
-
*
|
|
759
|
-
* @description
|
|
760
|
-
* Use this to create messages which need to be singular or plural.
|
|
761
|
-
* Some languages have several plural forms, so _complete_ message clauses
|
|
762
|
-
* are preferable to generating the message on the fly.
|
|
763
|
-
*
|
|
764
|
-
* @private
|
|
765
|
-
* @param {number} n - Non-negative integer
|
|
766
|
-
* @param {string} msg1 - Message to be used in English for `n = 1`
|
|
767
|
-
* @param {string} msg2 - Message to be used in English for `n = 0, 2, 3, ...`
|
|
768
|
-
* @returns {string} message corresponding to value of `n`
|
|
769
|
-
* @example
|
|
770
|
-
* var sprintf = require('util').format;
|
|
771
|
-
* var pkgs = ['one', 'two'];
|
|
772
|
-
* var msg = sprintf(
|
|
773
|
-
* ngettext(
|
|
774
|
-
* pkgs.length,
|
|
775
|
-
* 'cannot load package: %s',
|
|
776
|
-
* 'cannot load packages: %s'
|
|
777
|
-
* ),
|
|
778
|
-
* pkgs.map(sQuote).join(', ')
|
|
779
|
-
* );
|
|
780
|
-
* console.log(msg); // => cannot load packages: 'one', 'two'
|
|
781
|
-
*/
|
|
782
|
-
exports.ngettext = function(n, msg1, msg2) {
|
|
783
|
-
if (typeof n === 'number' && n >= 0) {
|
|
784
|
-
return n === 1 ? msg1 : msg2;
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
|
|
788
756
|
/**
|
|
789
757
|
* It's a noop.
|
|
790
758
|
* @public
|
|
@@ -831,3 +799,25 @@ exports.defineConstants = function(obj) {
|
|
|
831
799
|
}
|
|
832
800
|
return Object.freeze(exports.createMap(obj));
|
|
833
801
|
};
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Whether current version of Node support ES modules
|
|
805
|
+
*
|
|
806
|
+
* @description
|
|
807
|
+
* Versions prior to 10 did not support ES Modules, and version 10 has an old incompatibile version of ESM.
|
|
808
|
+
* This function returns whether Node.JS has ES Module supports that is compatible with Mocha's needs,
|
|
809
|
+
* which is version >=12.11.
|
|
810
|
+
*
|
|
811
|
+
* @returns {Boolean} whether the current version of Node.JS supports ES Modules in a way that is compatible with Mocha
|
|
812
|
+
*/
|
|
813
|
+
exports.supportsEsModules = function() {
|
|
814
|
+
if (!process.browser && process.versions && process.versions.node) {
|
|
815
|
+
var versionFields = process.versions.node.split('.');
|
|
816
|
+
var major = +versionFields[0];
|
|
817
|
+
var minor = +versionFields[1];
|
|
818
|
+
|
|
819
|
+
if (major >= 13 || (major === 12 && minor >= 11)) {
|
|
820
|
+
return true;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
};
|