mocha 8.2.1 → 8.4.0

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/lib/errors.js CHANGED
@@ -17,6 +17,7 @@ const emitWarning = (msg, type) => {
17
17
  if (process.emitWarning) {
18
18
  process.emitWarning(msg, type);
19
19
  } else {
20
+ /* istanbul ignore next */
20
21
  process.nextTick(function() {
21
22
  console.warn(type + ': ' + msg);
22
23
  });
@@ -53,88 +54,136 @@ const warn = msg => {
53
54
  };
54
55
 
55
56
  /**
56
- * When Mocha throw exceptions (or otherwise errors), it attempts to assign a
57
- * `code` property to the `Error` object, for easier handling. These are the
58
- * potential values of `code`.
57
+ * When Mocha throws exceptions (or rejects `Promise`s), it attempts to assign a `code` property to the `Error` object, for easier handling. These are the potential values of `code`.
58
+ * @public
59
+ * @namespace
60
+ * @memberof module:lib/errors
59
61
  */
60
62
  var constants = {
61
63
  /**
62
64
  * An unrecoverable error.
65
+ * @constant
66
+ * @default
63
67
  */
64
68
  FATAL: 'ERR_MOCHA_FATAL',
65
69
 
66
70
  /**
67
71
  * The type of an argument to a function call is invalid
72
+ * @constant
73
+ * @default
68
74
  */
69
75
  INVALID_ARG_TYPE: 'ERR_MOCHA_INVALID_ARG_TYPE',
70
76
 
71
77
  /**
72
78
  * The value of an argument to a function call is invalid
79
+ * @constant
80
+ * @default
73
81
  */
74
82
  INVALID_ARG_VALUE: 'ERR_MOCHA_INVALID_ARG_VALUE',
75
83
 
76
84
  /**
77
85
  * Something was thrown, but it wasn't an `Error`
86
+ * @constant
87
+ * @default
78
88
  */
79
89
  INVALID_EXCEPTION: 'ERR_MOCHA_INVALID_EXCEPTION',
80
90
 
81
91
  /**
82
92
  * An interface (e.g., `Mocha.interfaces`) is unknown or invalid
93
+ * @constant
94
+ * @default
83
95
  */
84
96
  INVALID_INTERFACE: 'ERR_MOCHA_INVALID_INTERFACE',
85
97
 
86
98
  /**
87
99
  * A reporter (.e.g, `Mocha.reporters`) is unknown or invalid
100
+ * @constant
101
+ * @default
88
102
  */
89
103
  INVALID_REPORTER: 'ERR_MOCHA_INVALID_REPORTER',
90
104
 
91
105
  /**
92
106
  * `done()` was called twice in a `Test` or `Hook` callback
107
+ * @constant
108
+ * @default
93
109
  */
94
110
  MULTIPLE_DONE: 'ERR_MOCHA_MULTIPLE_DONE',
95
111
 
96
112
  /**
97
113
  * No files matched the pattern provided by the user
114
+ * @constant
115
+ * @default
98
116
  */
99
117
  NO_FILES_MATCH_PATTERN: 'ERR_MOCHA_NO_FILES_MATCH_PATTERN',
100
118
 
101
119
  /**
102
120
  * Known, but unsupported behavior of some kind
121
+ * @constant
122
+ * @default
103
123
  */
104
124
  UNSUPPORTED: 'ERR_MOCHA_UNSUPPORTED',
105
125
 
106
126
  /**
107
127
  * Invalid state transition occurring in `Mocha` instance
128
+ * @constant
129
+ * @default
108
130
  */
109
131
  INSTANCE_ALREADY_RUNNING: 'ERR_MOCHA_INSTANCE_ALREADY_RUNNING',
110
132
 
111
133
  /**
112
134
  * Invalid state transition occurring in `Mocha` instance
135
+ * @constant
136
+ * @default
113
137
  */
114
138
  INSTANCE_ALREADY_DISPOSED: 'ERR_MOCHA_INSTANCE_ALREADY_DISPOSED',
115
139
 
116
140
  /**
117
141
  * Use of `only()` w/ `--forbid-only` results in this error.
142
+ * @constant
143
+ * @default
118
144
  */
119
145
  FORBIDDEN_EXCLUSIVITY: 'ERR_MOCHA_FORBIDDEN_EXCLUSIVITY',
120
146
 
121
147
  /**
122
148
  * To be thrown when a user-defined plugin implementation (e.g., `mochaHooks`) is invalid
149
+ * @constant
150
+ * @default
123
151
  */
124
152
  INVALID_PLUGIN_IMPLEMENTATION: 'ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION',
125
153
 
126
154
  /**
127
155
  * To be thrown when a builtin or third-party plugin definition (the _definition_ of `mochaHooks`) is invalid
156
+ * @constant
157
+ * @default
158
+ */
159
+ INVALID_PLUGIN_DEFINITION: 'ERR_MOCHA_INVALID_PLUGIN_DEFINITION',
160
+
161
+ /**
162
+ * When a runnable exceeds its allowed run time.
163
+ * @constant
164
+ * @default
128
165
  */
129
- INVALID_PLUGIN_DEFINITION: 'ERR_MOCHA_INVALID_PLUGIN_DEFINITION'
166
+ TIMEOUT: 'ERR_MOCHA_TIMEOUT',
167
+
168
+ /**
169
+ * Input file is not able to be parsed
170
+ * @constant
171
+ * @default
172
+ */
173
+ UNPARSABLE_FILE: 'ERR_MOCHA_UNPARSABLE_FILE'
130
174
  };
131
175
 
176
+ /**
177
+ * A set containing all string values of all Mocha error constants, for use by {@link isMochaError}.
178
+ * @private
179
+ */
132
180
  const MOCHA_ERRORS = new Set(Object.values(constants));
133
181
 
134
182
  /**
135
183
  * Creates an error object to be thrown when no files to be tested could be found using specified pattern.
136
184
  *
137
185
  * @public
186
+ * @static
138
187
  * @param {string} message - Error message to be displayed.
139
188
  * @param {string} pattern - User-specified argument value.
140
189
  * @returns {Error} instance detailing the error condition
@@ -165,6 +214,7 @@ function createInvalidReporterError(message, reporter) {
165
214
  * Creates an error object to be thrown when the interface specified in the options was not found.
166
215
  *
167
216
  * @public
217
+ * @static
168
218
  * @param {string} message - Error message to be displayed.
169
219
  * @param {string} ui - User-specified interface value.
170
220
  * @returns {Error} instance detailing the error condition
@@ -180,6 +230,7 @@ function createInvalidInterfaceError(message, ui) {
180
230
  * Creates an error object to be thrown when a behavior, option, or parameter is unsupported.
181
231
  *
182
232
  * @public
233
+ * @static
183
234
  * @param {string} message - Error message to be displayed.
184
235
  * @returns {Error} instance detailing the error condition
185
236
  */
@@ -193,6 +244,7 @@ function createUnsupportedError(message) {
193
244
  * Creates an error object to be thrown when an argument is missing.
194
245
  *
195
246
  * @public
247
+ * @static
196
248
  * @param {string} message - Error message to be displayed.
197
249
  * @param {string} argument - Argument name.
198
250
  * @param {string} expected - Expected argument datatype.
@@ -206,6 +258,7 @@ function createMissingArgumentError(message, argument, expected) {
206
258
  * Creates an error object to be thrown when an argument did not use the supported type
207
259
  *
208
260
  * @public
261
+ * @static
209
262
  * @param {string} message - Error message to be displayed.
210
263
  * @param {string} argument - Argument name.
211
264
  * @param {string} expected - Expected argument datatype.
@@ -224,6 +277,7 @@ function createInvalidArgumentTypeError(message, argument, expected) {
224
277
  * Creates an error object to be thrown when an argument did not use the supported value
225
278
  *
226
279
  * @public
280
+ * @static
227
281
  * @param {string} message - Error message to be displayed.
228
282
  * @param {string} argument - Argument name.
229
283
  * @param {string} value - Argument value.
@@ -243,6 +297,7 @@ function createInvalidArgumentValueError(message, argument, value, reason) {
243
297
  * Creates an error object to be thrown when an exception was caught, but the `Error` is falsy or undefined.
244
298
  *
245
299
  * @public
300
+ * @static
246
301
  * @param {string} message - Error message to be displayed.
247
302
  * @returns {Error} instance detailing the error condition
248
303
  */
@@ -258,6 +313,7 @@ function createInvalidExceptionError(message, value) {
258
313
  * Creates an error object to be thrown when an unrecoverable error occurs.
259
314
  *
260
315
  * @public
316
+ * @static
261
317
  * @param {string} message - Error message to be displayed.
262
318
  * @returns {Error} instance detailing the error condition
263
319
  */
@@ -276,6 +332,7 @@ function createFatalError(message, value) {
276
332
  * @param {string} [pluginId] - Name/path of plugin, if any
277
333
  * @throws When `pluginType` is not known
278
334
  * @public
335
+ * @static
279
336
  * @returns {Error}
280
337
  */
281
338
  function createInvalidLegacyPluginError(message, pluginType, pluginId) {
@@ -297,6 +354,7 @@ function createInvalidLegacyPluginError(message, pluginType, pluginId) {
297
354
  * @param {string} [pluginId] - Name/path of plugin, if any
298
355
  * @throws When `pluginType` is not known
299
356
  * @public
357
+ * @static
300
358
  * @returns {Error}
301
359
  */
302
360
  function createInvalidPluginError(...args) {
@@ -309,6 +367,7 @@ function createInvalidPluginError(...args) {
309
367
  * @param {string} message The error message to be displayed.
310
368
  * @param {boolean} cleanReferencesAfterRun the value of `cleanReferencesAfterRun`
311
369
  * @param {Mocha} instance the mocha instance that throw this error
370
+ * @static
312
371
  */
313
372
  function createMochaInstanceAlreadyDisposedError(
314
373
  message,
@@ -325,6 +384,8 @@ function createMochaInstanceAlreadyDisposedError(
325
384
  /**
326
385
  * Creates an error object to be thrown when a mocha object's `run` method is called while a test run is in progress.
327
386
  * @param {string} message The error message to be displayed.
387
+ * @static
388
+ * @public
328
389
  */
329
390
  function createMochaInstanceAlreadyRunningError(message, instance) {
330
391
  var err = new Error(message);
@@ -333,13 +394,14 @@ function createMochaInstanceAlreadyRunningError(message, instance) {
333
394
  return err;
334
395
  }
335
396
 
336
- /*
397
+ /**
337
398
  * Creates an error object to be thrown when done() is called multiple times in a test
338
399
  *
339
400
  * @public
340
401
  * @param {Runnable} runnable - Original runnable
341
402
  * @param {Error} [originalErr] - Original error, if any
342
403
  * @returns {Error} instance detailing the error condition
404
+ * @static
343
405
  */
344
406
  function createMultipleDoneError(runnable, originalErr) {
345
407
  var title;
@@ -373,6 +435,7 @@ function createMultipleDoneError(runnable, originalErr) {
373
435
  /**
374
436
  * Creates an error object to be thrown when `.only()` is used with
375
437
  * `--forbid-only`.
438
+ * @static
376
439
  * @public
377
440
  * @param {Mocha} mocha - Mocha instance
378
441
  * @returns {Error} Error with code {@link constants.FORBIDDEN_EXCLUSIVITY}
@@ -389,6 +452,7 @@ function createForbiddenExclusivityError(mocha) {
389
452
 
390
453
  /**
391
454
  * Creates an error object to be thrown when a plugin definition is invalid
455
+ * @static
392
456
  * @param {string} msg - Error message
393
457
  * @param {PluginDefinition} [pluginDef] - Problematic plugin definition
394
458
  * @public
@@ -403,6 +467,7 @@ function createInvalidPluginDefinitionError(msg, pluginDef) {
403
467
 
404
468
  /**
405
469
  * Creates an error object to be thrown when a plugin implementation (user code) is invalid
470
+ * @static
406
471
  * @param {string} msg - Error message
407
472
  * @param {Object} [opts] - Plugin definition and user-supplied implementation
408
473
  * @param {PluginDefinition} [opts.pluginDef] - Plugin Definition
@@ -421,9 +486,40 @@ function createInvalidPluginImplementationError(
421
486
  return err;
422
487
  }
423
488
 
489
+ /**
490
+ * Creates an error object to be thrown when a runnable exceeds its allowed run time.
491
+ * @static
492
+ * @param {string} msg - Error message
493
+ * @param {number} [timeout] - Timeout in ms
494
+ * @param {string} [file] - File, if given
495
+ * @returns {MochaTimeoutError}
496
+ */
497
+ function createTimeoutError(msg, timeout, file) {
498
+ const err = new Error(msg);
499
+ err.code = constants.TIMEOUT;
500
+ err.timeout = timeout;
501
+ err.file = file;
502
+ return err;
503
+ }
504
+
505
+ /**
506
+ * Creates an error object to be thrown when file is unparsable
507
+ * @public
508
+ * @static
509
+ * @param {string} message - Error message to be displayed.
510
+ * @param {string} filename - File name
511
+ * @returns {Error} Error with code {@link constants.UNPARSABLE_FILE}
512
+ */
513
+ function createUnparsableFileError(message, filename) {
514
+ var err = new Error(message);
515
+ err.code = constants.UNPARSABLE_FILE;
516
+ return err;
517
+ }
518
+
424
519
  /**
425
520
  * Returns `true` if an error came out of Mocha.
426
521
  * _Can suffer from false negatives, but not false positives._
522
+ * @static
427
523
  * @public
428
524
  * @param {*} err - Error, or anything
429
525
  * @returns {boolean}
@@ -449,8 +545,19 @@ module.exports = {
449
545
  createMochaInstanceAlreadyRunningError,
450
546
  createMultipleDoneError,
451
547
  createNoFilesMatchPatternError,
548
+ createTimeoutError,
549
+ createUnparsableFileError,
452
550
  createUnsupportedError,
453
551
  deprecate,
454
552
  isMochaError,
455
553
  warn
456
554
  };
555
+
556
+ /**
557
+ * The error thrown when a Runnable times out
558
+ * @memberof module:lib/errors
559
+ * @typedef {Error} MochaTimeoutError
560
+ * @property {constants.TIMEOUT} code - Error code
561
+ * @property {number?} timeout Timeout in ms
562
+ * @property {string?} file Filepath, if given
563
+ */
package/lib/esm-utils.js CHANGED
@@ -3,7 +3,29 @@ const url = require('url');
3
3
 
4
4
  const formattedImport = async file => {
5
5
  if (path.isAbsolute(file)) {
6
- return import(url.pathToFileURL(file));
6
+ try {
7
+ return await import(url.pathToFileURL(file));
8
+ } catch (err) {
9
+ // This is a hack created because ESM in Node.js (at least in Node v15.5.1) does not emit
10
+ // the location of the syntax error in the error thrown.
11
+ // This is problematic because the user can't see what file has the problem,
12
+ // so we add the file location to the error.
13
+ // This `if` should be removed once Node.js fixes the problem.
14
+ if (
15
+ err instanceof SyntaxError &&
16
+ err.message &&
17
+ err.stack &&
18
+ !err.stack.includes(file)
19
+ ) {
20
+ const newErrorWithFilename = new SyntaxError(err.message);
21
+ newErrorWithFilename.stack = err.stack.replace(
22
+ /^SyntaxError/,
23
+ `SyntaxError[ @${file} ]`
24
+ );
25
+ throw newErrorWithFilename;
26
+ }
27
+ throw err;
28
+ }
7
29
  }
8
30
  return import(file);
9
31
  };
@@ -105,13 +105,6 @@ module.exports = function bddInterface(suite) {
105
105
  context.xit = context.xspecify = context.it.skip = function(title) {
106
106
  return context.it(title);
107
107
  };
108
-
109
- /**
110
- * Number of attempts to retry.
111
- */
112
- context.it.retries = function(n) {
113
- context.retries(n);
114
- };
115
108
  });
116
109
  };
117
110
 
@@ -187,15 +187,6 @@ module.exports = function(suites, context, mocha) {
187
187
  */
188
188
  skip: function(title) {
189
189
  context.test(title);
190
- },
191
-
192
- /**
193
- * Number of retry attempts
194
- *
195
- * @param {number} n
196
- */
197
- retries: function(n) {
198
- context.retries(n);
199
190
  }
200
191
  }
201
192
  };
@@ -92,7 +92,6 @@ module.exports = function qUnitInterface(suite) {
92
92
  };
93
93
 
94
94
  context.test.skip = common.test.skip;
95
- context.test.retries = common.test.retries;
96
95
  });
97
96
  };
98
97
 
@@ -99,7 +99,6 @@ module.exports = function(suite) {
99
99
  };
100
100
 
101
101
  context.test.skip = common.test.skip;
102
- context.test.retries = common.test.retries;
103
102
  });
104
103
  };
105
104
 
package/lib/mocha.js CHANGED
@@ -96,6 +96,61 @@ exports.Suite = Suite;
96
96
  exports.Hook = require('./hook');
97
97
  exports.Test = require('./test');
98
98
 
99
+ let currentContext;
100
+ exports.afterEach = function(...args) {
101
+ return (currentContext.afterEach || currentContext.teardown).apply(
102
+ this,
103
+ args
104
+ );
105
+ };
106
+ exports.after = function(...args) {
107
+ return (currentContext.after || currentContext.suiteTeardown).apply(
108
+ this,
109
+ args
110
+ );
111
+ };
112
+ exports.beforeEach = function(...args) {
113
+ return (currentContext.beforeEach || currentContext.setup).apply(this, args);
114
+ };
115
+ exports.before = function(...args) {
116
+ return (currentContext.before || currentContext.suiteSetup).apply(this, args);
117
+ };
118
+ exports.describe = function(...args) {
119
+ return (currentContext.describe || currentContext.suite).apply(this, args);
120
+ };
121
+ exports.describe.only = function(...args) {
122
+ return (currentContext.describe || currentContext.suite).only.apply(
123
+ this,
124
+ args
125
+ );
126
+ };
127
+ exports.describe.skip = function(...args) {
128
+ return (currentContext.describe || currentContext.suite).skip.apply(
129
+ this,
130
+ args
131
+ );
132
+ };
133
+ exports.it = function(...args) {
134
+ return (currentContext.it || currentContext.test).apply(this, args);
135
+ };
136
+ exports.it.only = function(...args) {
137
+ return (currentContext.it || currentContext.test).only.apply(this, args);
138
+ };
139
+ exports.it.skip = function(...args) {
140
+ return (currentContext.it || currentContext.test).skip.apply(this, args);
141
+ };
142
+ exports.xdescribe = exports.describe.skip;
143
+ exports.xit = exports.it.skip;
144
+ exports.setup = exports.beforeEach;
145
+ exports.suiteSetup = exports.before;
146
+ exports.suiteTeardown = exports.after;
147
+ exports.suite = exports.describe;
148
+ exports.teardown = exports.afterEach;
149
+ exports.test = exports.it;
150
+ exports.run = function(...args) {
151
+ return currentContext.run.apply(this, args);
152
+ };
153
+
99
154
  /**
100
155
  * Constructs a new Mocha instance with `options`.
101
156
  *
@@ -125,10 +180,10 @@ exports.Test = require('./test');
125
180
  * @param {number} [options.slow] - Slow threshold value.
126
181
  * @param {number|string} [options.timeout] - Timeout threshold value.
127
182
  * @param {string} [options.ui] - Interface name.
128
- * @param {boolean} [options.parallel] - Run jobs in parallel
129
- * @param {number} [options.jobs] - Max number of worker processes for parallel runs
130
- * @param {MochaRootHookObject} [options.rootHooks] - Hooks to bootstrap the root
131
- * suite with
183
+ * @param {boolean} [options.parallel] - Run jobs in parallel.
184
+ * @param {number} [options.jobs] - Max number of worker processes for parallel runs.
185
+ * @param {MochaRootHookObject} [options.rootHooks] - Hooks to bootstrap the root suite with.
186
+ * @param {string[]} [options.require] - Pathname of `rootHooks` plugin for parallel runs.
132
187
  * @param {boolean} [options.isWorker] - Should be `true` if `Mocha` process is running in a worker process.
133
188
  */
134
189
  function Mocha(options = {}) {
@@ -351,20 +406,7 @@ Mocha.prototype.ui = function(ui) {
351
406
  bindInterface(this.suite);
352
407
 
353
408
  this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) {
354
- exports.afterEach = context.afterEach || context.teardown;
355
- exports.after = context.after || context.suiteTeardown;
356
- exports.beforeEach = context.beforeEach || context.setup;
357
- exports.before = context.before || context.suiteSetup;
358
- exports.describe = context.describe || context.suite;
359
- exports.it = context.it || context.test;
360
- exports.xit = context.xit || (context.test && context.test.skip);
361
- exports.setup = context.setup || context.beforeEach;
362
- exports.suiteSetup = context.suiteSetup || context.before;
363
- exports.suiteTeardown = context.suiteTeardown || context.after;
364
- exports.suite = context.suite || context.describe;
365
- exports.teardown = context.teardown || context.afterEach;
366
- exports.test = context.test || context.it;
367
- exports.run = context.run;
409
+ currentContext = context;
368
410
  });
369
411
 
370
412
  return this;
@@ -1299,7 +1341,7 @@ Mocha.prototype.hasGlobalTeardownFixtures = function hasGlobalTeardownFixtures()
1299
1341
  * A (sync) function to assert a user-supplied plugin implementation is valid.
1300
1342
  *
1301
1343
  * Defined in a {@link PluginDefinition}.
1302
-
1344
+
1303
1345
  * @callback PluginValidator
1304
1346
  * @param {*} value - Value to check
1305
1347
  * @this {PluginDefinition}
package/lib/runnable.js CHANGED
@@ -5,9 +5,11 @@ var Pending = require('./pending');
5
5
  var debug = require('debug')('mocha:runnable');
6
6
  var milliseconds = require('ms');
7
7
  var utils = require('./utils');
8
- var errors = require('./errors');
9
- var createInvalidExceptionError = errors.createInvalidExceptionError;
10
- var createMultipleDoneError = errors.createMultipleDoneError;
8
+ const {
9
+ createInvalidExceptionError,
10
+ createMultipleDoneError,
11
+ createTimeoutError
12
+ } = require('./errors');
11
13
 
12
14
  /**
13
15
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -422,14 +424,11 @@ Runnable.prototype.run = function(fn) {
422
424
  * @private
423
425
  */
424
426
  Runnable.prototype._timeoutError = function(ms) {
425
- var msg =
426
- 'Timeout of ' +
427
- ms +
428
- 'ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.';
427
+ let msg = `Timeout of ${ms}ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.`;
429
428
  if (this.file) {
430
429
  msg += ' (' + this.file + ')';
431
430
  }
432
- return new Error(msg);
431
+ return createTimeoutError(msg, ms, this.file);
433
432
  };
434
433
 
435
434
  var constants = utils.defineConstants(
package/lib/utils.js CHANGED
@@ -298,6 +298,9 @@ function jsonStringify(object, spaces, depth) {
298
298
  ? '-0'
299
299
  : val.toString();
300
300
  break;
301
+ case 'bigint':
302
+ val = val.toString() + 'n';
303
+ break;
301
304
  case 'date':
302
305
  var sDate = isNaN(val.getTime()) ? val.toString() : val.toISOString();
303
306
  val = '[Date: ' + sDate + ']';