mocha 9.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +1015 -0
  2. package/LICENSE +22 -0
  3. package/README.md +70 -0
  4. package/assets/growl/error.png +0 -0
  5. package/assets/growl/ok.png +0 -0
  6. package/bin/_mocha +10 -0
  7. package/bin/mocha +142 -0
  8. package/browser-entry.js +216 -0
  9. package/index.js +3 -0
  10. package/lib/browser/growl.js +169 -0
  11. package/lib/browser/highlight-tags.js +39 -0
  12. package/lib/browser/parse-query.js +24 -0
  13. package/lib/browser/progress.js +123 -0
  14. package/lib/browser/template.html +20 -0
  15. package/lib/cli/cli.js +89 -0
  16. package/lib/cli/collect-files.js +92 -0
  17. package/lib/cli/commands.js +13 -0
  18. package/lib/cli/config.js +105 -0
  19. package/lib/cli/index.js +3 -0
  20. package/lib/cli/init.js +36 -0
  21. package/lib/cli/lookup-files.js +145 -0
  22. package/lib/cli/node-flags.js +85 -0
  23. package/lib/cli/one-and-dones.js +69 -0
  24. package/lib/cli/options.js +261 -0
  25. package/lib/cli/run-helpers.js +243 -0
  26. package/lib/cli/run-option-metadata.js +117 -0
  27. package/lib/cli/run.js +379 -0
  28. package/lib/cli/watch-run.js +380 -0
  29. package/lib/context.js +86 -0
  30. package/lib/errors.js +563 -0
  31. package/lib/hook.js +89 -0
  32. package/lib/interfaces/bdd.js +111 -0
  33. package/lib/interfaces/common.js +193 -0
  34. package/lib/interfaces/exports.js +60 -0
  35. package/lib/interfaces/index.js +6 -0
  36. package/lib/interfaces/qunit.js +98 -0
  37. package/lib/interfaces/tdd.js +106 -0
  38. package/lib/mocha.js +1374 -0
  39. package/lib/mocharc.json +10 -0
  40. package/lib/nodejs/buffered-worker-pool.js +172 -0
  41. package/lib/nodejs/esm-utils.js +109 -0
  42. package/lib/nodejs/file-unloader.js +15 -0
  43. package/lib/nodejs/growl.js +137 -0
  44. package/lib/nodejs/parallel-buffered-runner.js +433 -0
  45. package/lib/nodejs/reporters/parallel-buffered.js +165 -0
  46. package/lib/nodejs/serializer.js +412 -0
  47. package/lib/nodejs/worker.js +151 -0
  48. package/lib/pending.js +16 -0
  49. package/lib/plugin-loader.js +286 -0
  50. package/lib/reporters/base.js +537 -0
  51. package/lib/reporters/doc.js +95 -0
  52. package/lib/reporters/dot.js +81 -0
  53. package/lib/reporters/html.js +390 -0
  54. package/lib/reporters/index.js +19 -0
  55. package/lib/reporters/json-stream.js +92 -0
  56. package/lib/reporters/json.js +162 -0
  57. package/lib/reporters/landing.js +116 -0
  58. package/lib/reporters/list.js +78 -0
  59. package/lib/reporters/markdown.js +112 -0
  60. package/lib/reporters/min.js +52 -0
  61. package/lib/reporters/nyan.js +276 -0
  62. package/lib/reporters/progress.js +104 -0
  63. package/lib/reporters/spec.js +99 -0
  64. package/lib/reporters/tap.js +293 -0
  65. package/lib/reporters/xunit.js +217 -0
  66. package/lib/runnable.js +476 -0
  67. package/lib/runner.js +1269 -0
  68. package/lib/stats-collector.js +83 -0
  69. package/lib/suite.js +695 -0
  70. package/lib/test.js +113 -0
  71. package/lib/utils.js +641 -0
  72. package/mocha-es2018.js +19816 -0
  73. package/mocha.css +325 -0
  74. package/mocha.js +30844 -0
  75. package/mocha.js.map +1 -0
  76. package/package.json +200 -0
