mocha 6.0.0-1 → 6.0.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/runner.js CHANGED
@@ -1,27 +1,36 @@
1
1
  'use strict';
2
2
 
3
- /**
4
- * @module Runner
5
- */
6
3
  /**
7
4
  * Module dependencies.
8
5
  */
6
+ var util = require('util');
9
7
  var EventEmitter = require('events').EventEmitter;
10
8
  var Pending = require('./pending');
11
9
  var utils = require('./utils');
12
10
  var inherits = utils.inherits;
13
11
  var debug = require('debug')('mocha:runner');
14
12
  var Runnable = require('./runnable');
15
- var createStatsCollector = require('./stats-collector');
13
+ var Suite = require('./suite');
14
+ var HOOK_TYPE_BEFORE_EACH = Suite.constants.HOOK_TYPE_BEFORE_EACH;
15
+ var HOOK_TYPE_AFTER_EACH = Suite.constants.HOOK_TYPE_AFTER_EACH;
16
+ var HOOK_TYPE_AFTER_ALL = Suite.constants.HOOK_TYPE_AFTER_ALL;
17
+ var HOOK_TYPE_BEFORE_ALL = Suite.constants.HOOK_TYPE_BEFORE_ALL;
18
+ var EVENT_ROOT_SUITE_RUN = Suite.constants.EVENT_ROOT_SUITE_RUN;
19
+ var STATE_FAILED = Runnable.constants.STATE_FAILED;
20
+ var STATE_PASSED = Runnable.constants.STATE_PASSED;
21
+ var dQuote = utils.dQuote;
22
+ var ngettext = utils.ngettext;
23
+ var sQuote = utils.sQuote;
16
24
  var stackFilter = utils.stackTraceFilter();
17
25
  var stringify = utils.stringify;
18
26
  var type = utils.type;
19
- var undefinedError = utils.undefinedError;
27
+ var createInvalidExceptionError = require('./errors')
28
+ .createInvalidExceptionError;
20
29
 
21
30
  /**
22
31
  * Non-enumerable globals.
32
+ * @readonly
23
33
  */
