mocha 7.1.1 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,8 @@
3
3
  var Suite = require('../suite');
4
4
  var errors = require('../errors');
5
5
  var createMissingArgumentError = errors.createMissingArgumentError;
6
+ var createUnsupportedError = errors.createUnsupportedError;
7
+ var createForbiddenExclusivityError = errors.createForbiddenExclusivityError;
6
8
 
7
9
  /**
8
10
  * Functions common to more than one interface.
@@ -92,6 +94,9 @@ module.exports = function(suites, context, mocha) {
92
94
  * @returns {Suite}
93
95
  */
94
96
  only: function only(opts) {
97
+ if (mocha.options.forbidOnly) {
98
+ throw createForbiddenExclusivityError(mocha);
99
+ }
95
100
  opts.isOnly = true;
96
101
  return this.create(opts);
97
102
  },
@@ -125,16 +130,14 @@ module.exports = function(suites, context, mocha) {
125
130
  suite.file = opts.file;
126
131
  suites.unshift(suite);
127
132
  if (opts.isOnly) {
128
- if (mocha.options.forbidOnly && shouldBeTested(suite)) {
129
- throw new Error('`.only` forbidden');
130
- }
131
-
132
- suite.parent.appendOnlySuite(suite);
133
+ suite.markOnly();
133
134
  }
134
- if (suite.pending) {
135
- if (mocha.options.forbidPending && shouldBeTested(suite)) {
136
- throw new Error('Pending test forbidden');
137
- }
135
+ if (
136
+ suite.pending &&
137
+ mocha.options.forbidPending &&
138
+ shouldBeTested(suite)
139
+ ) {
140
+ throw createUnsupportedError('Pending test forbidden');
138
141
  }
139
142
  if (typeof opts.fn === 'function') {
140
143
  opts.fn.call(suite);
@@ -165,7 +168,10 @@ module.exports = function(suites, context, mocha) {
165
168
  * @returns {*}
166
169
  */
167
170
  only: function(mocha, test) {
168
- test.parent.appendOnlyTest(test);
171
+ if (mocha.options.forbidOnly) {
172
+ throw createForbiddenExclusivityError(mocha);
173
+ }
174
+ test.markOnly();
169
175
  return test;
170
176
  },
171
177
 
package/lib/mocha.js CHANGED
@@ -9,28 +9,59 @@
9
9
  var escapeRe = require('escape-string-regexp');
10
10
  var path = require('path');
11
11
  var builtinReporters = require('./reporters');
12
- var growl = require('./growl');
12
+ var growl = require('./nodejs/growl');
13
13
  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
+ var esmUtils = utils.supportsEsModules(true)
18
+ ? require('./esm-utils')
19
+ : undefined;
18
20
  var createStatsCollector = require('./stats-collector');
19
21
  var createInvalidReporterError = errors.createInvalidReporterError;
20
22
  var createInvalidInterfaceError = errors.createInvalidInterfaceError;
23
+ var createMochaInstanceAlreadyDisposedError =
24
+ errors.createMochaInstanceAlreadyDisposedError;
25
+ var createMochaInstanceAlreadyRunningError =
26
+ errors.createMochaInstanceAlreadyRunningError;
21
27
  var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
22
28
  var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
23
29
  var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
24
30
  var sQuote = utils.sQuote;
31
+ var debug = require('debug')('mocha:mocha');
25
32
 
26
33
  exports = module.exports = Mocha;
27
34
 
35
+ /**
36
+ * A Mocha instance is a finite state machine.
37
+ * These are the states it can be in.
38
+ */
39
+ var mochaStates = utils.defineConstants({
40
+ /**
41
+ * Initial state of the mocha instance
42
+ */
43
+ INIT: 'init',
44
+ /**
45
+ * Mocha instance is running tests
46
+ */
47
+ RUNNING: 'running',
48
+ /**
49
+ * Mocha instance is done running tests and references to test functions and hooks are cleaned.
50
+ * You can reset this state by unloading the test files.
51
+ */
52
+ REFERENCES_CLEANED: 'referencesCleaned',
53
+ /**
54
+ * Mocha instance is disposed and can no longer be used.
55
+ */
56
+ DISPOSED: 'disposed'
57
+ });
58
+
28
59
  /**
29
60
  * To require local UIs and reporters when running in node.
30
61
  */
31
62
 
32
- if (!process.browser) {
33
- var cwd = process.cwd();
63
+ if (!utils.isBrowser() && typeof module.paths !== 'undefined') {
64
+ var cwd = utils.cwd();
34
65
  module.paths.push(cwd, path.join(cwd, 'node_modules'));
35
66
  }
36
67
 
@@ -38,11 +69,6 @@ if (!process.browser) {
38
69
  * Expose internals.
39
70
  */
40
71
 
41
- /**
42
- * @public
43
- * @class utils
44
- * @memberof Mocha
45
- */
46
72
  exports.utils = utils;
47
73
  exports.interfaces = require('./interfaces');
48
74
  /**
@@ -90,6 +116,11 @@ exports.Test = require('./test');
90
116
  * @param {number} [options.slow] - Slow threshold value.
91
117
  * @param {number|string} [options.timeout] - Timeout threshold value.
92
118
  * @param {string} [options.ui] - Interface name.
119
+ * @param {boolean} [options.parallel] - Run jobs in parallel
120
+ * @param {number} [options.jobs] - Max number of worker processes for parallel runs
121
+ * @param {MochaRootHookObject} [options.rootHooks] - Hooks to bootstrap the root
122
+ * suite with
123
+ * @param {boolean} [options.isWorker] - Should be `true` if `Mocha` process is running in a worker process.
93
124
  */
94
125
  function Mocha(options) {
95
126
  options = utils.assign({}, mocharc, options || {});
@@ -97,6 +128,8 @@ function Mocha(options) {
97
128
  this.options = options;
98
129
  // root suite
99
130
  this.suite = new exports.Suite('', new exports.Context(), true);
131
+ this._cleanReferencesAfterRun = true;
132
+ this._state = mochaStates.INIT;
100
133
 
101
134
  this.grep(options.grep)
102
135
  .fgrep(options.fgrep)
@@ -136,6 +169,43 @@ function Mocha(options) {
136
169
  this[opt]();
137
170
  }
138
171
  }, this);
172
+
173
+ if (options.rootHooks) {
174
+ this.rootHooks(options.rootHooks);
175
+ }
176
+
177
+ /**
178
+ * The class which we'll instantiate in {@link Mocha#run}. Defaults to
179
+ * {@link Runner} in serial mode; changes in parallel mode.
180
+ * @memberof Mocha
181
+ * @private
182
+ */
183
+ this._runnerClass = exports.Runner;
184
+
185
+ /**
186
+ * Whether or not to call {@link Mocha#loadFiles} implicitly when calling
187
+ * {@link Mocha#run}. If this is `true`, then it's up to the consumer to call
188
+ * {@link Mocha#loadFiles} _or_ {@link Mocha#loadFilesAsync}.
189
+ * @private
190
+ * @memberof Mocha
191
+ */
192
+ this._lazyLoadFiles = false;
193
+
194
+ /**
195
+ * It's useful for a Mocha instance to know if it's running in a worker process.
196
+ * We could derive this via other means, but it's helpful to have a flag to refer to.
197
+ * @memberof Mocha
198
+ * @private
199
+ */
200
+ this.isWorker = Boolean(options.isWorker);
201
+
202
+ if (
203
+ options.parallel &&
204
+ (typeof options.jobs === 'undefined' || options.jobs > 1)
205
+ ) {
206
+ debug('attempting to enable parallel mode');
207
+ this.parallelMode(true);
208
+ }
139
209
  }
140
210
 
141
211
  /**
@@ -186,52 +256,52 @@ Mocha.prototype.addFile = function(file) {
186
256
  * // Use XUnit reporter and direct its output to file
187
257
  * mocha.reporter('xunit', { output: '/path/to/testspec.xunit.xml' });
188
258
  */
189
- Mocha.prototype.reporter = function(reporter, reporterOptions) {
190
- if (typeof reporter === 'function') {
191
- this._reporter = reporter;
259
+ Mocha.prototype.reporter = function(reporterName, reporterOptions) {
260
+ if (typeof reporterName === 'function') {
261
+ this._reporter = reporterName;
192
262
  } else {
193
- reporter = reporter || 'spec';
194
- var _reporter;
263
+ reporterName = reporterName || 'spec';
264
+ var reporter;
195
265
  // Try to load a built-in reporter.
196
- if (builtinReporters[reporter]) {
197
- _reporter = builtinReporters[reporter];
266
+ if (builtinReporters[reporterName]) {
267
+ reporter = builtinReporters[reporterName];
198
268
  }
199
269
  // Try to load reporters from process.cwd() and node_modules
200
- if (!_reporter) {
270
+ if (!reporter) {
201
271
  try {
202
- _reporter = require(reporter);
272
+ reporter = require(reporterName);
203
273
  } catch (err) {
204
274
  if (
205
- err.code !== 'MODULE_NOT_FOUND' ||
206
- err.message.indexOf('Cannot find module') !== -1
275
+ err.code === 'MODULE_NOT_FOUND' ||
276
+ err.message.indexOf('Cannot find module') >= 0
207
277
  ) {
208
278
  // Try to load reporters from a path (absolute or relative)
209
279
  try {
210
- _reporter = require(path.resolve(process.cwd(), reporter));
280
+ reporter = require(path.resolve(utils.cwd(), reporterName));
211
281
  } catch (_err) {
212
- _err.code !== 'MODULE_NOT_FOUND' ||
213
- _err.message.indexOf('Cannot find module') !== -1
214
- ? console.warn(sQuote(reporter) + ' reporter not found')
215
- : console.warn(
216
- sQuote(reporter) +
282
+ _err.code === 'MODULE_NOT_FOUND' ||
283
+ _err.message.indexOf('Cannot find module') >= 0
284
+ ? utils.warn(sQuote(reporterName) + ' reporter not found')
285
+ : utils.warn(
286
+ sQuote(reporterName) +
217
287
  ' reporter blew up with error:\n' +
218
288
  err.stack
219
289
  );
220
290
  }
221
291
  } else {
222
- console.warn(
223
- sQuote(reporter) + ' reporter blew up with error:\n' + err.stack
292
+ utils.warn(
293
+ sQuote(reporterName) + ' reporter blew up with error:\n' + err.stack
224
294
  );
225
295
  }
226
296
  }
227
297
  }
228
- if (!_reporter) {
298
+ if (!reporter) {
229
299
  throw createInvalidReporterError(
230
- 'invalid reporter ' + sQuote(reporter),
231
- reporter
300
+ 'invalid reporter ' + sQuote(reporterName),
301
+ reporterName
232
302
  );
233
303
  }
234
- this._reporter = _reporter;
304
+ this._reporter = reporter;
235
305
  }
236
306
  this.options.reporterOption = reporterOptions;
237
307
  // alias option name is used in public reporters xunit/tap/progress
@@ -340,7 +410,7 @@ Mocha.prototype.loadFiles = function(fn) {
340
410
  Mocha.prototype.loadFilesAsync = function() {
341
411
  var self = this;
342
412
  var suite = this.suite;
343
- this.loadAsync = true;
413
+ this.lazyLoadFiles(true);
344
414
 
345
415
  if (!esmUtils) {
346
416
  return new Promise(function(resolve) {
@@ -388,7 +458,18 @@ Mocha.unloadFile = function(file) {
388
458
  * @chainable
389
459
  */
390
460
  Mocha.prototype.unloadFiles = function() {
391
- this.files.forEach(Mocha.unloadFile);
461
+ if (this._state === mochaStates.DISPOSED) {
462
+ throw createMochaInstanceAlreadyDisposedError(
463
+ 'Mocha instance is already disposed, it cannot be used again.',
464
+ this._cleanReferencesAfterRun,
465
+ this
466
+ );
467
+ }
468
+
469
+ this.files.forEach(function(file) {
470
+ Mocha.unloadFile(file);
471
+ });
472
+ this._state = mochaStates.INIT;
392
473
  return this;
393
474
  };
394
475
 
@@ -475,37 +556,51 @@ Mocha.prototype.invert = function() {
475
556
  };
476
557
 
477
558
  /**
478
- * Enables or disables ignoring global leaks.
559
+ * Enables or disables checking for global variables leaked while running tests.
479
560
  *
480
- * @deprecated since v7.0.0
481
561
  * @public
482
- * @see {@link Mocha#checkLeaks}
483
- * @param {boolean} [ignoreLeaks=false] - Whether to ignore global leaks.
562
+ * @see [CLI option](../#-check-leaks)
563
+ * @param {boolean} [checkLeaks=true] - Whether to check for global variable leaks.
484
564
  * @return {Mocha} this
485
565
  * @chainable
486
566
  */
487
- Mocha.prototype.ignoreLeaks = function(ignoreLeaks) {
488
- utils.deprecate(
489
- '"ignoreLeaks()" is DEPRECATED, please use "checkLeaks()" instead.'
490
- );
491
- this.options.checkLeaks = !ignoreLeaks;
567
+ Mocha.prototype.checkLeaks = function(checkLeaks) {
568
+ this.options.checkLeaks = checkLeaks !== false;
492
569
  return this;
493
570
  };
494
571
 
495
572
  /**
496
- * Enables or disables checking for global variables leaked while running tests.
497
- *
573
+ * Enables or disables whether or not to dispose after each test run.
574
+ * Disable this to ensure you can run the test suite multiple times.
575
+ * If disabled, be sure to dispose mocha when you're done to prevent memory leaks.
498
576
  * @public
499
- * @see [CLI option](../#-check-leaks)
500
- * @param {boolean} [checkLeaks=true] - Whether to check for global variable leaks.
577
+ * @see {@link Mocha#dispose}
578
+ * @param {boolean} cleanReferencesAfterRun
501
579
  * @return {Mocha} this
502
580
  * @chainable
503
581
  */
504
- Mocha.prototype.checkLeaks = function(checkLeaks) {
505
- this.options.checkLeaks = checkLeaks !== false;
582
+ Mocha.prototype.cleanReferencesAfterRun = function(cleanReferencesAfterRun) {
583
+ this._cleanReferencesAfterRun = cleanReferencesAfterRun !== false;
506
584
  return this;
507
585
  };
508
586
 
587
+ /**
588
+ * Manually dispose this mocha instance. Mark this instance as `disposed` and unable to run more tests.
589
+ * It also removes function references to tests functions and hooks, so variables trapped in closures can be cleaned by the garbage collector.
590
+ * @public
591
+ */
592
+ Mocha.prototype.dispose = function() {
593
+ if (this._state === mochaStates.RUNNING) {
594
+ throw createMochaInstanceAlreadyRunningError(
595
+ 'Cannot dispose while the mocha instance is still running tests.'
596
+ );
597
+ }
598
+ this.unloadFiles();
599
+ this._previousRunner && this._previousRunner.dispose();
600
+ this.suite.dispose();
601
+ this._state = mochaStates.DISPOSED;
602
+ };
603
+
509
604
  /**
510
605
  * Displays full stack trace upon test failure.
511
606
  *
@@ -531,7 +626,7 @@ Mocha.prototype.fullTrace = function(fullTrace) {
531
626
  Mocha.prototype.growl = function() {
532
627
  this.options.growl = this.isGrowlCapable();
533
628
  if (!this.options.growl) {
534
- var detail = process.browser
629
+ var detail = utils.isBrowser()
535
630
  ? 'notification support not available in this browser...'
536
631
  : 'notification support prerequisites not installed...';
537
632
  console.error(detail + ' cannot enable!');
@@ -589,24 +684,6 @@ Mocha.prototype.global = function(global) {
589
684
  // for backwards compability, 'globals' is an alias of 'global'
590
685
  Mocha.prototype.globals = Mocha.prototype.global;
591
686
 
592
- /**
593
- * Enables or disables TTY color output by screen-oriented reporters.
594
- *
595
- * @deprecated since v7.0.0
596
- * @public
597
- * @see {@link Mocha#color}
598
- * @param {boolean} colors - Whether to enable color output.
599
- * @return {Mocha} this
600
- * @chainable
601
- */
602
- Mocha.prototype.useColors = function(colors) {
603
- utils.deprecate('"useColors()" is DEPRECATED, please use "color()" instead.');
604
- if (colors !== undefined) {
605
- this.options.color = colors;
606
- }
607
- return this;
608
- };
609
-
610
687
  /**
611
688
  * Enables or disables TTY color output by screen-oriented reporters.
612
689
  *
@@ -621,25 +698,6 @@ Mocha.prototype.color = function(color) {
621
698
  return this;
622
699
  };
623
700
 
624
- /**
625
- * Determines if reporter should use inline diffs (rather than +/-)
626
- * in test failure output.
627
- *
628
- * @deprecated since v7.0.0
629
- * @public
630
- * @see {@link Mocha#inlineDiffs}
631
- * @param {boolean} [inlineDiffs=false] - Whether to use inline diffs.
632
- * @return {Mocha} this
633
- * @chainable
634
- */
635
- Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
636
- utils.deprecate(
637
- '"useInlineDiffs()" is DEPRECATED, please use "inlineDiffs()" instead.'
638
- );
639
- this.options.inlineDiffs = inlineDiffs !== undefined && inlineDiffs;
640
- return this;
641
- };
642
-
643
701
  /**
644
702
  * Enables or disables reporter to use inline diffs (rather than +/-)
645
703
  * in test failure output.
@@ -655,22 +713,6 @@ Mocha.prototype.inlineDiffs = function(inlineDiffs) {
655
713
  return this;
656
714
  };
657
715
 
658
- /**
659
- * Determines if reporter should include diffs in test failure output.
660
- *
661
- * @deprecated since v7.0.0
662
- * @public
663
- * @see {@link Mocha#diff}
664
- * @param {boolean} [hideDiff=false] - Whether to hide diffs.
665
- * @return {Mocha} this
666
- * @chainable
667
- */
668
- Mocha.prototype.hideDiff = function(hideDiff) {
669
- utils.deprecate('"hideDiff()" is DEPRECATED, please use "diff()" instead.');
670
- this.options.diff = !(hideDiff === true);
671
- return this;
672
- };
673
-
674
716
  /**
675
717
  * Enables or disables reporter to include diff in test failure output.
676
718
  *
@@ -696,7 +738,6 @@ Mocha.prototype.diff = function(diff) {
696
738
  * @public
697
739
  * @see [CLI option](../#-timeout-ms-t-ms)
698
740
  * @see [Timeouts](../#timeouts)
699
- * @see {@link Mocha#enableTimeouts}
700
741
  * @param {number|string} msecs - Timeout threshold value.
701
742
  * @return {Mocha} this
702
743
  * @chainable
@@ -755,22 +796,6 @@ Mocha.prototype.slow = function(msecs) {
755
796
  return this;
756
797
  };
757
798
 
758
- /**
759
- * Enables or disables timeouts.
760
- *
761
- * @public
762
- * @see [CLI option](../#-timeout-ms-t-ms)
763
- * @param {boolean} enableTimeouts - Whether to enable timeouts.
764
- * @return {Mocha} this
765
- * @chainable
766
- */
767
- Mocha.prototype.enableTimeouts = function(enableTimeouts) {
768
- this.suite.enableTimeouts(
769
- arguments.length && enableTimeouts !== undefined ? enableTimeouts : true
770
- );
771
- return this;
772
- };
773
-
774
799
  /**
775
800
  * Forces all tests to either accept a `done` callback or return a promise.
776
801
  *
@@ -856,6 +881,29 @@ Mocha.prototype.forbidPending = function(forbidPending) {
856
881
  return this;
857
882
  };
858
883
 
884
+ /**
885
+ * Throws an error if mocha is in the wrong state to be able to transition to a "running" state.
886
+ * @private
887
+ */
888
+ Mocha.prototype._guardRunningStateTransition = function() {
889
+ if (this._state === mochaStates.RUNNING) {
890
+ throw createMochaInstanceAlreadyRunningError(
891
+ 'Mocha instance is currently running tests, cannot start a next test run until this one is done',
892
+ this
893
+ );
894
+ }
895
+ if (
896
+ this._state === mochaStates.DISPOSED ||
897
+ this._state === mochaStates.REFERENCES_CLEANED
898
+ ) {
899
+ throw createMochaInstanceAlreadyDisposedError(
900
+ '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.',
901
+ this._cleanReferencesAfterRun,
902
+ this
903
+ );
904
+ }
905
+ };
906
+
859
907
  /**
860
908
  * Mocha version as specified by "package.json".
861
909
  *
@@ -896,13 +944,23 @@ Object.defineProperty(Mocha.prototype, 'version', {
896
944
  * mocha.run(failures => process.exitCode = failures ? 1 : 0);
897
945
  */
898
946
  Mocha.prototype.run = function(fn) {
899
- if (this.files.length && !this.loadAsync) {
947
+ this._guardRunningStateTransition();
948
+ this._state = mochaStates.RUNNING;
949
+ if (this._previousRunner) {
950
+ this._previousRunner.dispose();
951
+ this.suite.reset();
952
+ }
953
+ if (this.files.length && !this._lazyLoadFiles) {
900
954
  this.loadFiles();
901
955
  }
956
+ var self = this;
902
957
  var suite = this.suite;
903
958
  var options = this.options;
904
959
  options.files = this.files;
905
- var runner = new exports.Runner(suite, options.delay);
960
+ var runner = new this._runnerClass(suite, {
961
+ delay: options.delay,
962
+ cleanReferencesAfterRun: this._cleanReferencesAfterRun
963
+ });
906
964
  createStatsCollector(runner);
907
965
  var reporter = new this._reporter(runner, options);
908
966
  runner.checkLeaks = options.checkLeaks === true;
@@ -927,6 +985,12 @@ Mocha.prototype.run = function(fn) {
927
985
  exports.reporters.Base.hideDiff = !options.diff;
928
986
 
929
987
  function done(failures) {
988
+ self._previousRunner = runner;
989
+ if (self._cleanReferencesAfterRun) {
990
+ self._state = mochaStates.REFERENCES_CLEANED;
991
+ } else {
992
+ self._state = mochaStates.INIT;
993
+ }
930
994
  fn = fn || utils.noop;
931
995
  if (reporter.done) {
932
996
  reporter.done(failures, fn);
@@ -935,5 +999,107 @@ Mocha.prototype.run = function(fn) {
935
999
  }
936
1000
  }
937
1001
 
938
- return runner.run(done);
1002
+ return runner.run(done, {files: this.files, options: options});
939
1003
  };
1004
+
1005
+ /**
1006
+ * Assigns hooks to the root suite
1007
+ * @param {MochaRootHookObject} [hooks] - Hooks to assign to root suite
1008
+ * @chainable
1009
+ */
1010
+ Mocha.prototype.rootHooks = function rootHooks(hooks) {
1011
+ if (utils.type(hooks) === 'object') {
1012
+ var beforeAll = [].concat(hooks.beforeAll || []);
1013
+ var beforeEach = [].concat(hooks.beforeEach || []);
1014
+ var afterAll = [].concat(hooks.afterAll || []);
1015
+ var afterEach = [].concat(hooks.afterEach || []);
1016
+ var rootSuite = this.suite;
1017
+ beforeAll.forEach(function(hook) {
1018
+ rootSuite.beforeAll(hook);
1019
+ });
1020
+ beforeEach.forEach(function(hook) {
1021
+ rootSuite.beforeEach(hook);
1022
+ });
1023
+ afterAll.forEach(function(hook) {
1024
+ rootSuite.afterAll(hook);
1025
+ });
1026
+ afterEach.forEach(function(hook) {
1027
+ rootSuite.afterEach(hook);
1028
+ });
1029
+ }
1030
+ return this;
1031
+ };
1032
+
1033
+ /**
1034
+ * Toggles parallel mode.
1035
+ *
1036
+ * Must be run before calling {@link Mocha#run}. Changes the `Runner` class to
1037
+ * use; also enables lazy file loading if not already done so.
1038
+ * @param {boolean} [enable] - If `true`, enable; otherwise disable.
1039
+ * @throws If run in browser
1040
+ * @throws If Mocha not in "INIT" state
1041
+ * @returns {Mocha}
1042
+ * @chainable
1043
+ * @public
1044
+ */
1045
+ Mocha.prototype.parallelMode = function parallelMode(enable) {
1046
+ if (utils.isBrowser()) {
1047
+ throw errors.createUnsupportedError(
1048
+ 'parallel mode is only supported in Node.js'
1049
+ );
1050
+ }
1051
+ var parallel = enable === true;
1052
+ if (
1053
+ parallel === this.options.parallel &&
1054
+ this._lazyLoadFiles &&
1055
+ this._runnerClass !== exports.Runner
1056
+ ) {
1057
+ return this;
1058
+ }
1059
+ if (this._state !== mochaStates.INIT) {
1060
+ throw errors.createUnsupportedError(
1061
+ 'cannot change parallel mode after having called run()'
1062
+ );
1063
+ }
1064
+ this.options.parallel = parallel;
1065
+
1066
+ // swap Runner class
1067
+ this._runnerClass = parallel
1068
+ ? require('./nodejs/parallel-buffered-runner')
1069
+ : exports.Runner;
1070
+
1071
+ // lazyLoadFiles may have been set `true` otherwise (for ESM loading),
1072
+ // so keep `true` if so.
1073
+ return this.lazyLoadFiles(this._lazyLoadFiles || parallel);
1074
+ };
1075
+
1076
+ /**
1077
+ * Disables implicit call to {@link Mocha#loadFiles} in {@link Mocha#run}. This
1078
+ * setting is used by watch mode, parallel mode, and for loading ESM files.
1079
+ * @todo This should throw if we've already loaded files; such behavior
1080
+ * necessitates adding a new state.
1081
+ * @param {boolean} [enable] - If `true`, disable eager loading of files in
1082
+ * {@link Mocha#run}
1083
+ * @chainable
1084
+ * @public
1085
+ */
1086
+ Mocha.prototype.lazyLoadFiles = function lazyLoadFiles(enable) {
1087
+ this._lazyLoadFiles = enable === true;
1088
+ debug('set lazy load to %s', enable);
1089
+ return this;
1090
+ };
1091
+
1092
+ /**
1093
+ * An alternative way to define root hooks that works with parallel runs.
1094
+ * @typedef {Object} MochaRootHookObject
1095
+ * @property {Function|Function[]} [beforeAll] - "Before all" hook(s)
1096
+ * @property {Function|Function[]} [beforeEach] - "Before each" hook(s)
1097
+ * @property {Function|Function[]} [afterAll] - "After all" hook(s)
1098
+ * @property {Function|Function[]} [afterEach] - "After each" hook(s)
1099
+ */
1100
+
1101
+ /**
1102
+ * An function that returns a {@link MochaRootHookObject}, either sync or async.
1103
+ * @callback MochaRootHookFunction
1104
+ * @returns {MochaRootHookObject|Promise<MochaRootHookObject>}
1105
+ */
package/lib/mocharc.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "diff": true,
3
3
  "extension": ["js", "cjs", "mjs"],
4
- "opts": "./test/mocha.opts",
5
4
  "package": "./package.json",
6
5
  "reporter": "spec",
7
6
  "slow": 75,