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/CHANGELOG.md +38 -0
- package/bin/mocha +79 -45
- package/lib/browser/growl.js +3 -2
- package/lib/cli/node-flags.js +21 -0
- package/lib/cli/options.js +44 -13
- package/lib/cli/run-helpers.js +19 -10
- package/lib/cli/run-option-metadata.js +4 -0
- package/lib/cli/run.js +12 -8
- package/lib/errors.js +16 -14
- package/lib/growl.js +3 -2
- package/lib/interfaces/bdd.js +3 -1
- package/lib/interfaces/common.js +7 -6
- package/lib/interfaces/exports.js +1 -1
- package/lib/interfaces/qunit.js +3 -1
- package/lib/interfaces/tdd.js +3 -1
- package/lib/mocha.js +61 -27
- package/lib/reporters/base.js +5 -2
- package/lib/reporters/doc.js +9 -4
- package/lib/reporters/dot.js +11 -5
- package/lib/reporters/html.js +11 -5
- package/lib/reporters/json-stream.js +9 -4
- package/lib/reporters/json.js +11 -5
- package/lib/reporters/landing.js +10 -4
- package/lib/reporters/list.js +13 -6
- package/lib/reporters/markdown.js +9 -4
- package/lib/reporters/min.js +5 -2
- package/lib/reporters/nyan.js +11 -5
- package/lib/reporters/progress.js +7 -3
- package/lib/reporters/spec.js +15 -7
- package/lib/reporters/tap.js +13 -6
- package/lib/reporters/xunit.js +16 -9
- package/lib/runnable.js +50 -6
- package/lib/runner.js +187 -188
- package/lib/stats-collector.js +17 -15
- package/lib/suite.js +239 -26
- package/lib/test.js +3 -2
- package/lib/utils.js +256 -72
- package/mocha.js +1029 -458
- package/package.json +19 -4
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
|
|
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
|
|
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
|
-
|
|
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`
|
|
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
|
-
* @
|
|
120
|
+
* @extends external:EventEmitter
|
|
60
121
|
* @public
|
|
61
122
|
* @class
|
|
62
|
-
* @param {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(
|
|
136
|
+
this.on(constants.EVENT_TEST_END, function(test) {
|
|
76
137
|
self.checkGlobals(test);
|
|
77
138
|
});
|
|
78
|
-
this.on(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
267
|
+
if (leaks.length) {
|
|
268
|
+
var format = ngettext(
|
|
269
|
+
leaks.length,
|
|
270
|
+
'global leak detected: %s',
|
|
271
|
+
'global leaks detected: %s'
|
|
211
272
|
);
|
|
212
|
-
|
|
213
|
-
this.fail(test,
|
|
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 =
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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 ===
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
619
|
+
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
543
620
|
}
|
|
544
|
-
self.emit(
|
|
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(
|
|
550
|
-
self.hookDown(
|
|
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(
|
|
634
|
+
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
558
635
|
}
|
|
559
|
-
self.emit(
|
|
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(
|
|
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(
|
|
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(
|
|
661
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
585
662
|
} else {
|
|
586
663
|
self.fail(test, err);
|
|
587
664
|
}
|
|
588
|
-
self.emit(
|
|
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(
|
|
671
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
595
672
|
}
|
|
596
673
|
|
|
597
|
-
test.state =
|
|
598
|
-
self.emit(
|
|
599
|
-
self.emit(
|
|
600
|
-
self.hookUp(
|
|
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(
|
|
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(
|
|
684
|
-
self.emit(
|
|
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(
|
|
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 =
|
|
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(
|
|
809
|
+
this.emit(constants.EVENT_RUN_BEGIN);
|
|
738
810
|
this.fail(runnable, err);
|
|
739
|
-
this.emit(
|
|
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 ===
|
|
760
|
-
this.emit(
|
|
761
|
-
this.hookUp(
|
|
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(
|
|
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
|
|
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(
|
|
843
|
-
filterOnly(
|
|
879
|
+
if (rootSuite.hasOnly()) {
|
|
880
|
+
rootSuite.filterOnly();
|
|
844
881
|
}
|
|
845
882
|
self.started = true;
|
|
846
|
-
|
|
847
|
-
self.emit(
|
|
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
|
-
|
|
853
|
-
self.emit('end');
|
|
854
|
-
});
|
|
890
|
+
self.emit(constants.EVENT_RUN_END);
|
|
855
891
|
});
|
|
856
892
|
}
|
|
857
893
|
|
|
858
|
-
debug(
|
|
894
|
+
debug(constants.EVENT_RUN_BEGIN);
|
|
859
895
|
|
|
860
896
|
// references cleanup to avoid memory leaks
|
|
861
|
-
this.on(
|
|
897
|
+
this.on(constants.EVENT_SUITE_END, function(suite) {
|
|
898
|
+
suite.cleanReferences();
|
|
899
|
+
});
|
|
862
900
|
|
|
863
901
|
// callback
|
|
864
|
-
this.on(
|
|
865
|
-
debug(
|
|
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(
|
|
877
|
-
rootSuite.once(
|
|
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
|
|
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
|
+
*/
|