mocha 5.1.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 +686 -984
- package/README.md +2 -1
- package/{images → assets/growl}/error.png +0 -0
- package/{images → assets/growl}/ok.png +0 -0
- package/bin/_mocha +4 -595
- package/bin/mocha +121 -61
- package/bin/options.js +6 -39
- package/browser-entry.js +21 -17
- package/lib/browser/growl.js +165 -2
- package/lib/browser/progress.js +11 -11
- package/lib/{template.html → browser/template.html} +0 -0
- package/lib/browser/tty.js +2 -2
- package/lib/cli/cli.js +68 -0
- package/lib/cli/commands.js +13 -0
- package/lib/cli/config.js +79 -0
- package/lib/cli/index.js +9 -0
- package/lib/cli/init.js +37 -0
- package/lib/cli/node-flags.js +69 -0
- package/lib/cli/one-and-dones.js +70 -0
- package/lib/cli/options.js +330 -0
- package/lib/cli/run-helpers.js +337 -0
- package/lib/cli/run-option-metadata.js +76 -0
- package/lib/cli/run.js +297 -0
- package/lib/context.js +14 -14
- package/lib/errors.js +141 -0
- package/lib/growl.js +136 -0
- package/lib/hook.js +5 -16
- package/lib/interfaces/bdd.js +16 -13
- package/lib/interfaces/common.js +62 -18
- package/lib/interfaces/exports.js +5 -8
- package/lib/interfaces/qunit.js +10 -10
- package/lib/interfaces/tdd.js +12 -11
- package/lib/mocha.js +477 -256
- package/lib/mocharc.json +10 -0
- package/lib/pending.js +1 -5
- package/lib/reporters/base.js +95 -117
- package/lib/reporters/doc.js +23 -9
- package/lib/reporters/dot.js +19 -13
- package/lib/reporters/html.js +82 -47
- package/lib/reporters/json-stream.js +43 -23
- package/lib/reporters/json.js +32 -23
- package/lib/reporters/landing.js +16 -9
- package/lib/reporters/list.js +19 -11
- package/lib/reporters/markdown.js +18 -12
- package/lib/reporters/min.js +8 -4
- package/lib/reporters/nyan.js +42 -35
- package/lib/reporters/progress.js +12 -7
- package/lib/reporters/spec.js +23 -12
- package/lib/reporters/tap.js +250 -32
- package/lib/reporters/xunit.js +61 -35
- package/lib/runnable.js +152 -95
- package/lib/runner.js +296 -248
- package/lib/stats-collector.js +83 -0
- package/lib/suite.js +294 -75
- package/lib/test.js +16 -15
- package/lib/utils.js +419 -146
- package/mocha.js +4589 -2228
- package/package.json +137 -38
- package/lib/ms.js +0 -94
- package/lib/reporters/base.js.orig +0 -498
- package/lib/reporters/json.js.orig +0 -128
package/lib/runner.js
CHANGED
|
@@ -1,26 +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');
|
|
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;
|
|
15
24
|
var stackFilter = utils.stackTraceFilter();
|
|
16
25
|
var stringify = utils.stringify;
|
|
17
26
|
var type = utils.type;
|
|
18
|
-
var
|
|
27
|
+
var createInvalidExceptionError = require('./errors')
|
|
28
|
+
.createInvalidExceptionError;
|
|
19
29
|
|
|
20
30
|
/**
|
|
21
31
|
* Non-enumerable globals.
|
|
32
|
+
* @readonly
|
|
22
33
|
*/
|
|
23
|
-
|
|
24
34
|
var globals = [
|
|
25
35
|
'setTimeout',
|
|
26
36
|
'clearTimeout',
|
|
@@ -32,38 +42,89 @@ var globals = [
|
|
|
32
42
|
'clearImmediate'
|
|
33
43
|
];
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
);
|
|
38
114
|
|
|
39
115
|
module.exports = Runner;
|
|
40
116
|
|
|
41
117
|
/**
|
|
42
|
-
* Initialize a `Runner`
|
|
43
|
-
*
|
|
44
|
-
* Events:
|
|
45
|
-
*
|
|
46
|
-
* - `start` execution started
|
|
47
|
-
* - `end` execution complete
|
|
48
|
-
* - `suite` (suite) test suite execution started
|
|
49
|
-
* - `suite end` (suite) all tests (and sub-suites) have finished
|
|
50
|
-
* - `test` (test) test execution started
|
|
51
|
-
* - `test end` (test) test completed
|
|
52
|
-
* - `hook` (hook) hook execution started
|
|
53
|
-
* - `hook end` (hook) hook complete
|
|
54
|
-
* - `pass` (test) test passed
|
|
55
|
-
* - `fail` (test, err) test failed
|
|
56
|
-
* - `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}.
|
|
57
119
|
*
|
|
58
|
-
* @
|
|
120
|
+
* @extends external:EventEmitter
|
|
59
121
|
* @public
|
|
60
122
|
* @class
|
|
61
|
-
* @
|
|
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
|
*/
|
|
66
|
-
function Runner
|
|
127
|
+
function Runner(suite, delay) {
|
|
67
128
|
var self = this;
|
|
68
129
|
this._globals = [];
|
|
69
130
|
this._abort = false;
|
|
@@ -72,10 +133,10 @@ 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 = /.*/;
|
|
@@ -87,7 +148,7 @@ function Runner (suite, delay) {
|
|
|
87
148
|
* Wrapper for setImmediate, process.nextTick, or browser polyfill.
|
|
88
149
|
*
|
|
89
150
|
* @param {Function} fn
|
|
90
|
-
* @
|
|
151
|
+
* @private
|
|
91
152
|
*/
|
|
92
153
|
Runner.immediately = global.setImmediate || process.nextTick;
|
|
93
154
|
|
|
@@ -100,14 +161,13 @@ inherits(Runner, EventEmitter);
|
|
|
100
161
|
* Run tests with full titles matching `re`. Updates runner.total
|
|
101
162
|
* with number of tests matched.
|
|
102
163
|
*
|
|
103
|
-
* @api public
|
|
104
164
|
* @public
|
|
105
|
-
* @memberof
|
|
165
|
+
* @memberof Runner
|
|
106
166
|
* @param {RegExp} re
|
|
107
167
|
* @param {boolean} invert
|
|
108
168
|
* @return {Runner} Runner instance.
|
|
109
169
|
*/
|
|
110
|
-
Runner.prototype.grep = function
|
|
170
|
+
Runner.prototype.grep = function(re, invert) {
|
|
111
171
|
debug('grep %s', re);
|
|
112
172
|
this._grep = re;
|
|
113
173
|
this._invert = invert;
|
|
@@ -119,17 +179,16 @@ 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
|
|
123
|
-
* @api public
|
|
182
|
+
* @memberof Runner
|
|
124
183
|
* @public
|
|
125
184
|
* @param {Suite} suite
|
|
126
185
|
* @return {number}
|
|
127
186
|
*/
|
|
128
|
-
Runner.prototype.grepTotal = function
|
|
187
|
+
Runner.prototype.grepTotal = function(suite) {
|
|
129
188
|
var self = this;
|
|
130
189
|
var total = 0;
|
|
131
190
|
|
|
132
|
-
suite.eachTest(function
|
|
191
|
+
suite.eachTest(function(test) {
|
|
133
192
|
var match = self._grep.test(test.fullTitle());
|
|
134
193
|
if (self._invert) {
|
|
135
194
|
match = !match;
|
|
@@ -146,9 +205,9 @@ Runner.prototype.grepTotal = function (suite) {
|
|
|
146
205
|
* Return a list of global properties.
|
|
147
206
|
*
|
|
148
207
|
* @return {Array}
|
|
149
|
-
* @
|
|
208
|
+
* @private
|
|
150
209
|
*/
|
|
151
|
-
Runner.prototype.globalProps = function
|
|
210
|
+
Runner.prototype.globalProps = function() {
|
|
152
211
|
var props = Object.keys(global);
|
|
153
212
|
|
|
154
213
|
// non-enumerables
|
|
@@ -165,13 +224,12 @@ Runner.prototype.globalProps = function () {
|
|
|
165
224
|
/**
|
|
166
225
|
* Allow the given `arr` of globals.
|
|
167
226
|
*
|
|
168
|
-
* @api public
|
|
169
227
|
* @public
|
|
170
|
-
* @memberof
|
|
228
|
+
* @memberof Runner
|
|
171
229
|
* @param {Array} arr
|
|
172
230
|
* @return {Runner} Runner instance.
|
|
173
231
|
*/
|
|
174
|
-
Runner.prototype.globals = function
|
|
232
|
+
Runner.prototype.globals = function(arr) {
|
|
175
233
|
if (!arguments.length) {
|
|
176
234
|
return this._globals;
|
|
177
235
|
}
|
|
@@ -183,9 +241,9 @@ Runner.prototype.globals = function (arr) {
|
|
|
183
241
|
/**
|
|
184
242
|
* Check for global variable leaks.
|
|
185
243
|
*
|
|
186
|
-
* @
|
|
244
|
+
* @private
|
|
187
245
|
*/
|
|
188
|
-
Runner.prototype.checkGlobals = function
|
|
246
|
+
Runner.prototype.checkGlobals = function(test) {
|
|
189
247
|
if (this.ignoreLeaks) {
|
|
190
248
|
return;
|
|
191
249
|
}
|
|
@@ -206,48 +264,52 @@ Runner.prototype.checkGlobals = function (test) {
|
|
|
206
264
|
leaks = filterLeaks(ok, globals);
|
|
207
265
|
this._globals = this._globals.concat(leaks);
|
|
208
266
|
|
|
209
|
-
if (leaks.length
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
267
|
+
if (leaks.length) {
|
|
268
|
+
var format = ngettext(
|
|
269
|
+
leaks.length,
|
|
270
|
+
'global leak detected: %s',
|
|
271
|
+
'global leaks detected: %s'
|
|
272
|
+
);
|
|
273
|
+
var error = new Error(util.format(format, leaks.map(sQuote).join(', ')));
|
|
274
|
+
this.fail(test, error);
|
|
213
275
|
}
|
|
214
276
|
};
|
|
215
277
|
|
|
216
278
|
/**
|
|
217
279
|
* Fail the given `test`.
|
|
218
280
|
*
|
|
219
|
-
* @
|
|
281
|
+
* @private
|
|
220
282
|
* @param {Test} test
|
|
221
283
|
* @param {Error} err
|
|
222
284
|
*/
|
|
223
|
-
Runner.prototype.fail = function
|
|
285
|
+
Runner.prototype.fail = function(test, err) {
|
|
224
286
|
if (test.isPending()) {
|
|
225
287
|
return;
|
|
226
288
|
}
|
|
227
289
|
|
|
228
290
|
++this.failures;
|
|
229
|
-
test.state =
|
|
291
|
+
test.state = STATE_FAILED;
|
|
230
292
|
|
|
231
|
-
if (!(err
|
|
232
|
-
err =
|
|
293
|
+
if (!isError(err)) {
|
|
294
|
+
err = thrown2Error(err);
|
|
233
295
|
}
|
|
234
296
|
|
|
235
297
|
try {
|
|
236
|
-
err.stack =
|
|
237
|
-
? err.stack
|
|
238
|
-
|
|
239
|
-
} catch (ignored) {
|
|
298
|
+
err.stack =
|
|
299
|
+
this.fullStackTrace || !err.stack ? err.stack : stackFilter(err.stack);
|
|
300
|
+
} catch (ignore) {
|
|
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
|
/**
|
|
247
308
|
* Fail the given `hook` with `err`.
|
|
248
309
|
*
|
|
249
310
|
* Hook failures work in the following pattern:
|
|
250
|
-
* - If bail,
|
|
311
|
+
* - If bail, run corresponding `after each` and `after` hooks,
|
|
312
|
+
* then exit
|
|
251
313
|
* - Failed `before` hook skips all tests in a suite and subsuites,
|
|
252
314
|
* but jumps to corresponding `after` hook
|
|
253
315
|
* - Failed `before each` hook skips remaining tests in a
|
|
@@ -259,65 +321,80 @@ Runner.prototype.fail = function (test, err) {
|
|
|
259
321
|
* suite and subsuites, but executes other `after each`
|
|
260
322
|
* hooks
|
|
261
323
|
*
|
|
262
|
-
* @
|
|
324
|
+
* @private
|
|
263
325
|
* @param {Hook} hook
|
|
264
326
|
* @param {Error} err
|
|
265
327
|
*/
|
|
266
|
-
Runner.prototype.failHook = function
|
|
328
|
+
Runner.prototype.failHook = function(hook, err) {
|
|
329
|
+
hook.originalTitle = hook.originalTitle || hook.title;
|
|
267
330
|
if (hook.ctx && hook.ctx.currentTest) {
|
|
268
|
-
hook.
|
|
269
|
-
|
|
331
|
+
hook.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);
|
|
270
341
|
}
|
|
271
342
|
|
|
272
|
-
if (this.suite.bail()) {
|
|
273
|
-
this.emit('end');
|
|
274
|
-
}
|
|
275
343
|
this.fail(hook, err);
|
|
276
344
|
};
|
|
277
345
|
|
|
278
346
|
/**
|
|
279
347
|
* Run hook `name` callbacks and then invoke `fn()`.
|
|
280
348
|
*
|
|
281
|
-
* @
|
|
349
|
+
* @private
|
|
282
350
|
* @param {string} name
|
|
283
351
|
* @param {Function} fn
|
|
284
352
|
*/
|
|
285
353
|
|
|
286
|
-
Runner.prototype.hook = function
|
|
354
|
+
Runner.prototype.hook = function(name, fn) {
|
|
287
355
|
var suite = this.suite;
|
|
288
|
-
var hooks = suite
|
|
356
|
+
var hooks = suite.getHooks(name);
|
|
289
357
|
var self = this;
|
|
290
358
|
|
|
291
|
-
function next
|
|
359
|
+
function next(i) {
|
|
292
360
|
var hook = hooks[i];
|
|
293
361
|
if (!hook) {
|
|
294
362
|
return fn();
|
|
295
363
|
}
|
|
296
364
|
self.currentRunnable = hook;
|
|
297
365
|
|
|
298
|
-
|
|
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
|
+
}
|
|
299
373
|
|
|
300
|
-
self.emit(
|
|
374
|
+
self.emit(constants.EVENT_HOOK_BEGIN, hook);
|
|
301
375
|
|
|
302
376
|
if (!hook.listeners('error').length) {
|
|
303
|
-
hook.on('error', function
|
|
377
|
+
hook.on('error', function(err) {
|
|
304
378
|
self.failHook(hook, err);
|
|
305
379
|
});
|
|
306
380
|
}
|
|
307
381
|
|
|
308
|
-
hook.run(function
|
|
382
|
+
hook.run(function(err) {
|
|
309
383
|
var testError = hook.error();
|
|
310
384
|
if (testError) {
|
|
311
385
|
self.fail(self.test, testError);
|
|
312
386
|
}
|
|
313
387
|
if (err) {
|
|
314
388
|
if (err instanceof Pending) {
|
|
315
|
-
if (name ===
|
|
389
|
+
if (name === HOOK_TYPE_BEFORE_EACH || name === HOOK_TYPE_AFTER_EACH) {
|
|
316
390
|
self.test.pending = true;
|
|
317
391
|
} else {
|
|
318
|
-
suite.tests.forEach(function
|
|
392
|
+
suite.tests.forEach(function(test) {
|
|
319
393
|
test.pending = true;
|
|
320
394
|
});
|
|
395
|
+
suite.suites.forEach(function(suite) {
|
|
396
|
+
suite.pending = true;
|
|
397
|
+
});
|
|
321
398
|
// a pending hook won't be executed twice.
|
|
322
399
|
hook.pending = true;
|
|
323
400
|
}
|
|
@@ -328,13 +405,13 @@ Runner.prototype.hook = function (name, fn) {
|
|
|
328
405
|
return fn(err);
|
|
329
406
|
}
|
|
330
407
|
}
|
|
331
|
-
self.emit(
|
|
408
|
+
self.emit(constants.EVENT_HOOK_END, hook);
|
|
332
409
|
delete hook.ctx.currentTest;
|
|
333
410
|
next(++i);
|
|
334
411
|
});
|
|
335
412
|
}
|
|
336
413
|
|
|
337
|
-
Runner.immediately(function
|
|
414
|
+
Runner.immediately(function() {
|
|
338
415
|
next(0);
|
|
339
416
|
});
|
|
340
417
|
};
|
|
@@ -343,16 +420,16 @@ Runner.prototype.hook = function (name, fn) {
|
|
|
343
420
|
* Run hook `name` for the given array of `suites`
|
|
344
421
|
* in order, and callback `fn(err, errSuite)`.
|
|
345
422
|
*
|
|
346
|
-
* @
|
|
423
|
+
* @private
|
|
347
424
|
* @param {string} name
|
|
348
425
|
* @param {Array} suites
|
|
349
426
|
* @param {Function} fn
|
|
350
427
|
*/
|
|
351
|
-
Runner.prototype.hooks = function
|
|
428
|
+
Runner.prototype.hooks = function(name, suites, fn) {
|
|
352
429
|
var self = this;
|
|
353
430
|
var orig = this.suite;
|
|
354
431
|
|
|
355
|
-
function next
|
|
432
|
+
function next(suite) {
|
|
356
433
|
self.suite = suite;
|
|
357
434
|
|
|
358
435
|
if (!suite) {
|
|
@@ -360,7 +437,7 @@ Runner.prototype.hooks = function (name, suites, fn) {
|
|
|
360
437
|
return fn();
|
|
361
438
|
}
|
|
362
439
|
|
|
363
|
-
self.hook(name, function
|
|
440
|
+
self.hook(name, function(err) {
|
|
364
441
|
if (err) {
|
|
365
442
|
var errSuite = self.suite;
|
|
366
443
|
self.suite = orig;
|
|
@@ -379,9 +456,9 @@ Runner.prototype.hooks = function (name, suites, fn) {
|
|
|
379
456
|
*
|
|
380
457
|
* @param {String} name
|
|
381
458
|
* @param {Function} fn
|
|
382
|
-
* @
|
|
459
|
+
* @private
|
|
383
460
|
*/
|
|
384
|
-
Runner.prototype.hookUp = function
|
|
461
|
+
Runner.prototype.hookUp = function(name, fn) {
|
|
385
462
|
var suites = [this.suite].concat(this.parents()).reverse();
|
|
386
463
|
this.hooks(name, suites, fn);
|
|
387
464
|
};
|
|
@@ -391,9 +468,9 @@ Runner.prototype.hookUp = function (name, fn) {
|
|
|
391
468
|
*
|
|
392
469
|
* @param {String} name
|
|
393
470
|
* @param {Function} fn
|
|
394
|
-
* @
|
|
471
|
+
* @private
|
|
395
472
|
*/
|
|
396
|
-
Runner.prototype.hookDown = function
|
|
473
|
+
Runner.prototype.hookDown = function(name, fn) {
|
|
397
474
|
var suites = [this.suite].concat(this.parents());
|
|
398
475
|
this.hooks(name, suites, fn);
|
|
399
476
|
};
|
|
@@ -403,9 +480,9 @@ Runner.prototype.hookDown = function (name, fn) {
|
|
|
403
480
|
* closest to furthest.
|
|
404
481
|
*
|
|
405
482
|
* @return {Array}
|
|
406
|
-
* @
|
|
483
|
+
* @private
|
|
407
484
|
*/
|
|
408
|
-
Runner.prototype.parents = function
|
|
485
|
+
Runner.prototype.parents = function() {
|
|
409
486
|
var suite = this.suite;
|
|
410
487
|
var suites = [];
|
|
411
488
|
while (suite.parent) {
|
|
@@ -419,23 +496,25 @@ Runner.prototype.parents = function () {
|
|
|
419
496
|
* Run the current test and callback `fn(err)`.
|
|
420
497
|
*
|
|
421
498
|
* @param {Function} fn
|
|
422
|
-
* @
|
|
499
|
+
* @private
|
|
423
500
|
*/
|
|
424
|
-
Runner.prototype.runTest = function
|
|
501
|
+
Runner.prototype.runTest = function(fn) {
|
|
425
502
|
var self = this;
|
|
426
503
|
var test = this.test;
|
|
427
504
|
|
|
428
505
|
if (!test) {
|
|
429
506
|
return;
|
|
430
507
|
}
|
|
431
|
-
|
|
508
|
+
|
|
509
|
+
var suite = this.parents().reverse()[0] || this.suite;
|
|
510
|
+
if (this.forbidOnly && suite.hasOnly()) {
|
|
432
511
|
fn(new Error('`.only` forbidden'));
|
|
433
512
|
return;
|
|
434
513
|
}
|
|
435
514
|
if (this.asyncOnly) {
|
|
436
515
|
test.asyncOnly = true;
|
|
437
516
|
}
|
|
438
|
-
test.on('error', function
|
|
517
|
+
test.on('error', function(err) {
|
|
439
518
|
self.fail(test, err);
|
|
440
519
|
});
|
|
441
520
|
if (this.allowUncaught) {
|
|
@@ -452,16 +531,16 @@ Runner.prototype.runTest = function (fn) {
|
|
|
452
531
|
/**
|
|
453
532
|
* Run tests in the given `suite` and invoke the callback `fn()` when complete.
|
|
454
533
|
*
|
|
455
|
-
* @
|
|
534
|
+
* @private
|
|
456
535
|
* @param {Suite} suite
|
|
457
536
|
* @param {Function} fn
|
|
458
537
|
*/
|
|
459
|
-
Runner.prototype.runTests = function
|
|
538
|
+
Runner.prototype.runTests = function(suite, fn) {
|
|
460
539
|
var self = this;
|
|
461
540
|
var tests = suite.tests.slice();
|
|
462
541
|
var test;
|
|
463
542
|
|
|
464
|
-
function hookErr
|
|
543
|
+
function hookErr(_, errSuite, after) {
|
|
465
544
|
// before/after Each hook for errSuite failed:
|
|
466
545
|
var orig = self.suite;
|
|
467
546
|
|
|
@@ -471,7 +550,7 @@ Runner.prototype.runTests = function (suite, fn) {
|
|
|
471
550
|
|
|
472
551
|
if (self.suite) {
|
|
473
552
|
// call hookUp afterEach
|
|
474
|
-
self.hookUp(
|
|
553
|
+
self.hookUp(HOOK_TYPE_AFTER_EACH, function(err2, errSuite2) {
|
|
475
554
|
self.suite = orig;
|
|
476
555
|
// some hooks may fail even now
|
|
477
556
|
if (err2) {
|
|
@@ -487,10 +566,10 @@ Runner.prototype.runTests = function (suite, fn) {
|
|
|
487
566
|
}
|
|
488
567
|
}
|
|
489
568
|
|
|
490
|
-
function next
|
|
569
|
+
function next(err, errSuite) {
|
|
491
570
|
// if we bail after first err
|
|
492
571
|
if (self.failures && suite._bail) {
|
|
493
|
-
|
|
572
|
+
tests = [];
|
|
494
573
|
}
|
|
495
574
|
|
|
496
575
|
if (self._abort) {
|
|
@@ -537,31 +616,31 @@ Runner.prototype.runTests = function (suite, fn) {
|
|
|
537
616
|
self.fail(test, new Error('Pending test forbidden'));
|
|
538
617
|
delete test.isPending;
|
|
539
618
|
} else {
|
|
540
|
-
self.emit(
|
|
619
|
+
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
541
620
|
}
|
|
542
|
-
self.emit(
|
|
621
|
+
self.emit(constants.EVENT_TEST_END, test);
|
|
543
622
|
return next();
|
|
544
623
|
}
|
|
545
624
|
|
|
546
625
|
// execute test and hook(s)
|
|
547
|
-
self.emit(
|
|
548
|
-
self.hookDown(
|
|
626
|
+
self.emit(constants.EVENT_TEST_BEGIN, (self.test = test));
|
|
627
|
+
self.hookDown(HOOK_TYPE_BEFORE_EACH, function(err, errSuite) {
|
|
549
628
|
if (test.isPending()) {
|
|
550
629
|
if (self.forbidPending) {
|
|
551
630
|
test.isPending = alwaysFalse;
|
|
552
631
|
self.fail(test, new Error('Pending test forbidden'));
|
|
553
632
|
delete test.isPending;
|
|
554
633
|
} else {
|
|
555
|
-
self.emit(
|
|
634
|
+
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
556
635
|
}
|
|
557
|
-
self.emit(
|
|
636
|
+
self.emit(constants.EVENT_TEST_END, test);
|
|
558
637
|
return next();
|
|
559
638
|
}
|
|
560
639
|
if (err) {
|
|
561
640
|
return hookErr(err, errSuite, false);
|
|
562
641
|
}
|
|
563
642
|
self.currentRunnable = self.test;
|
|
564
|
-
self.runTest(function
|
|
643
|
+
self.runTest(function(err) {
|
|
565
644
|
test = self.test;
|
|
566
645
|
if (err) {
|
|
567
646
|
var retry = test.currentRetry();
|
|
@@ -569,31 +648,33 @@ Runner.prototype.runTests = function (suite, fn) {
|
|
|
569
648
|
self.fail(test, new Error('Pending test forbidden'));
|
|
570
649
|
} else if (err instanceof Pending) {
|
|
571
650
|
test.pending = true;
|
|
572
|
-
self.emit(
|
|
651
|
+
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
573
652
|
} else if (retry < test.retries()) {
|
|
574
653
|
var clonedTest = test.clone();
|
|
575
654
|
clonedTest.currentRetry(retry + 1);
|
|
576
655
|
tests.unshift(clonedTest);
|
|
577
656
|
|
|
657
|
+
self.emit(constants.EVENT_TEST_RETRY, test, err);
|
|
658
|
+
|
|
578
659
|
// Early return + hook trigger so that it doesn't
|
|
579
660
|
// increment the count wrong
|
|
580
|
-
return self.hookUp(
|
|
661
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
581
662
|
} else {
|
|
582
663
|
self.fail(test, err);
|
|
583
664
|
}
|
|
584
|
-
self.emit(
|
|
665
|
+
self.emit(constants.EVENT_TEST_END, test);
|
|
585
666
|
|
|
586
667
|
if (err instanceof Pending) {
|
|
587
668
|
return next();
|
|
588
669
|
}
|
|
589
670
|
|
|
590
|
-
return self.hookUp(
|
|
671
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
591
672
|
}
|
|
592
673
|
|
|
593
|
-
test.state =
|
|
594
|
-
self.emit(
|
|
595
|
-
self.emit(
|
|
596
|
-
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);
|
|
597
678
|
});
|
|
598
679
|
});
|
|
599
680
|
}
|
|
@@ -603,18 +684,18 @@ Runner.prototype.runTests = function (suite, fn) {
|
|
|
603
684
|
next();
|
|
604
685
|
};
|
|
605
686
|
|
|
606
|
-
function alwaysFalse
|
|
687
|
+
function alwaysFalse() {
|
|
607
688
|
return false;
|
|
608
689
|
}
|
|
609
690
|
|
|
610
691
|
/**
|
|
611
692
|
* Run the given `suite` and invoke the callback `fn()` when complete.
|
|
612
693
|
*
|
|
613
|
-
* @
|
|
694
|
+
* @private
|
|
614
695
|
* @param {Suite} suite
|
|
615
696
|
* @param {Function} fn
|
|
616
697
|
*/
|
|
617
|
-
Runner.prototype.runSuite = function
|
|
698
|
+
Runner.prototype.runSuite = function(suite, fn) {
|
|
618
699
|
var i = 0;
|
|
619
700
|
var self = this;
|
|
620
701
|
var total = this.grepTotal(suite);
|
|
@@ -626,9 +707,9 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
626
707
|
return fn();
|
|
627
708
|
}
|
|
628
709
|
|
|
629
|
-
this.emit(
|
|
710
|
+
this.emit(constants.EVENT_SUITE_BEGIN, (this.suite = suite));
|
|
630
711
|
|
|
631
|
-
function next
|
|
712
|
+
function next(errSuite) {
|
|
632
713
|
if (errSuite) {
|
|
633
714
|
// current suite failed on a hook from errSuite
|
|
634
715
|
if (errSuite === suite) {
|
|
@@ -654,7 +735,7 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
654
735
|
// huge recursive loop and thus a maximum call stack error.
|
|
655
736
|
// See comment in `this.runTests()` for more information.
|
|
656
737
|
if (self._grep !== self._defaultGrep) {
|
|
657
|
-
Runner.immediately(function
|
|
738
|
+
Runner.immediately(function() {
|
|
658
739
|
self.runSuite(curr, next);
|
|
659
740
|
});
|
|
660
741
|
} else {
|
|
@@ -662,7 +743,7 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
662
743
|
}
|
|
663
744
|
}
|
|
664
745
|
|
|
665
|
-
function done
|
|
746
|
+
function done(errSuite) {
|
|
666
747
|
self.suite = suite;
|
|
667
748
|
self.nextSuite = next;
|
|
668
749
|
|
|
@@ -676,8 +757,8 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
676
757
|
// remove reference to test
|
|
677
758
|
delete self.test;
|
|
678
759
|
|
|
679
|
-
self.hook(
|
|
680
|
-
self.emit(
|
|
760
|
+
self.hook(HOOK_TYPE_AFTER_ALL, function() {
|
|
761
|
+
self.emit(constants.EVENT_SUITE_END, suite);
|
|
681
762
|
fn(errSuite);
|
|
682
763
|
});
|
|
683
764
|
}
|
|
@@ -685,7 +766,7 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
685
766
|
|
|
686
767
|
this.nextSuite = next;
|
|
687
768
|
|
|
688
|
-
this.hook(
|
|
769
|
+
this.hook(HOOK_TYPE_BEFORE_ALL, function(err) {
|
|
689
770
|
if (err) {
|
|
690
771
|
return done();
|
|
691
772
|
}
|
|
@@ -697,16 +778,21 @@ Runner.prototype.runSuite = function (suite, fn) {
|
|
|
697
778
|
* Handle uncaught exceptions.
|
|
698
779
|
*
|
|
699
780
|
* @param {Error} err
|
|
700
|
-
* @
|
|
781
|
+
* @private
|
|
701
782
|
*/
|
|
702
|
-
Runner.prototype.uncaught = function
|
|
783
|
+
Runner.prototype.uncaught = function(err) {
|
|
703
784
|
if (err) {
|
|
704
|
-
debug('uncaught exception %
|
|
705
|
-
return this;
|
|
706
|
-
}.call(err)) ? (err.message || err) : err);
|
|
785
|
+
debug('uncaught exception %O', err);
|
|
707
786
|
} else {
|
|
708
|
-
debug('uncaught undefined exception');
|
|
709
|
-
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
|
+
);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (!isError(err)) {
|
|
795
|
+
err = thrown2Error(err);
|
|
710
796
|
}
|
|
711
797
|
err.uncaught = true;
|
|
712
798
|
|
|
@@ -720,9 +806,9 @@ Runner.prototype.uncaught = function (err) {
|
|
|
720
806
|
this.fail(runnable, err);
|
|
721
807
|
} else {
|
|
722
808
|
// Can't recover from this failure
|
|
723
|
-
this.emit(
|
|
809
|
+
this.emit(constants.EVENT_RUN_BEGIN);
|
|
724
810
|
this.fail(runnable, err);
|
|
725
|
-
this.emit(
|
|
811
|
+
this.emit(constants.EVENT_RUN_END);
|
|
726
812
|
}
|
|
727
813
|
|
|
728
814
|
return;
|
|
@@ -742,14 +828,17 @@ Runner.prototype.uncaught = function (err) {
|
|
|
742
828
|
this.fail(runnable, err);
|
|
743
829
|
if (!alreadyPassed) {
|
|
744
830
|
// recover from test
|
|
745
|
-
if (runnable.type ===
|
|
746
|
-
this.emit(
|
|
747
|
-
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);
|
|
748
834
|
return;
|
|
749
835
|
}
|
|
836
|
+
debug(runnable);
|
|
750
837
|
|
|
751
838
|
// recover from hooks
|
|
752
839
|
var errSuite = this.suite;
|
|
840
|
+
|
|
841
|
+
// XXX how about a less awful way to determine this?
|
|
753
842
|
// if hook failure is in afterEach block
|
|
754
843
|
if (runnable.fullTitle().indexOf('after each') > -1) {
|
|
755
844
|
return this.hookErr(err, errSuite, true);
|
|
@@ -763,88 +852,55 @@ Runner.prototype.uncaught = function (err) {
|
|
|
763
852
|
}
|
|
764
853
|
|
|
765
854
|
// bail
|
|
766
|
-
this.emit(
|
|
855
|
+
this.emit(constants.EVENT_RUN_END);
|
|
767
856
|
};
|
|
768
857
|
|
|
769
|
-
/**
|
|
770
|
-
* Cleans up the references to all the deferred functions
|
|
771
|
-
* (before/after/beforeEach/afterEach) and tests of a Suite.
|
|
772
|
-
* These must be deleted otherwise a memory leak can happen,
|
|
773
|
-
* as those functions may reference variables from closures,
|
|
774
|
-
* thus those variables can never be garbage collected as long
|
|
775
|
-
* as the deferred functions exist.
|
|
776
|
-
*
|
|
777
|
-
* @param {Suite} suite
|
|
778
|
-
*/
|
|
779
|
-
function cleanSuiteReferences (suite) {
|
|
780
|
-
function cleanArrReferences (arr) {
|
|
781
|
-
for (var i = 0; i < arr.length; i++) {
|
|
782
|
-
delete arr[i].fn;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (Array.isArray(suite._beforeAll)) {
|
|
787
|
-
cleanArrReferences(suite._beforeAll);
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (Array.isArray(suite._beforeEach)) {
|
|
791
|
-
cleanArrReferences(suite._beforeEach);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
if (Array.isArray(suite._afterAll)) {
|
|
795
|
-
cleanArrReferences(suite._afterAll);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
if (Array.isArray(suite._afterEach)) {
|
|
799
|
-
cleanArrReferences(suite._afterEach);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
for (var i = 0; i < suite.tests.length; i++) {
|
|
803
|
-
delete suite.tests[i].fn;
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
|
|
807
858
|
/**
|
|
808
859
|
* Run the root suite and invoke `fn(failures)`
|
|
809
860
|
* on completion.
|
|
810
861
|
*
|
|
811
|
-
* @api public
|
|
812
862
|
* @public
|
|
813
|
-
* @memberof
|
|
863
|
+
* @memberof Runner
|
|
814
864
|
* @param {Function} fn
|
|
815
865
|
* @return {Runner} Runner instance.
|
|
816
866
|
*/
|
|
817
|
-
Runner.prototype.run = function
|
|
867
|
+
Runner.prototype.run = function(fn) {
|
|
818
868
|
var self = this;
|
|
819
869
|
var rootSuite = this.suite;
|
|
820
870
|
|
|
821
|
-
fn = fn || function
|
|
871
|
+
fn = fn || function() {};
|
|
822
872
|
|
|
823
|
-
function uncaught
|
|
873
|
+
function uncaught(err) {
|
|
824
874
|
self.uncaught(err);
|
|
825
875
|
}
|
|
826
876
|
|
|
827
|
-
function start
|
|
877
|
+
function start() {
|
|
828
878
|
// If there is an `only` filter
|
|
829
|
-
if (hasOnly(
|
|
830
|
-
filterOnly(
|
|
879
|
+
if (rootSuite.hasOnly()) {
|
|
880
|
+
rootSuite.filterOnly();
|
|
831
881
|
}
|
|
832
882
|
self.started = true;
|
|
833
|
-
self.
|
|
834
|
-
|
|
883
|
+
if (self._delay) {
|
|
884
|
+
self.emit(constants.EVENT_DELAY_END);
|
|
885
|
+
}
|
|
886
|
+
self.emit(constants.EVENT_RUN_BEGIN);
|
|
887
|
+
|
|
888
|
+
self.runSuite(rootSuite, function() {
|
|
835
889
|
debug('finished running');
|
|
836
|
-
self.emit(
|
|
890
|
+
self.emit(constants.EVENT_RUN_END);
|
|
837
891
|
});
|
|
838
892
|
}
|
|
839
893
|
|
|
840
|
-
debug(
|
|
894
|
+
debug(constants.EVENT_RUN_BEGIN);
|
|
841
895
|
|
|
842
896
|
// references cleanup to avoid memory leaks
|
|
843
|
-
this.on(
|
|
897
|
+
this.on(constants.EVENT_SUITE_END, function(suite) {
|
|
898
|
+
suite.cleanReferences();
|
|
899
|
+
});
|
|
844
900
|
|
|
845
901
|
// callback
|
|
846
|
-
this.on(
|
|
847
|
-
debug(
|
|
902
|
+
this.on(constants.EVENT_RUN_END, function() {
|
|
903
|
+
debug(constants.EVENT_RUN_END);
|
|
848
904
|
process.removeListener('uncaughtException', uncaught);
|
|
849
905
|
fn(self.failures);
|
|
850
906
|
});
|
|
@@ -855,8 +911,8 @@ Runner.prototype.run = function (fn) {
|
|
|
855
911
|
if (this._delay) {
|
|
856
912
|
// for reporters, I guess.
|
|
857
913
|
// might be nice to debounce some dots while we wait.
|
|
858
|
-
this.emit(
|
|
859
|
-
rootSuite.once(
|
|
914
|
+
this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
|
|
915
|
+
rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
|
|
860
916
|
} else {
|
|
861
917
|
start();
|
|
862
918
|
}
|
|
@@ -867,70 +923,27 @@ Runner.prototype.run = function (fn) {
|
|
|
867
923
|
/**
|
|
868
924
|
* Cleanly abort execution.
|
|
869
925
|
*
|
|
870
|
-
* @memberof
|
|
926
|
+
* @memberof Runner
|
|
871
927
|
* @public
|
|
872
|
-
* @api public
|
|
873
928
|
* @return {Runner} Runner instance.
|
|
874
929
|
*/
|
|
875
|
-
Runner.prototype.abort = function
|
|
930
|
+
Runner.prototype.abort = function() {
|
|
876
931
|
debug('aborting');
|
|
877
932
|
this._abort = true;
|
|
878
933
|
|
|
879
934
|
return this;
|
|
880
935
|
};
|
|
881
936
|
|
|
882
|
-
/**
|
|
883
|
-
* Filter suites based on `isOnly` logic.
|
|
884
|
-
*
|
|
885
|
-
* @param {Array} suite
|
|
886
|
-
* @returns {Boolean}
|
|
887
|
-
* @api private
|
|
888
|
-
*/
|
|
889
|
-
function filterOnly (suite) {
|
|
890
|
-
if (suite._onlyTests.length) {
|
|
891
|
-
// If the suite contains `only` tests, run those and ignore any nested suites.
|
|
892
|
-
suite.tests = suite._onlyTests;
|
|
893
|
-
suite.suites = [];
|
|
894
|
-
} else {
|
|
895
|
-
// Otherwise, do not run any of the tests in this suite.
|
|
896
|
-
suite.tests = [];
|
|
897
|
-
suite._onlySuites.forEach(function (onlySuite) {
|
|
898
|
-
// If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
|
|
899
|
-
// Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
|
|
900
|
-
if (hasOnly(onlySuite)) {
|
|
901
|
-
filterOnly(onlySuite);
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
// Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
|
|
905
|
-
suite.suites = suite.suites.filter(function (childSuite) {
|
|
906
|
-
return suite._onlySuites.indexOf(childSuite) !== -1 || filterOnly(childSuite);
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
// Keep the suite only if there is something to run
|
|
910
|
-
return suite.tests.length || suite.suites.length;
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
/**
|
|
914
|
-
* Determines whether a suite has an `only` test or suite as a descendant.
|
|
915
|
-
*
|
|
916
|
-
* @param {Array} suite
|
|
917
|
-
* @returns {Boolean}
|
|
918
|
-
* @api private
|
|
919
|
-
*/
|
|
920
|
-
function hasOnly (suite) {
|
|
921
|
-
return suite._onlyTests.length || suite._onlySuites.length || suite.suites.some(hasOnly);
|
|
922
|
-
}
|
|
923
|
-
|
|
924
937
|
/**
|
|
925
938
|
* Filter leaks with the given globals flagged as `ok`.
|
|
926
939
|
*
|
|
927
|
-
* @
|
|
940
|
+
* @private
|
|
928
941
|
* @param {Array} ok
|
|
929
942
|
* @param {Array} globals
|
|
930
943
|
* @return {Array}
|
|
931
944
|
*/
|
|
932
|
-
function filterLeaks
|
|
933
|
-
return globals.filter(function
|
|
945
|
+
function filterLeaks(ok, globals) {
|
|
946
|
+
return globals.filter(function(key) {
|
|
934
947
|
// Firefox and Chrome exposes iframes as index inside the window object
|
|
935
948
|
if (/^\d+/.test(key)) {
|
|
936
949
|
return false;
|
|
@@ -939,13 +952,13 @@ function filterLeaks (ok, globals) {
|
|
|
939
952
|
// in firefox
|
|
940
953
|
// if runner runs in an iframe, this iframe's window.getInterface method
|
|
941
954
|
// not init at first it is assigned in some seconds
|
|
942
|
-
if (global.navigator &&
|
|
955
|
+
if (global.navigator && /^getInterface/.test(key)) {
|
|
943
956
|
return false;
|
|
944
957
|
}
|
|
945
958
|
|
|
946
959
|
// an iframe could be approached by window[iframeIndex]
|
|
947
960
|
// in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
|
|
948
|
-
if (global.navigator &&
|
|
961
|
+
if (global.navigator && /^\d+/.test(key)) {
|
|
949
962
|
return false;
|
|
950
963
|
}
|
|
951
964
|
|
|
@@ -954,7 +967,7 @@ function filterLeaks (ok, globals) {
|
|
|
954
967
|
return false;
|
|
955
968
|
}
|
|
956
969
|
|
|
957
|
-
var matched = ok.filter(function
|
|
970
|
+
var matched = ok.filter(function(ok) {
|
|
958
971
|
if (~ok.indexOf('*')) {
|
|
959
972
|
return key.indexOf(ok.split('*')[0]) === 0;
|
|
960
973
|
}
|
|
@@ -964,25 +977,60 @@ function filterLeaks (ok, globals) {
|
|
|
964
977
|
});
|
|
965
978
|
}
|
|
966
979
|
|
|
980
|
+
/**
|
|
981
|
+
* Check if argument is an instance of Error object or a duck-typed equivalent.
|
|
982
|
+
*
|
|
983
|
+
* @private
|
|
984
|
+
* @param {Object} err - object to check
|
|
985
|
+
* @param {string} err.message - error message
|
|
986
|
+
* @returns {boolean}
|
|
987
|
+
*/
|
|
988
|
+
function isError(err) {
|
|
989
|
+
return err instanceof Error || (err && typeof err.message === 'string');
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/**
|
|
993
|
+
*
|
|
994
|
+
* Converts thrown non-extensible type into proper Error.
|
|
995
|
+
*
|
|
996
|
+
* @private
|
|
997
|
+
* @param {*} thrown - Non-extensible type thrown by code
|
|
998
|
+
* @return {Error}
|
|
999
|
+
*/
|
|
1000
|
+
function thrown2Error(err) {
|
|
1001
|
+
return new Error(
|
|
1002
|
+
'the ' + type(err) + ' ' + stringify(err) + ' was thrown, throw an Error :)'
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
967
1006
|
/**
|
|
968
1007
|
* Array of globals dependent on the environment.
|
|
969
1008
|
*
|
|
970
1009
|
* @return {Array}
|
|
971
|
-
* @
|
|
1010
|
+
* @deprecated
|
|
1011
|
+
* @todo remove; long since unsupported
|
|
1012
|
+
* @private
|
|
972
1013
|
*/
|
|
973
|
-
function extraGlobals
|
|
1014
|
+
function extraGlobals() {
|
|
974
1015
|
if (typeof process === 'object' && typeof process.version === 'string') {
|
|
975
1016
|
var parts = process.version.split('.');
|
|
976
|
-
var nodeVersion = parts.reduce(function
|
|
977
|
-
return a << 8 | v;
|
|
1017
|
+
var nodeVersion = parts.reduce(function(a, v) {
|
|
1018
|
+
return (a << 8) | v;
|
|
978
1019
|
});
|
|
979
1020
|
|
|
980
1021
|
// 'errno' was renamed to process._errno in v0.9.11.
|
|
981
|
-
|
|
982
|
-
if (nodeVersion < 0x00090B) {
|
|
1022
|
+
if (nodeVersion < 0x00090b) {
|
|
983
1023
|
return ['errno'];
|
|
984
1024
|
}
|
|
985
1025
|
}
|
|
986
1026
|
|
|
987
1027
|
return [];
|
|
988
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
|
+
*/
|