24
-
25
34
  var globals = [
26
35
  'setTimeout',
27
36
  'clearTimeout',
@@ -33,33 +42,85 @@ var globals = [
33
42
  'clearImmediate'
34
43
  ];
35
44
 
36
- /**
37
- * Expose `Runner`.
38
- */
45
+ var constants = utils.defineConstants(
46
+ /**
47
+ * {@link Runner}-related constants.
48
+ * @public
49
+ * @memberof Runner
50
+ * @readonly
51
+ * @alias constants
52
+ * @static
53
+ * @enum {string}
54
+ */
55
+ {
56
+ /**
57
+ * Emitted when {@link Hook} execution begins
58
+ */
59
+ EVENT_HOOK_BEGIN: 'hook',
60
+ /**
61
+ * Emitted when {@link Hook} execution ends
62
+ */
63
+ EVENT_HOOK_END: 'hook end',
64
+ /**
65
+ * Emitted when Root {@link Suite} execution begins (all files have been parsed and hooks/tests are ready for execution)
66
+ */
67
+ EVENT_RUN_BEGIN: 'start',
68
+ /**
69
+ * Emitted when Root {@link Suite} execution has been delayed via `delay` option
70
+ */
71
+ EVENT_DELAY_BEGIN: 'waiting',
72
+ /**
73
+ * Emitted when delayed Root {@link Suite} execution is triggered by user via `global.run()`
74
+ */
75
+ EVENT_DELAY_END: 'ready',
76
+ /**
77
+ * Emitted when Root {@link Suite} execution ends
78
+ */
79
+ EVENT_RUN_END: 'end',
80
+ /**
81
+ * Emitted when {@link Suite} execution begins
82
+ */
83
+ EVENT_SUITE_BEGIN: 'suite',
84
+ /**
85
+ * Emitted when {@link Suite} execution ends
86
+ */
87
+ EVENT_SUITE_END: 'suite end',
88
+ /**
89
+ * Emitted when {@link Test} execution begins
90
+ */
91
+ EVENT_TEST_BEGIN: 'test',
92
+ /**
93
+ * Emitted when {@link Test} execution ends
94
+ */
95
+ EVENT_TEST_END: 'test end',
96
+ /**
97
+ * Emitted when {@link Test} execution fails
98
+ */
99
+ EVENT_TEST_FAIL: 'fail',
100
+ /**
101
+ * Emitted when {@link Test} execution succeeds
102
+ */
103
+ EVENT_TEST_PASS: 'pass',
104
+ /**
105
+ * Emitted when {@link Test} becomes pending
106
+ */
107
+ EVENT_TEST_PENDING: 'pending',
108
+ /**
109
+ * Emitted when {@link Test} execution has failed, but will retry
110
+ */
111
+ EVENT_TEST_RETRY: 'retry'
112
+ }
113
+ );
39
114
 
40
115
  module.exports = Runner;
41
116
 
42
117
  /**
43
- * Initialize a `Runner` for the given `suite`. Derived from [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
44
- *
45
- * Events:
46
- *
47
- * - `start` execution started
48
- * - `end` execution complete
49
- * - `suite` (suite) test suite execution started
50
- * - `suite end` (suite) all tests (and sub-suites) have finished
51
- * - `test` (test) test execution started
52
- * - `test end` (test) test completed
53
- * - `hook` (hook) hook execution started
54
- * - `hook end` (hook) hook complete
55
- * - `pass` (test) test passed
56
- * - `fail` (test, err) test failed
57
- * - `pending` (test) test pending
118
+ * Initialize a `Runner` at the Root {@link Suite}, which represents a hierarchy of {@link Suite|Suites} and {@link Test|Tests}.
58
119
  *
59
- * @memberof Mocha
120
+ * @extends external:EventEmitter
60
121
  * @public
61
122
  * @class
62
- * @param {Suite} [suite] Root suite
123
+ * @param {Suite} suite Root suite
63
124
  * @param {boolean} [delay] Whether or not to delay execution of root suite
64
125
  * until ready.
65
126
  */
@@ -72,16 +133,15 @@ function Runner(suite, delay) {
72
133
  this.started = false;
73
134
  this.total = suite.total();
74
135
  this.failures = 0;
75
- this.on('test end', function(test) {
136
+ this.on(constants.EVENT_TEST_END, function(test) {
76
137
  self.checkGlobals(test);
77
138
  });
78
- this.on('hook end', function(hook) {
139
+ this.on(constants.EVENT_HOOK_END, function(hook) {
79
140
  self.checkGlobals(hook);
80
141
  });
81
142
  this._defaultGrep = /.*/;
82
143
  this.grep(this._defaultGrep);
83
144
  this.globals(this.globalProps().concat(extraGlobals()));
84
- createStatsCollector(this);
85
145
  }
86
146
 
87
147
  /**
@@ -102,7 +162,7 @@ inherits(Runner, EventEmitter);
102
162
  * with number of tests matched.
103
163
  *
104
164
  * @public
105
- * @memberof Mocha.Runner
165
+ * @memberof Runner
106
166
  * @param {RegExp} re
107
167
  * @param {boolean} invert
108
168
  * @return {Runner} Runner instance.
@@ -119,7 +179,7 @@ Runner.prototype.grep = function(re, invert) {
119
179
  * Returns the number of tests matching the grep search for the
120
180
  * given suite.
121
181
  *
122
- * @memberof Mocha.Runner
182
+ * @memberof Runner
123
183
  * @public
124
184
  * @param {Suite} suite
125
185
  * @return {number}
@@ -165,7 +225,7 @@ Runner.prototype.globalProps = function() {
165
225
  * Allow the given `arr` of globals.
166
226
  *
167
227
  * @public
168
- * @memberof Mocha.Runner
228
+ * @memberof Runner
169
229
  * @param {Array} arr
170
230
  * @return {Runner} Runner instance.
171
231
  */
@@ -204,13 +264,14 @@ Runner.prototype.checkGlobals = function(test) {
204
264
  leaks = filterLeaks(ok, globals);
205
265
  this._globals = this._globals.concat(leaks);
206
266
 
207
- if (leaks.length > 1) {
208
- this.fail(
209
- test,
210
- new Error('global leaks detected: ' + leaks.join(', ') + '')
267
+ if (leaks.length) {
268
+ var format = ngettext(
269
+ leaks.length,
270
+ 'global leak detected: %s',
271
+ 'global leaks detected: %s'
211
272
  );
212
- } else if (leaks.length) {
213
- this.fail(test, new Error('global leak detected: ' + leaks[0]));
273
+ var error = new Error(util.format(format, leaks.map(sQuote).join(', ')));
274
+ this.fail(test, error);
214
275
  }
215
276
  };
216
277
 
@@ -227,7 +288,7 @@ Runner.prototype.fail = function(test, err) {
227
288
  }
228
289
 
229
290
  ++this.failures;
230
- test.state = 'failed';
291
+ test.state = STATE_FAILED;
231
292
 
232
293
  if (!isError(err)) {
233
294
  err = thrown2Error(err);
@@ -240,7 +301,7 @@ Runner.prototype.fail = function(test, err) {
240
301
  // some environments do not take kindly to monkeying with the stack
241
302
  }
242
303
 
243
- this.emit('fail', test, err);
304
+ this.emit(constants.EVENT_TEST_FAIL, test, err);
244
305
  };
245
306
 
246
307
  /**
@@ -265,10 +326,18 @@ Runner.prototype.fail = function(test, err) {
265
326
  * @param {Error} err
266
327
  */
267
328
  Runner.prototype.failHook = function(hook, err) {
329
+ hook.originalTitle = hook.originalTitle || hook.title;
268
330
  if (hook.ctx && hook.ctx.currentTest) {
269
- hook.originalTitle = hook.originalTitle || hook.title;
270
331
  hook.title =
271
- hook.originalTitle + ' for "' + hook.ctx.currentTest.title + '"';
332
+ hook.originalTitle + ' for ' + dQuote(hook.ctx.currentTest.title);
333
+ } else {
334
+ var parentTitle;
335
+ if (hook.parent.title) {
336
+ parentTitle = hook.parent.title;
337
+ } else {
338
+ parentTitle = hook.parent.root ? '{root}' : '';
339
+ }
340
+ hook.title = hook.originalTitle + ' in ' + dQuote(parentTitle);
272
341
  }
273
342
 
274
343
  this.fail(hook, err);
@@ -284,7 +353,7 @@ Runner.prototype.failHook = function(hook, err) {
284
353
 
285
354
  Runner.prototype.hook = function(name, fn) {
286
355
  var suite = this.suite;
287
- var hooks = suite['_' + name];
356
+ var hooks = suite.getHooks(name);
288
357
  var self = this;
289
358
 
290
359
  function next(i) {
@@ -294,9 +363,15 @@ Runner.prototype.hook = function(name, fn) {
294
363
  }
295
364
  self.currentRunnable = hook;
296
365
 
297
- hook.ctx.currentTest = self.test;
366
+ if (name === 'beforeAll') {
367
+ hook.ctx.currentTest = hook.parent.tests[0];
368
+ } else if (name === 'afterAll') {
369
+ hook.ctx.currentTest = hook.parent.tests[hook.parent.tests.length - 1];
370
+ } else {
371
+ hook.ctx.currentTest = self.test;
372
+ }
298
373
 
299
- self.emit('hook', hook);
374
+ self.emit(constants.EVENT_HOOK_BEGIN, hook);
300
375
 
301
376
  if (!hook.listeners('error').length) {
302
377
  hook.on('error', function(err) {
@@ -311,7 +386,7 @@ Runner.prototype.hook = function(name, fn) {
311
386
  }
312
387
  if (err) {
313
388
  if (err instanceof Pending) {
314
- if (name === 'beforeEach' || name === 'afterEach') {
389
+ if (name === HOOK_TYPE_BEFORE_EACH || name === HOOK_TYPE_AFTER_EACH) {
315
390
  self.test.pending = true;
316
391
  } else {
317
392
  suite.tests.forEach(function(test) {
@@ -330,7 +405,7 @@ Runner.prototype.hook = function(name, fn) {
330
405
  return fn(err);
331
406
  }
332
407
  }
333
- self.emit('hook end', hook);
408
+ self.emit(constants.EVENT_HOOK_END, hook);
334
409
  delete hook.ctx.currentTest;
335
410
  next(++i);
336
411
  });
@@ -430,7 +505,9 @@ Runner.prototype.runTest = function(fn) {
430
505
  if (!test) {
431
506
  return;
432
507
  }
433
- if (this.forbidOnly && hasOnly(this.parents().reverse()[0] || this.suite)) {
508
+
509
+ var suite = this.parents().reverse()[0] || this.suite;
510
+ if (this.forbidOnly && suite.hasOnly()) {
434
511
  fn(new Error('`.only` forbidden'));
435
512
  return;
436
513
  }
@@ -473,7 +550,7 @@ Runner.prototype.runTests = function(suite, fn) {
473
550
 
474
551
  if (self.suite) {
475
552
  // call hookUp afterEach
476
- self.hookUp('afterEach', function(err2, errSuite2) {
553
+ self.hookUp(HOOK_TYPE_AFTER_EACH, function(err2, errSuite2) {
477
554
  self.suite = orig;
478
555
  // some hooks may fail even now
479
556
  if (err2) {
@@ -539,24 +616,24 @@ Runner.prototype.runTests = function(suite, fn) {
539
616
  self.fail(test, new Error('Pending test forbidden'));
540
617
  delete test.isPending;
541
618
  } else {
542
- self.emit('pending', test);
619
+ self.emit(constants.EVENT_TEST_PENDING, test);
543
620
  }
544
- self.emit('test end', test);
621
+ self.emit(constants.EVENT_TEST_END, test);
545
622
  return next();
546
623
  }
547
624
 
548
625
  // execute test and hook(s)
549
- self.emit('test', (self.test = test));
550
- self.hookDown('beforeEach', function(err, errSuite) {
626
+ self.emit(constants.EVENT_TEST_BEGIN, (self.test = test));
627
+ self.hookDown(HOOK_TYPE_BEFORE_EACH, function(err, errSuite) {
551
628
  if (test.isPending()) {
552
629
  if (self.forbidPending) {
553
630
  test.isPending = alwaysFalse;
554
631
  self.fail(test, new Error('Pending test forbidden'));
555
632
  delete test.isPending;
556
633
  } else {
557
- self.emit('pending', test);
634
+ self.emit(constants.EVENT_TEST_PENDING, test);
558
635
  }
559
- self.emit('test end', test);
636
+ self.emit(constants.EVENT_TEST_END, test);
560
637
  return next();
561
638
  }
562
639
  if (err) {
@@ -571,33 +648,33 @@ Runner.prototype.runTests = function(suite, fn) {
571
648
  self.fail(test, new Error('Pending test forbidden'));
572
649
  } else if (err instanceof Pending) {
573
650
  test.pending = true;
574
- self.emit('pending', test);
651
+ self.emit(constants.EVENT_TEST_PENDING, test);
575
652
  } else if (retry < test.retries()) {
576
653
  var clonedTest = test.clone();
577
654
  clonedTest.currentRetry(retry + 1);
578
655
  tests.unshift(clonedTest);
579
656
 
580
- self.emit('retry', test, err);
657
+ self.emit(constants.EVENT_TEST_RETRY, test, err);
581
658
 
582
659
  // Early return + hook trigger so that it doesn't
583
660
  // increment the count wrong
584
- return self.hookUp('afterEach', next);
661
+ return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
585
662
  } else {
586
663
  self.fail(test, err);
587
664
  }
588
- self.emit('test end', test);
665
+ self.emit(constants.EVENT_TEST_END, test);
589
666
 
590
667
  if (err instanceof Pending) {
591
668
  return next();
592
669
  }
593
670
 
594
- return self.hookUp('afterEach', next);
671
+ return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
595
672
  }
596
673
 
597
- test.state = 'passed';
598
- self.emit('pass', test);
599
- self.emit('test end', test);
600
- self.hookUp('afterEach', next);
674
+ test.state = STATE_PASSED;
675
+ self.emit(constants.EVENT_TEST_PASS, test);
676
+ self.emit(constants.EVENT_TEST_END, test);
677
+ self.hookUp(HOOK_TYPE_AFTER_EACH, next);
601
678
  });
602
679
  });
603
680
  }
@@ -630,7 +707,7 @@ Runner.prototype.runSuite = function(suite, fn) {
630
707
  return fn();
631
708
  }
632
709
 
633
- this.emit('suite', (this.suite = suite));
710
+ this.emit(constants.EVENT_SUITE_BEGIN, (this.suite = suite));
634
711
 
635
712
  function next(errSuite) {
636
713
  if (errSuite) {
@@ -680,8 +757,8 @@ Runner.prototype.runSuite = function(suite, fn) {
680
757
  // remove reference to test
681
758
  delete self.test;
682
759
 
683
- self.hook('afterAll', function() {
684
- self.emit('suite end', suite);
760
+ self.hook(HOOK_TYPE_AFTER_ALL, function() {
761
+ self.emit(constants.EVENT_SUITE_END, suite);
685
762
  fn(errSuite);
686
763
  });
687
764
  }
@@ -689,7 +766,7 @@ Runner.prototype.runSuite = function(suite, fn) {
689
766
 
690
767
  this.nextSuite = next;
691
768
 
692
- this.hook('beforeAll', function(err) {
769
+ this.hook(HOOK_TYPE_BEFORE_ALL, function(err) {
693
770
  if (err) {
694
771
  return done();
695
772
  }
@@ -705,18 +782,13 @@ Runner.prototype.runSuite = function(suite, fn) {
705
782
  */
706
783
  Runner.prototype.uncaught = function(err) {
707
784
  if (err) {
708
- debug(
709
- 'uncaught exception %s',
710
- err ===
711
- function() {
712
- return this;
713
- }.call(err)
714
- ? err.message || err
715
- : err
716
- );
785
+ debug('uncaught exception %O', err);
717
786
  } else {
718
- debug('uncaught undefined exception');
719
- err = undefinedError();
787
+ debug('uncaught undefined/falsy exception');
788
+ err = createInvalidExceptionError(
789
+ 'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
790
+ err
791
+ );
720
792
  }
721
793
 
722
794
  if (!isError(err)) {
@@ -734,9 +806,9 @@ Runner.prototype.uncaught = function(err) {
734
806
  this.fail(runnable, err);
735
807
  } else {
736
808
  // Can't recover from this failure
737
- this.emit('start');
809
+ this.emit(constants.EVENT_RUN_BEGIN);
738
810
  this.fail(runnable, err);
739
- this.emit('end');
811
+ this.emit(constants.EVENT_RUN_END);
740
812
  }
741
813
 
742
814
  return;
@@ -756,14 +828,17 @@ Runner.prototype.uncaught = function(err) {
756
828
  this.fail(runnable, err);
757
829
  if (!alreadyPassed) {
758
830
  // recover from test
759
- if (runnable.type === 'test') {
760
- this.emit('test end', runnable);
761
- this.hookUp('afterEach', this.next);
831
+ if (runnable.type === constants.EVENT_TEST_BEGIN) {
832
+ this.emit(constants.EVENT_TEST_END, runnable);
833
+ this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
762
834
  return;
763
835
  }
836
+ debug(runnable);
764
837
 
765
838
  // recover from hooks
766
839
  var errSuite = this.suite;
840
+
841
+ // XXX how about a less awful way to determine this?
767
842
  // if hook failure is in afterEach block
768
843
  if (runnable.fullTitle().indexOf('after each') > -1) {
769
844
  return this.hookErr(err, errSuite, true);
@@ -777,53 +852,15 @@ Runner.prototype.uncaught = function(err) {
777
852
  }
778
853
 
779
854
  // bail
780
- this.emit('end');
855
+ this.emit(constants.EVENT_RUN_END);
781
856
  };
782
857
 
783
- /**
784
- * Cleans up the references to all the deferred functions
785
- * (before/after/beforeEach/afterEach) and tests of a Suite.
786
- * These must be deleted otherwise a memory leak can happen,
787
- * as those functions may reference variables from closures,
788
- * thus those variables can never be garbage collected as long
789
- * as the deferred functions exist.
790
- *
791
- * @param {Suite} suite
792
- */
793
- function cleanSuiteReferences(suite) {
794
- function cleanArrReferences(arr) {
795
- for (var i = 0; i < arr.length; i++) {
796
- delete arr[i].fn;
797
- }
798
- }
799
-
800
- if (Array.isArray(suite._beforeAll)) {
801
- cleanArrReferences(suite._beforeAll);
802
- }
803
-
804
- if (Array.isArray(suite._beforeEach)) {
805
- cleanArrReferences(suite._beforeEach);
806
- }
807
-
808
- if (Array.isArray(suite._afterAll)) {
809
- cleanArrReferences(suite._afterAll);
810
- }
811
-
812
- if (Array.isArray(suite._afterEach)) {
813
- cleanArrReferences(suite._afterEach);
814
- }
815
-
816
- for (var i = 0; i < suite.tests.length; i++) {
817
- delete suite.tests[i].fn;
818
- }
819
- }
820
-
821
858
  /**
822
859
  * Run the root suite and invoke `fn(failures)`
823
860
  * on completion.
824
861
  *
825
862
  * @public
826
- * @memberof Mocha.Runner
863
+ * @memberof Runner
827
864
  * @param {Function} fn
828
865
  * @return {Runner} Runner instance.
829
866
  */
@@ -839,30 +876,31 @@ Runner.prototype.run = function(fn) {
839
876
 
840
877
  function start() {
841
878
  // If there is an `only` filter
842
- if (hasOnly(rootSuite)) {
843
- filterOnly(rootSuite);
879
+ if (rootSuite.hasOnly()) {
880
+ rootSuite.filterOnly();
844
881
  }
845
882
  self.started = true;
846
- Runner.immediately(function() {
847
- self.emit('start');
848
- });
883
+ if (self._delay) {
884
+ self.emit(constants.EVENT_DELAY_END);
885
+ }
886
+ self.emit(constants.EVENT_RUN_BEGIN);
849
887
 
850
888
  self.runSuite(rootSuite, function() {
851
889
  debug('finished running');
852
- Runner.immediately(function() {
853
- self.emit('end');
854
- });
890
+ self.emit(constants.EVENT_RUN_END);
855
891
  });
856
892
  }
857
893
 
858
- debug('start');
894
+ debug(constants.EVENT_RUN_BEGIN);
859
895
 
860
896
  // references cleanup to avoid memory leaks
861
- this.on('suite end', cleanSuiteReferences);
897
+ this.on(constants.EVENT_SUITE_END, function(suite) {
898
+ suite.cleanReferences();
899
+ });
862
900
 
863
901
  // callback
864
- this.on('end', function() {
865
- debug('end');
902
+ this.on(constants.EVENT_RUN_END, function() {
903
+ debug(constants.EVENT_RUN_END);
866
904
  process.removeListener('uncaughtException', uncaught);
867
905
  fn(self.failures);
868
906
  });
@@ -873,8 +911,8 @@ Runner.prototype.run = function(fn) {
873
911
  if (this._delay) {
874
912
  // for reporters, I guess.
875
913
  // might be nice to debounce some dots while we wait.
876
- this.emit('waiting', rootSuite);
877
- rootSuite.once('run', start);
914
+ this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
915
+ rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
878
916
  } else {
879
917
  start();
880
918
  }
@@ -885,7 +923,7 @@ Runner.prototype.run = function(fn) {
885
923
  /**
886
924
  * Cleanly abort execution.
887
925
  *
888
- * @memberof Mocha.Runner
926
+ * @memberof Runner
889
927
  * @public
890
928
  * @return {Runner} Runner instance.
891
929
  */
@@ -896,54 +934,6 @@ Runner.prototype.abort = function() {
896
934
  return this;
897
935
  };
898
936
 
899
- /**
900
- * Filter suites based on `isOnly` logic.
901
- *
902
- * @param {Array} suite
903
- * @returns {Boolean}
904
- * @private
905
- */
906
- function filterOnly(suite) {
907
- if (suite._onlyTests.length) {
908
- // If the suite contains `only` tests, run those and ignore any nested suites.
909
- suite.tests = suite._onlyTests;
910
- suite.suites = [];
911
- } else {
912
- // Otherwise, do not run any of the tests in this suite.
913
- suite.tests = [];
914
- suite._onlySuites.forEach(function(onlySuite) {
915
- // If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
916
- // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
917
- if (hasOnly(onlySuite)) {
918
- filterOnly(onlySuite);
919
- }
920
- });
921
- // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
922
- suite.suites = suite.suites.filter(function(childSuite) {
923
- return (
924
- suite._onlySuites.indexOf(childSuite) !== -1 || filterOnly(childSuite)
925
- );
926
- });
927
- }
928
- // Keep the suite only if there is something to run
929
- return suite.tests.length || suite.suites.length;
930
- }
931
-
932
- /**
933
- * Determines whether a suite has an `only` test or suite as a descendant.
934
- *
935
- * @param {Array} suite
936
- * @returns {Boolean}
937
- * @private
938
- */
939
- function hasOnly(suite) {
940
- return (
941
- suite._onlyTests.length ||
942
- suite._onlySuites.length ||
943
- suite.suites.some(hasOnly)
944
- );
945
- }
946
-
947
937
  /**
948
938
  * Filter leaks with the given globals flagged as `ok`.
949
939
  *
@@ -1017,6 +1007,8 @@ function thrown2Error(err) {
1017
1007
  * Array of globals dependent on the environment.
1018
1008
  *
1019
1009
  * @return {Array}
1010
+ * @deprecated
1011
+ * @todo remove; long since unsupported
1020
1012
  * @private
1021
1013
  */
1022
1014
  function extraGlobals() {
@@ -1027,7 +1019,6 @@ function extraGlobals() {
1027
1019
  });
1028
1020
 
1029
1021
  // 'errno' was renamed to process._errno in v0.9.11.
1030
-
1031
1022
  if (nodeVersion < 0x00090b) {
1032
1023
  return ['errno'];
1033
1024
  }
@@ -1035,3 +1026,11 @@ function extraGlobals() {
1035
1026
 
1036
1027
  return [];
1037
1028
  }
1029
+
1030
+ Runner.constants = constants;
1031
+
1032
+ /**
1033
+ * Node.js' `EventEmitter`
1034
+ * @external EventEmitter
1035
+ * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter}
1036
+ */