package/lib/mocha.js ADDED
@@ -0,0 +1,1374 @@
1
+ 'use strict';
2
+
3
+ /*!
4
+ * mocha
5
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
6
+ * MIT Licensed
7
+ */
8
+
9
+ var escapeRe = require('escape-string-regexp');
10
+ var path = require('path');
11
+ var builtinReporters = require('./reporters');
12
+ var growl = require('./nodejs/growl');
13
+ var utils = require('./utils');
14
+ var mocharc = require('./mocharc.json');
15
+ var Suite = require('./suite');
16
+ var esmUtils = require('./nodejs/esm-utils');
17
+ var createStatsCollector = require('./stats-collector');
18
+ const {
19
+ warn,
20
+ createInvalidReporterError,
21
+ createInvalidInterfaceError,
22
+ createMochaInstanceAlreadyDisposedError,
23
+ createMochaInstanceAlreadyRunningError,
24
+ createUnsupportedError
25
+ } = require('./errors');
26
+ const {
27
+ EVENT_FILE_PRE_REQUIRE,
28
+ EVENT_FILE_POST_REQUIRE,
29
+ EVENT_FILE_REQUIRE
30
+ } = Suite.constants;
31
+ var debug = require('debug')('mocha:mocha');
32
+
33
+ exports = module.exports = Mocha;
34
+
35
+ /**
36
+ * A Mocha instance is a finite state machine.
37
+ * These are the states it can be in.
38
+ * @private
39
+ */
40
+ var mochaStates = utils.defineConstants({
41
+ /**
42
+ * Initial state of the mocha instance
43
+ * @private
44
+ */
45
+ INIT: 'init',
46
+ /**
47
+ * Mocha instance is running tests
48
+ * @private
49
+ */
50
+ RUNNING: 'running',
51
+ /**
52
+ * Mocha instance is done running tests and references to test functions and hooks are cleaned.
53
+ * You can reset this state by unloading the test files.
54
+ * @private
55
+ */
56
+ REFERENCES_CLEANED: 'referencesCleaned',
57
+ /**
58
+ * Mocha instance is disposed and can no longer be used.
59
+ * @private
60
+ */
61
+ DISPOSED: 'disposed'
62
+ });
63
+
64
+ /**
65
+ * To require local UIs and reporters when running in node.
66
+ */
67
+
68
+ if (!utils.isBrowser() && typeof module.paths !== 'undefined') {
69
+ var cwd = utils.cwd();
70
+ module.paths.push(cwd, path.join(cwd, 'node_modules'));
71
+ }
72
+
73
+ /**
74
+ * Expose internals.
75
+ * @private
76
+ */
77
+
78
+ exports.utils = utils;
79
+ exports.interfaces = require('./interfaces');
80
+ /**
81
+ * @public
82
+ * @memberof Mocha
83
+ */
84
+ exports.reporters = builtinReporters;
85
+ exports.Runnable = require('./runnable');
86
+ exports.Context = require('./context');
87
+ /**
88
+ *
89
+ * @memberof Mocha
90
+ */
91
+ exports.Runner = require('./runner');
92
+ exports.Suite = Suite;
93
+ exports.Hook = require('./hook');
94
+ exports.Test = require('./test');
95
+
96
+ let currentContext;
97
+ exports.afterEach = function(...args) {
98
+ return (currentContext.afterEach || currentContext.teardown).apply(
99
+ this,
100
+ args
101
+ );
102
+ };
103
+ exports.after = function(...args) {
104
+ return (currentContext.after || currentContext.suiteTeardown).apply(
105
+ this,
106
+ args
107
+ );
108
+ };
109
+ exports.beforeEach = function(...args) {
110
+ return (currentContext.beforeEach || currentContext.setup).apply(this, args);
111
+ };
112
+ exports.before = function(...args) {
113
+ return (currentContext.before || currentContext.suiteSetup).apply(this, args);
114
+ };
115
+ exports.describe = function(...args) {
116
+ return (currentContext.describe || currentContext.suite).apply(this, args);
117
+ };
118
+ exports.describe.only = function(...args) {
119
+ return (currentContext.describe || currentContext.suite).only.apply(
120
+ this,
121
+ args
122
+ );
123
+ };
124
+ exports.describe.skip = function(...args) {
125
+ return (currentContext.describe || currentContext.suite).skip.apply(
126
+ this,
127
+ args
128
+ );
129
+ };
130
+ exports.it = function(...args) {
131
+ return (currentContext.it || currentContext.test).apply(this, args);
132
+ };
133
+ exports.it.only = function(...args) {
134
+ return (currentContext.it || currentContext.test).only.apply(this, args);
135
+ };
136
+ exports.it.skip = function(...args) {
137
+ return (currentContext.it || currentContext.test).skip.apply(this, args);
138
+ };
139
+ exports.xdescribe = exports.describe.skip;
140
+ exports.xit = exports.it.skip;
141
+ exports.setup = exports.beforeEach;
142
+ exports.suiteSetup = exports.before;
143
+ exports.suiteTeardown = exports.after;
144
+ exports.suite = exports.describe;
145
+ exports.teardown = exports.afterEach;
146
+ exports.test = exports.it;
147
+ exports.run = function(...args) {
148
+ return currentContext.run.apply(this, args);
149
+ };
150
+
151
+ /**
152
+ * Constructs a new Mocha instance with `options`.
153
+ *
154
+ * @public
155
+ * @class Mocha
156
+ * @param {Object} [options] - Settings object.
157
+ * @param {boolean} [options.allowUncaught] - Propagate uncaught errors?
158
+ * @param {boolean} [options.asyncOnly] - Force `done` callback or promise?
159
+ * @param {boolean} [options.bail] - Bail after first test failure?
160
+ * @param {boolean} [options.checkLeaks] - Check for global variable leaks?
161
+ * @param {boolean} [options.color] - Color TTY output from reporter?
162
+ * @param {boolean} [options.delay] - Delay root suite execution?
163
+ * @param {boolean} [options.diff] - Show diff on failure?
164
+ * @param {boolean} [options.dryRun] - Report tests without running them?
165
+ * @param {boolean} [options.failZero] - Fail test run if zero tests?
166
+ * @param {string} [options.fgrep] - Test filter given string.
167
+ * @param {boolean} [options.forbidOnly] - Tests marked `only` fail the suite?
168
+ * @param {boolean} [options.forbidPending] - Pending tests fail the suite?
169
+ * @param {boolean} [options.fullTrace] - Full stacktrace upon failure?
170
+ * @param {string[]} [options.global] - Variables expected in global scope.
171
+ * @param {RegExp|string} [options.grep] - Test filter given regular expression.
172
+ * @param {boolean} [options.growl] - Enable desktop notifications?
173
+ * @param {boolean} [options.inlineDiffs] - Display inline diffs?
174
+ * @param {boolean} [options.invert] - Invert test filter matches?
175
+ * @param {boolean} [options.noHighlighting] - Disable syntax highlighting?
176
+ * @param {string|constructor} [options.reporter] - Reporter name or constructor.
177
+ * @param {Object} [options.reporterOption] - Reporter settings object.
178
+ * @param {number} [options.retries] - Number of times to retry failed tests.
179
+ * @param {number} [options.slow] - Slow threshold value.
180
+ * @param {number|string} [options.timeout] - Timeout threshold value.
181
+ * @param {string} [options.ui] - Interface name.
182
+ * @param {boolean} [options.parallel] - Run jobs in parallel.
183
+ * @param {number} [options.jobs] - Max number of worker processes for parallel runs.
184
+ * @param {MochaRootHookObject} [options.rootHooks] - Hooks to bootstrap the root suite with.
185
+ * @param {string[]} [options.require] - Pathname of `rootHooks` plugin for parallel runs.
186
+ * @param {boolean} [options.isWorker] - Should be `true` if `Mocha` process is running in a worker process.
187
+ */
188
+ function Mocha(options = {}) {
189
+ options = {...mocharc, ...options};
190
+ this.files = [];
191
+ this.options = options;
192
+ // root suite
193
+ this.suite = new exports.Suite('', new exports.Context(), true);
194
+ this._cleanReferencesAfterRun = true;
195
+ this._state = mochaStates.INIT;
196
+
197
+ this.grep(options.grep)
198
+ .fgrep(options.fgrep)
199
+ .ui(options.ui)
200
+ .reporter(
201
+ options.reporter,
202
+ options.reporterOption || options.reporterOptions // for backwards compability
203
+ )
204
+ .slow(options.slow)
205
+ .global(options.global);
206
+
207
+ // this guard exists because Suite#timeout does not consider `undefined` to be valid input
208
+ if (typeof options.timeout !== 'undefined') {
209
+ this.timeout(options.timeout === false ? 0 : options.timeout);
210
+ }
211
+
212
+ if ('retries' in options) {
213
+ this.retries(options.retries);
214
+ }
215
+
216
+ [
217
+ 'allowUncaught',
218
+ 'asyncOnly',
219
+ 'bail',
220
+ 'checkLeaks',
221
+ 'color',
222
+ 'delay',
223
+ 'diff',
224
+ 'dryRun',
225
+ 'failZero',
226
+ 'forbidOnly',
227
+ 'forbidPending',
228
+ 'fullTrace',
229
+ 'growl',
230
+ 'inlineDiffs',
231
+ 'invert'
232
+ ].forEach(function(opt) {
233
+ if (options[opt]) {
234
+ this[opt]();
235
+ }
236
+ }, this);
237
+
238
+ if (options.rootHooks) {
239
+ this.rootHooks(options.rootHooks);
240
+ }
241
+
242
+ /**
243
+ * The class which we'll instantiate in {@link Mocha#run}. Defaults to
244
+ * {@link Runner} in serial mode; changes in parallel mode.
245
+ * @memberof Mocha
246
+ * @private
247
+ */
248
+ this._runnerClass = exports.Runner;
249
+
250
+ /**
251
+ * Whether or not to call {@link Mocha#loadFiles} implicitly when calling
252
+ * {@link Mocha#run}. If this is `true`, then it's up to the consumer to call
253
+ * {@link Mocha#loadFiles} _or_ {@link Mocha#loadFilesAsync}.
254
+ * @private
255
+ * @memberof Mocha
256
+ */
257
+ this._lazyLoadFiles = false;
258
+
259
+ /**
260
+ * It's useful for a Mocha instance to know if it's running in a worker process.
261
+ * We could derive this via other means, but it's helpful to have a flag to refer to.
262
+ * @memberof Mocha
263
+ * @private
264
+ */
265
+ this.isWorker = Boolean(options.isWorker);
266
+
267
+ this.globalSetup(options.globalSetup)
268
+ .globalTeardown(options.globalTeardown)
269
+ .enableGlobalSetup(options.enableGlobalSetup)
270
+ .enableGlobalTeardown(options.enableGlobalTeardown);
271
+
272
+ if (
273
+ options.parallel &&
274
+ (typeof options.jobs === 'undefined' || options.jobs > 1)
275
+ ) {
276
+ debug('attempting to enable parallel mode');
277
+ this.parallelMode(true);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Enables or disables bailing on the first failure.
283
+ *
284
+ * @public
285
+ * @see [CLI option](../#-bail-b)
286
+ * @param {boolean} [bail=true] - Whether to bail on first error.
287
+ * @returns {Mocha} this
288
+ * @chainable
289
+ */
290
+ Mocha.prototype.bail = function(bail) {
291
+ this.suite.bail(bail !== false);
292
+ return this;
293
+ };
294
+
295
+ /**
296
+ * @summary
297
+ * Adds `file` to be loaded for execution.
298
+ *
299
+ * @description
300
+ * Useful for generic setup code that must be included within test suite.
301
+ *
302
+ * @public
303
+ * @see [CLI option](../#-file-filedirectoryglob)
304
+ * @param {string} file - Pathname of file to be loaded.
305
+ * @returns {Mocha} this
306
+ * @chainable
307
+ */
308
+ Mocha.prototype.addFile = function(file) {
309
+ this.files.push(file);
310
+ return this;
311
+ };
312
+
313
+ /**
314
+ * Sets reporter to `reporter`, defaults to "spec".
315
+ *
316
+ * @public
317
+ * @see [CLI option](../#-reporter-name-r-name)
318
+ * @see [Reporters](../#reporters)
319
+ * @param {String|Function} reporterName - Reporter name or constructor.
320
+ * @param {Object} [reporterOptions] - Options used to configure the reporter.
321
+ * @returns {Mocha} this
322
+ * @chainable
323
+ * @throws {Error} if requested reporter cannot be loaded
324
+ * @example
325
+ *
326
+ * // Use XUnit reporter and direct its output to file
327
+ * mocha.reporter('xunit', { output: '/path/to/testspec.xunit.xml' });
328
+ */
329
+ Mocha.prototype.reporter = function(reporterName, reporterOptions) {
330
+ if (typeof reporterName === 'function') {
331
+ this._reporter = reporterName;
332
+ } else {
333
+ reporterName = reporterName || 'spec';
334
+ var reporter;
335
+ // Try to load a built-in reporter.
336
+ if (builtinReporters[reporterName]) {
337
+ reporter = builtinReporters[reporterName];
338
+ }
339
+ // Try to load reporters from process.cwd() and node_modules
340
+ if (!reporter) {
341
+ try {
342
+ reporter = require(reporterName);
343
+ } catch (err) {
344
+ if (err.code === 'MODULE_NOT_FOUND') {
345
+ // Try to load reporters from a path (absolute or relative)
346
+ try {
347
+ reporter = require(path.resolve(utils.cwd(), reporterName));
348
+ } catch (_err) {
349
+ _err.code === 'MODULE_NOT_FOUND'
350
+ ? warn(`'${reporterName}' reporter not found`)
351
+ : warn(
352
+ `'${reporterName}' reporter blew up with error:\n ${err.stack}`
353
+ );
354
+ }
355
+ } else {
356
+ warn(`'${reporterName}' reporter blew up with error:\n ${err.stack}`);
357
+ }
358
+ }
359
+ }
360
+ if (!reporter) {
361
+ throw createInvalidReporterError(
362
+ `invalid reporter '${reporterName}'`,
363
+ reporterName
364
+ );
365
+ }
366
+ this._reporter = reporter;
367
+ }
368
+ this.options.reporterOption = reporterOptions;
369
+ // alias option name is used in public reporters xunit/tap/progress
370
+ this.options.reporterOptions = reporterOptions;
371
+ return this;
372
+ };
373
+
374
+ /**
375
+ * Sets test UI `name`, defaults to "bdd".
376
+ *
377
+ * @public
378
+ * @see [CLI option](../#-ui-name-u-name)
379
+ * @see [Interface DSLs](../#interfaces)
380
+ * @param {string|Function} [ui=bdd] - Interface name or class.
381
+ * @returns {Mocha} this
382
+ * @chainable
383
+ * @throws {Error} if requested interface cannot be loaded
384
+ */
385
+ Mocha.prototype.ui = function(ui) {
386
+ var bindInterface;
387
+ if (typeof ui === 'function') {
388
+ bindInterface = ui;
389
+ } else {
390
+ ui = ui || 'bdd';
391
+ bindInterface = exports.interfaces[ui];
392
+ if (!bindInterface) {
393
+ try {
394
+ bindInterface = require(ui);
395
+ } catch (err) {
396
+ throw createInvalidInterfaceError(`invalid interface '${ui}'`, ui);
397
+ }
398
+ }
399
+ }
400
+ bindInterface(this.suite);
401
+
402
+ this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) {
403
+ currentContext = context;
404
+ });
405
+
406
+ return this;
407
+ };
408
+
409
+ /**
410
+ * Loads `files` prior to execution. Does not support ES Modules.
411
+ *
412
+ * @description
413
+ * The implementation relies on Node's `require` to execute
414
+ * the test interface functions and will be subject to its cache.
415
+ * Supports only CommonJS modules. To load ES modules, use Mocha#loadFilesAsync.
416
+ *
417
+ * @private
418
+ * @see {@link Mocha#addFile}
419
+ * @see {@link Mocha#run}
420
+ * @see {@link Mocha#unloadFiles}
421
+ * @see {@link Mocha#loadFilesAsync}
422
+ * @param {Function} [fn] - Callback invoked upon completion.
423
+ */
424
+ Mocha.prototype.loadFiles = function(fn) {
425
+ var self = this;
426
+ var suite = this.suite;
427
+ this.files.forEach(function(file) {
428
+ file = path.resolve(file);
429
+ suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
430
+ suite.emit(EVENT_FILE_REQUIRE, require(file), file, self);
431
+ suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
432
+ });
433
+ fn && fn();
434
+ };
435
+
436
+ /**
437
+ * Loads `files` prior to execution. Supports Node ES Modules.
438
+ *
439
+ * @description
440
+ * The implementation relies on Node's `require` and `import` to execute
441
+ * the test interface functions and will be subject to its cache.
442
+ * Supports both CJS and ESM modules.
443
+ *
444
+ * @public
445
+ * @see {@link Mocha#addFile}
446
+ * @see {@link Mocha#run}
447
+ * @see {@link Mocha#unloadFiles}
448
+ * @returns {Promise}
449
+ * @example
450
+ *
451
+ * // loads ESM (and CJS) test files asynchronously, then runs root suite
452
+ * mocha.loadFilesAsync()
453
+ * .then(() => mocha.run(failures => process.exitCode = failures ? 1 : 0))
454
+ * .catch(() => process.exitCode = 1);
455
+ */
456
+ Mocha.prototype.loadFilesAsync = function() {
457
+ var self = this;
458
+ var suite = this.suite;
459
+ this.lazyLoadFiles(true);
460
+
461
+ return esmUtils.loadFilesAsync(
462
+ this.files,
463
+ function(file) {
464
+ suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
465
+ },
466
+ function(file, resultModule) {
467
+ suite.emit(EVENT_FILE_REQUIRE, resultModule, file, self);
468
+ suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
469
+ }
470
+ );
471
+ };
472
+
473
+ /**
474
+ * Removes a previously loaded file from Node's `require` cache.
475
+ *
476
+ * @private
477
+ * @static
478
+ * @see {@link Mocha#unloadFiles}
479
+ * @param {string} file - Pathname of file to be unloaded.
480
+ */
481
+ Mocha.unloadFile = function(file) {
482
+ if (utils.isBrowser()) {
483
+ throw createUnsupportedError(
484
+ 'unloadFile() is only suported in a Node.js environment'
485
+ );
486
+ }
487
+ return require('./nodejs/file-unloader').unloadFile(file);
488
+ };
489
+
490
+ /**
491
+ * Unloads `files` from Node's `require` cache.
492
+ *
493
+ * @description
494
+ * This allows required files to be "freshly" reloaded, providing the ability
495
+ * to reuse a Mocha instance programmatically.
496
+ * Note: does not clear ESM module files from the cache
497
+ *
498
+ * <strong>Intended for consumers &mdash; not used internally</strong>
499
+ *
500
+ * @public
501
+ * @see {@link Mocha#run}
502
+ * @returns {Mocha} this
503
+ * @chainable
504
+ */
505
+ Mocha.prototype.unloadFiles = function() {
506
+ if (this._state === mochaStates.DISPOSED) {
507
+ throw createMochaInstanceAlreadyDisposedError(
508
+ 'Mocha instance is already disposed, it cannot be used again.',
509
+ this._cleanReferencesAfterRun,
510
+ this
511
+ );
512
+ }
513
+
514
+ this.files.forEach(function(file) {
515
+ Mocha.unloadFile(file);
516
+ });
517
+ this._state = mochaStates.INIT;
518
+ return this;
519
+ };
520
+
521
+ /**
522
+ * Sets `grep` filter after escaping RegExp special characters.
523
+ *
524
+ * @public
525
+ * @see {@link Mocha#grep}
526
+ * @param {string} str - Value to be converted to a regexp.
527
+ * @returns {Mocha} this
528
+ * @chainable
529
+ * @example
530
+ *
531
+ * // Select tests whose full title begins with `"foo"` followed by a period
532
+ * mocha.fgrep('foo.');
533
+ */
534
+ Mocha.prototype.fgrep = function(str) {
535
+ if (!str) {
536
+ return this;
537
+ }
538
+ return this.grep(new RegExp(escapeRe(str)));
539
+ };
540
+
541
+ /**
542
+ * @summary
543
+ * Sets `grep` filter used to select specific tests for execution.
544
+ *
545
+ * @description
546
+ * If `re` is a regexp-like string, it will be converted to regexp.
547
+ * The regexp is tested against the full title of each test (i.e., the
548
+ * name of the test preceded by titles of each its ancestral suites).
549
+ * As such, using an <em>exact-match</em> fixed pattern against the
550
+ * test name itself will not yield any matches.
551
+ * <br>
552
+ * <strong>Previous filter value will be overwritten on each call!</strong>
553
+ *
554
+ * @public
555
+ * @see [CLI option](../#-grep-regexp-g-regexp)
556
+ * @see {@link Mocha#fgrep}
557
+ * @see {@link Mocha#invert}
558
+ * @param {RegExp|String} re - Regular expression used to select tests.
559
+ * @return {Mocha} this
560
+ * @chainable
561
+ * @example
562
+ *
563
+ * // Select tests whose full title contains `"match"`, ignoring case
564
+ * mocha.grep(/match/i);
565
+ * @example
566
+ *
567
+ * // Same as above but with regexp-like string argument
568
+ * mocha.grep('/match/i');
569
+ * @example
570
+ *
571
+ * // ## Anti-example
572
+ * // Given embedded test `it('only-this-test')`...
573
+ * mocha.grep('/^only-this-test$/'); // NO! Use `.only()` to do this!
574
+ */
575
+ Mocha.prototype.grep = function(re) {
576
+ if (utils.isString(re)) {
577
+ // extract args if it's regex-like, i.e: [string, pattern, flag]
578
+ var arg = re.match(/^\/(.*)\/([gimy]{0,4})$|.*/);
579
+ this.options.grep = new RegExp(arg[1] || arg[0], arg[2]);
580
+ } else {
581
+ this.options.grep = re;
582
+ }
583
+ return this;
584
+ };
585
+
586
+ /**
587
+ * Inverts `grep` matches.
588
+ *
589
+ * @public
590
+ * @see {@link Mocha#grep}
591
+ * @return {Mocha} this
592
+ * @chainable
593
+ * @example
594
+ *
595
+ * // Select tests whose full title does *not* contain `"match"`, ignoring case
596
+ * mocha.grep(/match/i).invert();
597
+ */
598
+ Mocha.prototype.invert = function() {
599
+ this.options.invert = true;
600
+ return this;
601
+ };
602
+
603
+ /**
604
+ * Enables or disables checking for global variables leaked while running tests.
605
+ *
606
+ * @public
607
+ * @see [CLI option](../#-check-leaks)
608
+ * @param {boolean} [checkLeaks=true] - Whether to check for global variable leaks.
609
+ * @return {Mocha} this
610
+ * @chainable
611
+ */
612
+ Mocha.prototype.checkLeaks = function(checkLeaks) {
613
+ this.options.checkLeaks = checkLeaks !== false;
614
+ return this;
615
+ };
616
+
617
+ /**
618
+ * Enables or disables whether or not to dispose after each test run.
619
+ * Disable this to ensure you can run the test suite multiple times.
620
+ * If disabled, be sure to dispose mocha when you're done to prevent memory leaks.
621
+ * @public
622
+ * @see {@link Mocha#dispose}
623
+ * @param {boolean} cleanReferencesAfterRun
624
+ * @return {Mocha} this
625
+ * @chainable
626
+ */
627
+ Mocha.prototype.cleanReferencesAfterRun = function(cleanReferencesAfterRun) {
628
+ this._cleanReferencesAfterRun = cleanReferencesAfterRun !== false;
629
+ return this;
630
+ };
631
+
632
+ /**
633
+ * Manually dispose this mocha instance. Mark this instance as `disposed` and unable to run more tests.
634
+ * It also removes function references to tests functions and hooks, so variables trapped in closures can be cleaned by the garbage collector.
635
+ * @public
636
+ */
637
+ Mocha.prototype.dispose = function() {
638
+ if (this._state === mochaStates.RUNNING) {
639
+ throw createMochaInstanceAlreadyRunningError(
640
+ 'Cannot dispose while the mocha instance is still running tests.'
641
+ );
642
+ }
643
+ this.unloadFiles();
644
+ this._previousRunner && this._previousRunner.dispose();
645
+ this.suite.dispose();
646
+ this._state = mochaStates.DISPOSED;
647
+ };
648
+
649
+ /**
650
+ * Displays full stack trace upon test failure.
651
+ *
652
+ * @public
653
+ * @see [CLI option](../#-full-trace)
654
+ * @param {boolean} [fullTrace=true] - Whether to print full stacktrace upon failure.
655
+ * @return {Mocha} this
656
+ * @chainable
657
+ */
658
+ Mocha.prototype.fullTrace = function(fullTrace) {
659
+ this.options.fullTrace = fullTrace !== false;
660
+ return this;
661
+ };
662
+
663
+ /**
664
+ * Enables desktop notification support if prerequisite software installed.
665
+ *
666
+ * @public
667
+ * @see [CLI option](../#-growl-g)
668
+ * @return {Mocha} this
669
+ * @chainable
670
+ */
671
+ Mocha.prototype.growl = function() {
672
+ this.options.growl = this.isGrowlCapable();
673
+ if (!this.options.growl) {
674
+ var detail = utils.isBrowser()
675
+ ? 'notification support not available in this browser...'
676
+ : 'notification support prerequisites not installed...';
677
+ console.error(detail + ' cannot enable!');
678
+ }
679
+ return this;
680
+ };
681
+
682
+ /**
683
+ * @summary
684
+ * Determines if Growl support seems likely.
685
+ *
686
+ * @description
687
+ * <strong>Not available when run in browser.</strong>
688
+ *
689
+ * @private
690
+ * @see {@link Growl#isCapable}
691
+ * @see {@link Mocha#growl}
692
+ * @return {boolean} whether Growl support can be expected
693
+ */
694
+ Mocha.prototype.isGrowlCapable = growl.isCapable;
695
+
696
+ /**
697
+ * Implements desktop notifications using a pseudo-reporter.
698
+ *
699
+ * @private
700
+ * @see {@link Mocha#growl}
701
+ * @see {@link Growl#notify}
702
+ * @param {Runner} runner - Runner instance.
703
+ */
704
+ Mocha.prototype._growl = growl.notify;
705
+
706
+ /**
707
+ * Specifies whitelist of variable names to be expected in global scope.
708
+ *
709
+ * @public
710
+ * @see [CLI option](../#-global-variable-name)
711
+ * @see {@link Mocha#checkLeaks}
712
+ * @param {String[]|String} global - Accepted global variable name(s).
713
+ * @return {Mocha} this
714
+ * @chainable
715
+ * @example
716
+ *
717
+ * // Specify variables to be expected in global scope
718
+ * mocha.global(['jQuery', 'MyLib']);
719
+ */
720
+ Mocha.prototype.global = function(global) {
721
+ this.options.global = (this.options.global || [])
722
+ .concat(global)
723
+ .filter(Boolean)
724
+ .filter(function(elt, idx, arr) {
725
+ return arr.indexOf(elt) === idx;
726
+ });
727
+ return this;
728
+ };
729
+ // for backwards compability, 'globals' is an alias of 'global'
730
+ Mocha.prototype.globals = Mocha.prototype.global;
731
+
732
+ /**
733
+ * Enables or disables TTY color output by screen-oriented reporters.
734
+ *
735
+ * @public
736
+ * @see [CLI option](../#-color-c-colors)
737
+ * @param {boolean} [color=true] - Whether to enable color output.
738
+ * @return {Mocha} this
739
+ * @chainable
740
+ */
741
+ Mocha.prototype.color = function(color) {
742
+ this.options.color = color !== false;
743
+ return this;
744
+ };
745
+
746
+ /**
747
+ * Enables or disables reporter to use inline diffs (rather than +/-)
748
+ * in test failure output.
749
+ *
750
+ * @public
751
+ * @see [CLI option](../#-inline-diffs)
752
+ * @param {boolean} [inlineDiffs=true] - Whether to use inline diffs.
753
+ * @return {Mocha} this
754
+ * @chainable
755
+ */
756
+ Mocha.prototype.inlineDiffs = function(inlineDiffs) {
757
+ this.options.inlineDiffs = inlineDiffs !== false;
758
+ return this;
759
+ };
760
+
761
+ /**
762
+ * Enables or disables reporter to include diff in test failure output.
763
+ *
764
+ * @public
765
+ * @see [CLI option](../#-diff)
766
+ * @param {boolean} [diff=true] - Whether to show diff on failure.
767
+ * @return {Mocha} this
768
+ * @chainable
769
+ */
770
+ Mocha.prototype.diff = function(diff) {
771
+ this.options.diff = diff !== false;
772
+ return this;
773
+ };
774
+
775
+ /**
776
+ * @summary
777
+ * Sets timeout threshold value.
778
+ *
779
+ * @description
780
+ * A string argument can use shorthand (such as "2s") and will be converted.
781
+ * If the value is `0`, timeouts will be disabled.
782
+ *
783
+ * @public
784
+ * @see [CLI option](../#-timeout-ms-t-ms)
785
+ * @see [Timeouts](../#timeouts)
786
+ * @param {number|string} msecs - Timeout threshold value.
787
+ * @return {Mocha} this
788
+ * @chainable
789
+ * @example
790
+ *
791
+ * // Sets timeout to one second
792
+ * mocha.timeout(1000);
793
+ * @example
794
+ *
795
+ * // Same as above but using string argument
796
+ * mocha.timeout('1s');
797
+ */
798
+ Mocha.prototype.timeout = function(msecs) {
799
+ this.suite.timeout(msecs);
800
+ return this;
801
+ };
802
+
803
+ /**
804
+ * Sets the number of times to retry failed tests.
805
+ *
806
+ * @public
807
+ * @see [CLI option](../#-retries-n)
808
+ * @see [Retry Tests](../#retry-tests)
809
+ * @param {number} retry - Number of times to retry failed tests.
810
+ * @return {Mocha} this
811
+ * @chainable
812
+ * @example
813
+ *
814
+ * // Allow any failed test to retry one more time
815
+ * mocha.retries(1);
816
+ */
817
+ Mocha.prototype.retries = function(retry) {
818
+ this.suite.retries(retry);
819
+ return this;
820
+ };
821
+
822
+ /**
823
+ * Sets slowness threshold value.
824
+ *
825
+ * @public
826
+ * @see [CLI option](../#-slow-ms-s-ms)
827
+ * @param {number} msecs - Slowness threshold value.
828
+ * @return {Mocha} this
829
+ * @chainable
830
+ * @example
831
+ *
832
+ * // Sets "slow" threshold to half a second
833
+ * mocha.slow(500);
834
+ * @example
835
+ *
836
+ * // Same as above but using string argument
837
+ * mocha.slow('0.5s');
838
+ */
839
+ Mocha.prototype.slow = function(msecs) {
840
+ this.suite.slow(msecs);
841
+ return this;
842
+ };
843
+
844
+ /**
845
+ * Forces all tests to either accept a `done` callback or return a promise.
846
+ *
847
+ * @public
848
+ * @see [CLI option](../#-async-only-a)
849
+ * @param {boolean} [asyncOnly=true] - Whether to force `done` callback or promise.
850
+ * @return {Mocha} this
851
+ * @chainable
852
+ */
853
+ Mocha.prototype.asyncOnly = function(asyncOnly) {
854
+ this.options.asyncOnly = asyncOnly !== false;
855
+ return this;
856
+ };
857
+
858
+ /**
859
+ * Disables syntax highlighting (in browser).
860
+ *
861
+ * @public
862
+ * @return {Mocha} this
863
+ * @chainable
864
+ */
865
+ Mocha.prototype.noHighlighting = function() {
866
+ this.options.noHighlighting = true;
867
+ return this;
868
+ };
869
+
870
+ /**
871
+ * Enables or disables uncaught errors to propagate.
872
+ *
873
+ * @public
874
+ * @see [CLI option](../#-allow-uncaught)
875
+ * @param {boolean} [allowUncaught=true] - Whether to propagate uncaught errors.
876
+ * @return {Mocha} this
877
+ * @chainable
878
+ */
879
+ Mocha.prototype.allowUncaught = function(allowUncaught) {
880
+ this.options.allowUncaught = allowUncaught !== false;
881
+ return this;
882
+ };
883
+
884
+ /**
885
+ * @summary
886
+ * Delays root suite execution.
887
+ *
888
+ * @description
889
+ * Used to perform async operations before any suites are run.
890
+ *
891
+ * @public
892
+ * @see [delayed root suite](../#delayed-root-suite)
893
+ * @returns {Mocha} this
894
+ * @chainable
895
+ */
896
+ Mocha.prototype.delay = function delay() {
897
+ this.options.delay = true;
898
+ return this;
899
+ };
900
+
901
+ /**
902
+ * Enables or disables running tests in dry-run mode.
903
+ *
904
+ * @public
905
+ * @see [CLI option](../#-dry-run)
906
+ * @param {boolean} [dryRun=true] - Whether to activate dry-run mode.
907
+ * @return {Mocha} this
908
+ * @chainable
909
+ */
910
+ Mocha.prototype.dryRun = function(dryRun) {
911
+ this.options.dryRun = dryRun !== false;
912
+ return this;
913
+ };
914
+
915
+ /**
916
+ * Fails test run if no tests encountered with exit-code 1.
917
+ *
918
+ * @public
919
+ * @see [CLI option](../#-fail-zero)
920
+ * @param {boolean} [failZero=true] - Whether to fail test run.
921
+ * @return {Mocha} this
922
+ * @chainable
923
+ */
924
+ Mocha.prototype.failZero = function(failZero) {
925
+ this.options.failZero = failZero !== false;
926
+ return this;
927
+ };
928
+
929
+ /**
930
+ * Causes tests marked `only` to fail the suite.
931
+ *
932
+ * @public
933
+ * @see [CLI option](../#-forbid-only)
934
+ * @param {boolean} [forbidOnly=true] - Whether tests marked `only` fail the suite.
935
+ * @returns {Mocha} this
936
+ * @chainable
937
+ */
938
+ Mocha.prototype.forbidOnly = function(forbidOnly) {
939
+ this.options.forbidOnly = forbidOnly !== false;
940
+ return this;
941
+ };
942
+
943
+ /**
944
+ * Causes pending tests and tests marked `skip` to fail the suite.
945
+ *
946
+ * @public
947
+ * @see [CLI option](../#-forbid-pending)
948
+ * @param {boolean} [forbidPending=true] - Whether pending tests fail the suite.
949
+ * @returns {Mocha} this
950
+ * @chainable
951
+ */
952
+ Mocha.prototype.forbidPending = function(forbidPending) {
953
+ this.options.forbidPending = forbidPending !== false;
954
+ return this;
955
+ };
956
+
957
+ /**
958
+ * Throws an error if mocha is in the wrong state to be able to transition to a "running" state.
959
+ * @private
960
+ */
961
+ Mocha.prototype._guardRunningStateTransition = function() {
962
+ if (this._state === mochaStates.RUNNING) {
963
+ throw createMochaInstanceAlreadyRunningError(
964
+ 'Mocha instance is currently running tests, cannot start a next test run until this one is done',
965
+ this
966
+ );
967
+ }
968
+ if (
969
+ this._state === mochaStates.DISPOSED ||
970
+ this._state === mochaStates.REFERENCES_CLEANED
971
+ ) {
972
+ throw createMochaInstanceAlreadyDisposedError(
973
+ 'Mocha instance is already disposed, cannot start a new test run. Please create a new mocha instance. Be sure to set disable `cleanReferencesAfterRun` when you want to reuse the same mocha instance for multiple test runs.',
974
+ this._cleanReferencesAfterRun,
975
+ this
976
+ );
977
+ }
978
+ };
979
+
980
+ /**
981
+ * Mocha version as specified by "package.json".
982
+ *
983
+ * @name Mocha#version
984
+ * @type string
985
+ * @readonly
986
+ */
987
+ Object.defineProperty(Mocha.prototype, 'version', {
988
+ value: require('../package.json').version,
989
+ configurable: false,
990
+ enumerable: true,
991
+ writable: false
992
+ });
993
+
994
+ /**
995
+ * Callback to be invoked when test execution is complete.
996
+ *
997
+ * @private
998
+ * @callback DoneCB
999
+ * @param {number} failures - Number of failures that occurred.
1000
+ */
1001
+
1002
+ /**
1003
+ * Runs root suite and invokes `fn()` when complete.
1004
+ *
1005
+ * @description
1006
+ * To run tests multiple times (or to run tests in files that are
1007
+ * already in the `require` cache), make sure to clear them from
1008
+ * the cache first!
1009
+ *
1010
+ * @public
1011
+ * @see {@link Mocha#unloadFiles}
1012
+ * @see {@link Runner#run}
1013
+ * @param {DoneCB} [fn] - Callback invoked when test execution completed.
1014
+ * @returns {Runner} runner instance
1015
+ * @example
1016
+ *
1017
+ * // exit with non-zero status if there were test failures
1018
+ * mocha.run(failures => process.exitCode = failures ? 1 : 0);
1019
+ */
1020
+ Mocha.prototype.run = function(fn) {
1021
+ this._guardRunningStateTransition();
1022
+ this._state = mochaStates.RUNNING;
1023
+ if (this._previousRunner) {
1024
+ this._previousRunner.dispose();
1025
+ this.suite.reset();
1026
+ }
1027
+ if (this.files.length && !this._lazyLoadFiles) {
1028
+ this.loadFiles();
1029
+ }
1030
+ var suite = this.suite;
1031
+ var options = this.options;
1032
+ options.files = this.files;
1033
+ const runner = new this._runnerClass(suite, {
1034
+ cleanReferencesAfterRun: this._cleanReferencesAfterRun,
1035
+ delay: options.delay,
1036
+ dryRun: options.dryRun,
1037
+ failZero: options.failZero
1038
+ });
1039
+ createStatsCollector(runner);
1040
+ var reporter = new this._reporter(runner, options);
1041
+ runner.checkLeaks = options.checkLeaks === true;
1042
+ runner.fullStackTrace = options.fullTrace;
1043
+ runner.asyncOnly = options.asyncOnly;
1044
+ runner.allowUncaught = options.allowUncaught;
1045
+ runner.forbidOnly = options.forbidOnly;
1046
+ runner.forbidPending = options.forbidPending;
1047
+ if (options.grep) {
1048
+ runner.grep(options.grep, options.invert);
1049
+ }
1050
+ if (options.global) {
1051
+ runner.globals(options.global);
1052
+ }
1053
+ if (options.growl) {
1054
+ this._growl(runner);
1055
+ }
1056
+ if (options.color !== undefined) {
1057
+ exports.reporters.Base.useColors = options.color;
1058
+ }
1059
+ exports.reporters.Base.inlineDiffs = options.inlineDiffs;
1060
+ exports.reporters.Base.hideDiff = !options.diff;
1061
+
1062
+ const done = failures => {
1063
+ this._previousRunner = runner;
1064
+ this._state = this._cleanReferencesAfterRun
1065
+ ? mochaStates.REFERENCES_CLEANED
1066
+ : mochaStates.INIT;
1067
+ fn = fn || utils.noop;
1068
+ if (typeof reporter.done === 'function') {
1069
+ reporter.done(failures, fn);
1070
+ } else {
1071
+ fn(failures);
1072
+ }
1073
+ };
1074
+
1075
+ const runAsync = async runner => {
1076
+ const context =
1077
+ this.options.enableGlobalSetup && this.hasGlobalSetupFixtures()
1078
+ ? await this.runGlobalSetup(runner)
1079
+ : {};
1080
+ const failureCount = await runner.runAsync({
1081
+ files: this.files,
1082
+ options
1083
+ });
1084
+ if (this.options.enableGlobalTeardown && this.hasGlobalTeardownFixtures()) {
1085
+ await this.runGlobalTeardown(runner, {context});
1086
+ }
1087
+ return failureCount;
1088
+ };
1089
+
1090
+ // no "catch" here is intentional. errors coming out of
1091
+ // Runner#run are considered uncaught/unhandled and caught
1092
+ // by the `process` event listeners.
1093
+ // also: returning anything other than `runner` would be a breaking
1094
+ // change
1095
+ runAsync(runner).then(done);
1096
+
1097
+ return runner;
1098
+ };
1099
+
1100
+ /**
1101
+ * Assigns hooks to the root suite
1102
+ * @param {MochaRootHookObject} [hooks] - Hooks to assign to root suite
1103
+ * @chainable
1104
+ */
1105
+ Mocha.prototype.rootHooks = function rootHooks({
1106
+ beforeAll = [],
1107
+ beforeEach = [],
1108
+ afterAll = [],
1109
+ afterEach = []
1110
+ } = {}) {
1111
+ beforeAll = utils.castArray(beforeAll);
1112
+ beforeEach = utils.castArray(beforeEach);
1113
+ afterAll = utils.castArray(afterAll);
1114
+ afterEach = utils.castArray(afterEach);
1115
+ beforeAll.forEach(hook => {
1116
+ this.suite.beforeAll(hook);
1117
+ });
1118
+ beforeEach.forEach(hook => {
1119
+ this.suite.beforeEach(hook);
1120
+ });
1121
+ afterAll.forEach(hook => {
1122
+ this.suite.afterAll(hook);
1123
+ });
1124
+ afterEach.forEach(hook => {
1125
+ this.suite.afterEach(hook);
1126
+ });
1127
+ return this;
1128
+ };
1129
+
1130
+ /**
1131
+ * Toggles parallel mode.
1132
+ *
1133
+ * Must be run before calling {@link Mocha#run}. Changes the `Runner` class to
1134
+ * use; also enables lazy file loading if not already done so.
1135
+ *
1136
+ * Warning: when passed `false` and lazy loading has been enabled _via any means_ (including calling `parallelMode(true)`), this method will _not_ disable lazy loading. Lazy loading is a prerequisite for parallel
1137
+ * mode, but parallel mode is _not_ a prerequisite for lazy loading!
1138
+ * @param {boolean} [enable] - If `true`, enable; otherwise disable.
1139
+ * @throws If run in browser
1140
+ * @throws If Mocha not in `INIT` state
1141
+ * @returns {Mocha}
1142
+ * @chainable
1143
+ * @public
1144
+ */
1145
+ Mocha.prototype.parallelMode = function parallelMode(enable = true) {
1146
+ if (utils.isBrowser()) {
1147
+ throw createUnsupportedError('parallel mode is only supported in Node.js');
1148
+ }
1149
+ const parallel = Boolean(enable);
1150
+ if (
1151
+ parallel === this.options.parallel &&
1152
+ this._lazyLoadFiles &&
1153
+ this._runnerClass !== exports.Runner
1154
+ ) {
1155
+ return this;
1156
+ }
1157
+ if (this._state !== mochaStates.INIT) {
1158
+ throw createUnsupportedError(
1159
+ 'cannot change parallel mode after having called run()'
1160
+ );
1161
+ }
1162
+ this.options.parallel = parallel;
1163
+
1164
+ // swap Runner class
1165
+ this._runnerClass = parallel
1166
+ ? require('./nodejs/parallel-buffered-runner')
1167
+ : exports.Runner;
1168
+
1169
+ // lazyLoadFiles may have been set `true` otherwise (for ESM loading),
1170
+ // so keep `true` if so.
1171
+ return this.lazyLoadFiles(this._lazyLoadFiles || parallel);
1172
+ };
1173
+
1174
+ /**
1175
+ * Disables implicit call to {@link Mocha#loadFiles} in {@link Mocha#run}. This
1176
+ * setting is used by watch mode, parallel mode, and for loading ESM files.
1177
+ * @todo This should throw if we've already loaded files; such behavior
1178
+ * necessitates adding a new state.
1179
+ * @param {boolean} [enable] - If `true`, disable eager loading of files in
1180
+ * {@link Mocha#run}
1181
+ * @chainable
1182
+ * @public
1183
+ */
1184
+ Mocha.prototype.lazyLoadFiles = function lazyLoadFiles(enable) {
1185
+ this._lazyLoadFiles = enable === true;
1186
+ debug('set lazy load to %s', enable);
1187
+ return this;
1188
+ };
1189
+
1190
+ /**
1191
+ * Configures one or more global setup fixtures.
1192
+ *
1193
+ * If given no parameters, _unsets_ any previously-set fixtures.
1194
+ * @chainable
1195
+ * @public
1196
+ * @param {MochaGlobalFixture|MochaGlobalFixture[]} [setupFns] - Global setup fixture(s)
1197
+ * @returns {Mocha}
1198
+ */
1199
+ Mocha.prototype.globalSetup = function globalSetup(setupFns = []) {
1200
+ setupFns = utils.castArray(setupFns);
1201
+ this.options.globalSetup = setupFns;
1202
+ debug('configured %d global setup functions', setupFns.length);
1203
+ return this;
1204
+ };
1205
+
1206
+ /**
1207
+ * Configures one or more global teardown fixtures.
1208
+ *
1209
+ * If given no parameters, _unsets_ any previously-set fixtures.
1210
+ * @chainable
1211
+ * @public
1212
+ * @param {MochaGlobalFixture|MochaGlobalFixture[]} [teardownFns] - Global teardown fixture(s)
1213
+ * @returns {Mocha}
1214
+ */
1215
+ Mocha.prototype.globalTeardown = function globalTeardown(teardownFns = []) {
1216
+ teardownFns = utils.castArray(teardownFns);
1217
+ this.options.globalTeardown = teardownFns;
1218
+ debug('configured %d global teardown functions', teardownFns.length);
1219
+ return this;
1220
+ };
1221
+
1222
+ /**
1223
+ * Run any global setup fixtures sequentially, if any.
1224
+ *
1225
+ * This is _automatically called_ by {@link Mocha#run} _unless_ the `runGlobalSetup` option is `false`; see {@link Mocha#enableGlobalSetup}.
1226
+ *
1227
+ * The context object this function resolves with should be consumed by {@link Mocha#runGlobalTeardown}.
1228
+ * @param {object} [context] - Context object if already have one
1229
+ * @public
1230
+ * @returns {Promise<object>} Context object
1231
+ */
1232
+ Mocha.prototype.runGlobalSetup = async function runGlobalSetup(context = {}) {
1233
+ const {globalSetup} = this.options;
1234
+ if (globalSetup && globalSetup.length) {
1235
+ debug('run(): global setup starting');
1236
+ await this._runGlobalFixtures(globalSetup, context);
1237
+ debug('run(): global setup complete');
1238
+ }
1239
+ return context;
1240
+ };
1241
+
1242
+ /**
1243
+ * Run any global teardown fixtures sequentially, if any.
1244
+ *
1245
+ * This is _automatically called_ by {@link Mocha#run} _unless_ the `runGlobalTeardown` option is `false`; see {@link Mocha#enableGlobalTeardown}.
1246
+ *
1247
+ * Should be called with context object returned by {@link Mocha#runGlobalSetup}, if applicable.
1248
+ * @param {object} [context] - Context object if already have one
1249
+ * @public
1250
+ * @returns {Promise<object>} Context object
1251
+ */
1252
+ Mocha.prototype.runGlobalTeardown = async function runGlobalTeardown(
1253
+ context = {}
1254
+ ) {
1255
+ const {globalTeardown} = this.options;
1256
+ if (globalTeardown && globalTeardown.length) {
1257
+ debug('run(): global teardown starting');
1258
+ await this._runGlobalFixtures(globalTeardown, context);
1259
+ }
1260
+ debug('run(): global teardown complete');
1261
+ return context;
1262
+ };
1263
+
1264
+ /**
1265
+ * Run global fixtures sequentially with context `context`
1266
+ * @private
1267
+ * @param {MochaGlobalFixture[]} [fixtureFns] - Fixtures to run
1268
+ * @param {object} [context] - context object
1269
+ * @returns {Promise<object>} context object
1270
+ */
1271
+ Mocha.prototype._runGlobalFixtures = async function _runGlobalFixtures(
1272
+ fixtureFns = [],
1273
+ context = {}
1274
+ ) {
1275
+ for await (const fixtureFn of fixtureFns) {
1276
+ await fixtureFn.call(context);
1277
+ }
1278
+ return context;
1279
+ };
1280
+
1281
+ /**
1282
+ * Toggle execution of any global setup fixture(s)
1283
+ *
1284
+ * @chainable
1285
+ * @public
1286
+ * @param {boolean } [enabled=true] - If `false`, do not run global setup fixture
1287
+ * @returns {Mocha}
1288
+ */
1289
+ Mocha.prototype.enableGlobalSetup = function enableGlobalSetup(enabled = true) {
1290
+ this.options.enableGlobalSetup = Boolean(enabled);
1291
+ return this;
1292
+ };
1293
+
1294
+ /**
1295
+ * Toggle execution of any global teardown fixture(s)
1296
+ *
1297
+ * @chainable
1298
+ * @public
1299
+ * @param {boolean } [enabled=true] - If `false`, do not run global teardown fixture
1300
+ * @returns {Mocha}
1301
+ */
1302
+ Mocha.prototype.enableGlobalTeardown = function enableGlobalTeardown(
1303
+ enabled = true
1304
+ ) {
1305
+ this.options.enableGlobalTeardown = Boolean(enabled);
1306
+ return this;
1307
+ };
1308
+
1309
+ /**
1310
+ * Returns `true` if one or more global setup fixtures have been supplied.
1311
+ * @public
1312
+ * @returns {boolean}
1313
+ */
1314
+ Mocha.prototype.hasGlobalSetupFixtures = function hasGlobalSetupFixtures() {
1315
+ return Boolean(this.options.globalSetup.length);
1316
+ };
1317
+
1318
+ /**
1319
+ * Returns `true` if one or more global teardown fixtures have been supplied.
1320
+ * @public
1321
+ * @returns {boolean}
1322
+ */
1323
+ Mocha.prototype.hasGlobalTeardownFixtures = function hasGlobalTeardownFixtures() {
1324
+ return Boolean(this.options.globalTeardown.length);
1325
+ };
1326
+
1327
+ /**
1328
+ * An alternative way to define root hooks that works with parallel runs.
1329
+ * @typedef {Object} MochaRootHookObject
1330
+ * @property {Function|Function[]} [beforeAll] - "Before all" hook(s)
1331
+ * @property {Function|Function[]} [beforeEach] - "Before each" hook(s)
1332
+ * @property {Function|Function[]} [afterAll] - "After all" hook(s)
1333
+ * @property {Function|Function[]} [afterEach] - "After each" hook(s)
1334
+ */
1335
+
1336
+ /**
1337
+ * An function that returns a {@link MochaRootHookObject}, either sync or async.
1338
+ @callback MochaRootHookFunction
1339
+ * @returns {MochaRootHookObject|Promise<MochaRootHookObject>}
1340
+ */
1341
+
1342
+ /**
1343
+ * A function that's invoked _once_ which is either sync or async.
1344
+ * Can be a "teardown" or "setup". These will all share the same context.
1345
+ * @callback MochaGlobalFixture
1346
+ * @returns {void|Promise<void>}
1347
+ */
1348
+
1349
+ /**
1350
+ * An object making up all necessary parts of a plugin loader and aggregator
1351
+ * @typedef {Object} PluginDefinition
1352
+ * @property {string} exportName - Named export to use
1353
+ * @property {string} [optionName] - Option name for Mocha constructor (use `exportName` if omitted)
1354
+ * @property {PluginValidator} [validate] - Validator function
1355
+ * @property {PluginFinalizer} [finalize] - Finalizer/aggregator function
1356
+ */
1357
+
1358
+ /**
1359
+ * A (sync) function to assert a user-supplied plugin implementation is valid.
1360
+ *
1361
+ * Defined in a {@link PluginDefinition}.
1362
+
1363
+ * @callback PluginValidator
1364
+ * @param {*} value - Value to check
1365
+ * @this {PluginDefinition}
1366
+ * @returns {void}
1367
+ */
1368
+
1369
+ /**
1370
+ * A function to finalize plugins impls of a particular ilk
1371
+ * @callback PluginFinalizer
1372
+ * @param {Array<*>} impls - User-supplied implementations
1373
+ * @returns {Promise<*>|*}
1374
+ */