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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provides a factory function for a {@link StatsCollector} object.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var constants = require('./runner').constants;
|
|
9
|
+
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
|
|
10
|
+
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
|
|
11
|
+
var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
|
|
12
|
+
var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
|
|
13
|
+
var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
|
|
14
|
+
var EVENT_RUN_END = constants.EVENT_RUN_END;
|
|
15
|
+
var EVENT_TEST_END = constants.EVENT_TEST_END;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Test statistics collector.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
* @typedef {Object} StatsCollector
|
|
22
|
+
* @property {number} suites - integer count of suites run.
|
|
23
|
+
* @property {number} tests - integer count of tests run.
|
|
24
|
+
* @property {number} passes - integer count of passing tests.
|
|
25
|
+
* @property {number} pending - integer count of pending tests.
|
|
26
|
+
* @property {number} failures - integer count of failed tests.
|
|
27
|
+
* @property {Date} start - time when testing began.
|
|
28
|
+
* @property {Date} end - time when testing concluded.
|
|
29
|
+
* @property {number} duration - number of msecs that testing took.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
var Date = global.Date;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Provides stats such as test duration, number of tests passed / failed etc., by listening for events emitted by `runner`.
|
|
36
|
+
*
|
|
37
|
+
* @private
|
|
38
|
+
* @param {Runner} runner - Runner instance
|
|
39
|
+
* @throws {TypeError} If falsy `runner`
|
|
40
|
+
*/
|
|
41
|
+
function createStatsCollector(runner) {
|
|
42
|
+
/**
|
|
43
|
+
* @type StatsCollector
|
|
44
|
+
*/
|
|
45
|
+
var stats = {
|
|
46
|
+
suites: 0,
|
|
47
|
+
tests: 0,
|
|
48
|
+
passes: 0,
|
|
49
|
+
pending: 0,
|
|
50
|
+
failures: 0
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (!runner) {
|
|
54
|
+
throw new TypeError('Missing runner argument');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
runner.stats = stats;
|
|
58
|
+
|
|
59
|
+
runner.once(EVENT_RUN_BEGIN, function() {
|
|
60
|
+
stats.start = new Date();
|
|
61
|
+
});
|
|
62
|
+
runner.on(EVENT_SUITE_BEGIN, function(suite) {
|
|
63
|
+
suite.root || stats.suites++;
|
|
64
|
+
});
|
|
65
|
+
runner.on(EVENT_TEST_PASS, function() {
|
|
66
|
+
stats.passes++;
|
|
67
|
+
});
|
|
68
|
+
runner.on(EVENT_TEST_FAIL, function() {
|
|
69
|
+
stats.failures++;
|
|
70
|
+
});
|
|
71
|
+
runner.on(EVENT_TEST_PENDING, function() {
|
|
72
|
+
stats.pending++;
|
|
73
|
+
});
|
|
74
|
+
runner.on(EVENT_TEST_END, function() {
|
|
75
|
+
stats.tests++;
|
|
76
|
+
});
|
|
77
|
+
runner.once(EVENT_RUN_END, function() {
|
|
78
|
+
stats.end = new Date();
|
|
79
|
+
stats.duration = stats.end - stats.start;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = createStatsCollector;
|
package/lib/suite.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
/**
|
|
3
|
-
* @module Suite
|
|
4
|
-
*/
|
|
5
2
|
|
|
6
3
|
/**
|
|
7
4
|
* Module dependencies.
|
|
@@ -11,7 +8,9 @@ var Hook = require('./hook');
|
|
|
11
8
|
var utils = require('./utils');
|
|
12
9
|
var inherits = utils.inherits;
|
|
13
10
|
var debug = require('debug')('mocha:suite');
|
|
14
|
-
var milliseconds = require('
|
|
11
|
+
var milliseconds = require('ms');
|
|
12
|
+
var errors = require('./errors');
|
|
13
|
+
var createInvalidArgumentTypeError = errors.createInvalidArgumentTypeError;
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* Expose `Suite`.
|
|
@@ -20,18 +19,14 @@ var milliseconds = require('./ms');
|
|
|
20
19
|
exports = module.exports = Suite;
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
* Create a new `Suite` with the given `title` and parent `Suite`.
|
|
24
|
-
* with the same title is already present, that suite is returned to provide
|
|
25
|
-
* nicer reporter and more flexible meta-testing.
|
|
22
|
+
* Create a new `Suite` with the given `title` and parent `Suite`.
|
|
26
23
|
*
|
|
27
|
-
* @memberof Mocha
|
|
28
24
|
* @public
|
|
29
|
-
* @
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {string} title
|
|
25
|
+
* @param {Suite} parent - Parent suite (required!)
|
|
26
|
+
* @param {string} title - Title
|
|
32
27
|
* @return {Suite}
|
|
33
28
|
*/
|
|
34
|
-
|
|
29
|
+
Suite.create = function(parent, title) {
|
|
35
30
|
var suite = new Suite(title, parent.ctx);
|
|
36
31
|
suite.parent = parent;
|
|
37
32
|
title = suite.fullTitle();
|
|
@@ -40,20 +35,28 @@ exports.create = function (parent, title) {
|
|
|
40
35
|
};
|
|
41
36
|
|
|
42
37
|
/**
|
|
43
|
-
*
|
|
38
|
+
* Constructs a new `Suite` instance with the given `title`, `ctx`, and `isRoot`.
|
|
44
39
|
*
|
|
45
|
-
* @memberof Mocha
|
|
46
40
|
* @public
|
|
47
41
|
* @class
|
|
48
|
-
* @
|
|
49
|
-
* @
|
|
42
|
+
* @extends EventEmitter
|
|
43
|
+
* @see {@link https://nodejs.org/api/events.html#events_class_eventemitter|EventEmitter}
|
|
44
|
+
* @param {string} title - Suite title.
|
|
45
|
+
* @param {Context} parentContext - Parent context instance.
|
|
46
|
+
* @param {boolean} [isRoot=false] - Whether this is the root suite.
|
|
50
47
|
*/
|
|
51
|
-
function Suite
|
|
48
|
+
function Suite(title, parentContext, isRoot) {
|
|
52
49
|
if (!utils.isString(title)) {
|
|
53
|
-
throw
|
|
50
|
+
throw createInvalidArgumentTypeError(
|
|
51
|
+
'Suite argument "title" must be a string. Received type "' +
|
|
52
|
+
typeof title +
|
|
53
|
+
'"',
|
|
54
|
+
'title',
|
|
55
|
+
'string'
|
|
56
|
+
);
|
|
54
57
|
}
|
|
55
58
|
this.title = title;
|
|
56
|
-
function Context
|
|
59
|
+
function Context() {}
|
|
57
60
|
Context.prototype = parentContext;
|
|
58
61
|
this.ctx = new Context();
|
|
59
62
|
this.suites = [];
|
|
@@ -63,7 +66,7 @@ function Suite (title, parentContext) {
|
|
|
63
66
|
this._beforeAll = [];
|
|
64
67
|
this._afterEach = [];
|
|
65
68
|
this._afterAll = [];
|
|
66
|
-
this.root =
|
|
69
|
+
this.root = isRoot === true;
|
|
67
70
|
this._timeout = 2000;
|
|
68
71
|
this._enableTimeouts = true;
|
|
69
72
|
this._slow = 75;
|
|
@@ -72,6 +75,16 @@ function Suite (title, parentContext) {
|
|
|
72
75
|
this._onlyTests = [];
|
|
73
76
|
this._onlySuites = [];
|
|
74
77
|
this.delayed = false;
|
|
78
|
+
|
|
79
|
+
this.on('newListener', function(event) {
|
|
80
|
+
if (deprecatedEvents[event]) {
|
|
81
|
+
utils.deprecate(
|
|
82
|
+
'Event "' +
|
|
83
|
+
event +
|
|
84
|
+
'" is deprecated. Please let the Mocha team know about your use case: https://git.io/v6Lwm'
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
/**
|
|
@@ -82,10 +95,10 @@ inherits(Suite, EventEmitter);
|
|
|
82
95
|
/**
|
|
83
96
|
* Return a clone of this `Suite`.
|
|
84
97
|
*
|
|
85
|
-
* @
|
|
98
|
+
* @private
|
|
86
99
|
* @return {Suite}
|
|
87
100
|
*/
|
|
88
|
-
Suite.prototype.clone = function
|
|
101
|
+
Suite.prototype.clone = function() {
|
|
89
102
|
var suite = new Suite(this.title);
|
|
90
103
|
debug('clone');
|
|
91
104
|
suite.ctx = this.ctx;
|
|
@@ -100,11 +113,11 @@ Suite.prototype.clone = function () {
|
|
|
100
113
|
/**
|
|
101
114
|
* Set or get timeout `ms` or short-hand such as "2s".
|
|
102
115
|
*
|
|
103
|
-
* @
|
|
116
|
+
* @private
|
|
104
117
|
* @param {number|string} ms
|
|
105
118
|
* @return {Suite|number} for chaining
|
|
106
119
|
*/
|
|
107
|
-
Suite.prototype.timeout = function
|
|
120
|
+
Suite.prototype.timeout = function(ms) {
|
|
108
121
|
if (!arguments.length) {
|
|
109
122
|
return this._timeout;
|
|
110
123
|
}
|
|
@@ -122,11 +135,11 @@ Suite.prototype.timeout = function (ms) {
|
|
|
122
135
|
/**
|
|
123
136
|
* Set or get number of times to retry a failed test.
|
|
124
137
|
*
|
|
125
|
-
* @
|
|
138
|
+
* @private
|
|
126
139
|
* @param {number|string} n
|
|
127
140
|
* @return {Suite|number} for chaining
|
|
128
141
|
*/
|
|
129
|
-
Suite.prototype.retries = function
|
|
142
|
+
Suite.prototype.retries = function(n) {
|
|
130
143
|
if (!arguments.length) {
|
|
131
144
|
return this._retries;
|
|
132
145
|
}
|
|
@@ -136,13 +149,13 @@ Suite.prototype.retries = function (n) {
|
|
|
136
149
|
};
|
|
137
150
|
|
|
138
151
|
/**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
Suite.prototype.enableTimeouts = function
|
|
152
|
+
* Set or get timeout to `enabled`.
|
|
153
|
+
*
|
|
154
|
+
* @private
|
|
155
|
+
* @param {boolean} enabled
|
|
156
|
+
* @return {Suite|boolean} self or enabled
|
|
157
|
+
*/
|
|
158
|
+
Suite.prototype.enableTimeouts = function(enabled) {
|
|
146
159
|
if (!arguments.length) {
|
|
147
160
|
return this._enableTimeouts;
|
|
148
161
|
}
|
|
@@ -154,11 +167,11 @@ Suite.prototype.enableTimeouts = function (enabled) {
|
|
|
154
167
|
/**
|
|
155
168
|
* Set or get slow `ms` or short-hand such as "2s".
|
|
156
169
|
*
|
|
157
|
-
* @
|
|
170
|
+
* @private
|
|
158
171
|
* @param {number|string} ms
|
|
159
172
|
* @return {Suite|number} for chaining
|
|
160
173
|
*/
|
|
161
|
-
Suite.prototype.slow = function
|
|
174
|
+
Suite.prototype.slow = function(ms) {
|
|
162
175
|
if (!arguments.length) {
|
|
163
176
|
return this._slow;
|
|
164
177
|
}
|
|
@@ -173,11 +186,11 @@ Suite.prototype.slow = function (ms) {
|
|
|
173
186
|
/**
|
|
174
187
|
* Set or get whether to bail after first error.
|
|
175
188
|
*
|
|
176
|
-
* @
|
|
189
|
+
* @private
|
|
177
190
|
* @param {boolean} bail
|
|
178
191
|
* @return {Suite|number} for chaining
|
|
179
192
|
*/
|
|
180
|
-
Suite.prototype.bail = function
|
|
193
|
+
Suite.prototype.bail = function(bail) {
|
|
181
194
|
if (!arguments.length) {
|
|
182
195
|
return this._bail;
|
|
183
196
|
}
|
|
@@ -189,9 +202,9 @@ Suite.prototype.bail = function (bail) {
|
|
|
189
202
|
/**
|
|
190
203
|
* Check if this suite or its parent suite is marked as pending.
|
|
191
204
|
*
|
|
192
|
-
* @
|
|
205
|
+
* @private
|
|
193
206
|
*/
|
|
194
|
-
Suite.prototype.isPending = function
|
|
207
|
+
Suite.prototype.isPending = function() {
|
|
195
208
|
return this.pending || (this.parent && this.parent.isPending());
|
|
196
209
|
};
|
|
197
210
|
|
|
@@ -202,7 +215,7 @@ Suite.prototype.isPending = function () {
|
|
|
202
215
|
* @param {Function} fn - Hook callback
|
|
203
216
|
* @returns {Hook} A new hook
|
|
204
217
|
*/
|
|
205
|
-
Suite.prototype._createHook = function
|
|
218
|
+
Suite.prototype._createHook = function(title, fn) {
|
|
206
219
|
var hook = new Hook(title, fn);
|
|
207
220
|
hook.parent = this;
|
|
208
221
|
hook.timeout(this.timeout());
|
|
@@ -217,12 +230,12 @@ Suite.prototype._createHook = function (title, fn) {
|
|
|
217
230
|
/**
|
|
218
231
|
* Run `fn(test[, done])` before running tests.
|
|
219
232
|
*
|
|
220
|
-
* @
|
|
233
|
+
* @private
|
|
221
234
|
* @param {string} title
|
|
222
235
|
* @param {Function} fn
|
|
223
236
|
* @return {Suite} for chaining
|
|
224
237
|
*/
|
|
225
|
-
Suite.prototype.beforeAll = function
|
|
238
|
+
Suite.prototype.beforeAll = function(title, fn) {
|
|
226
239
|
if (this.isPending()) {
|
|
227
240
|
return this;
|
|
228
241
|
}
|
|
@@ -234,19 +247,19 @@ Suite.prototype.beforeAll = function (title, fn) {
|
|
|
234
247
|
|
|
235
248
|
var hook = this._createHook(title, fn);
|
|
236
249
|
this._beforeAll.push(hook);
|
|
237
|
-
this.emit(
|
|
250
|
+
this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_ALL, hook);
|
|
238
251
|
return this;
|
|
239
252
|
};
|
|
240
253
|
|
|
241
254
|
/**
|
|
242
255
|
* Run `fn(test[, done])` after running tests.
|
|
243
256
|
*
|
|
244
|
-
* @
|
|
257
|
+
* @private
|
|
245
258
|
* @param {string} title
|
|
246
259
|
* @param {Function} fn
|
|
247
260
|
* @return {Suite} for chaining
|
|
248
261
|
*/
|
|
249
|
-
Suite.prototype.afterAll = function
|
|
262
|
+
Suite.prototype.afterAll = function(title, fn) {
|
|
250
263
|
if (this.isPending()) {
|
|
251
264
|
return this;
|
|
252
265
|
}
|
|
@@ -258,19 +271,19 @@ Suite.prototype.afterAll = function (title, fn) {
|
|
|
258
271
|
|
|
259
272
|
var hook = this._createHook(title, fn);
|
|
260
273
|
this._afterAll.push(hook);
|
|
261
|
-
this.emit(
|
|
274
|
+
this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_ALL, hook);
|
|
262
275
|
return this;
|
|
263
276
|
};
|
|
264
277
|
|
|
265
278
|
/**
|
|
266
279
|
* Run `fn(test[, done])` before each test case.
|
|
267
280
|
*
|
|
268
|
-
* @
|
|
281
|
+
* @private
|
|
269
282
|
* @param {string} title
|
|
270
283
|
* @param {Function} fn
|
|
271
284
|
* @return {Suite} for chaining
|
|
272
285
|
*/
|
|
273
|
-
Suite.prototype.beforeEach = function
|
|
286
|
+
Suite.prototype.beforeEach = function(title, fn) {
|
|
274
287
|
if (this.isPending()) {
|
|
275
288
|
return this;
|
|
276
289
|
}
|
|
@@ -282,19 +295,19 @@ Suite.prototype.beforeEach = function (title, fn) {
|
|
|
282
295
|
|
|
283
296
|
var hook = this._createHook(title, fn);
|
|
284
297
|
this._beforeEach.push(hook);
|
|
285
|
-
this.emit(
|
|
298
|
+
this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_EACH, hook);
|
|
286
299
|
return this;
|
|
287
300
|
};
|
|
288
301
|
|
|
289
302
|
/**
|
|
290
303
|
* Run `fn(test[, done])` after each test case.
|
|
291
304
|
*
|
|
292
|
-
* @
|
|
305
|
+
* @private
|
|
293
306
|
* @param {string} title
|
|
294
307
|
* @param {Function} fn
|
|
295
308
|
* @return {Suite} for chaining
|
|
296
309
|
*/
|
|
297
|
-
Suite.prototype.afterEach = function
|
|
310
|
+
Suite.prototype.afterEach = function(title, fn) {
|
|
298
311
|
if (this.isPending()) {
|
|
299
312
|
return this;
|
|
300
313
|
}
|
|
@@ -306,37 +319,38 @@ Suite.prototype.afterEach = function (title, fn) {
|
|
|
306
319
|
|
|
307
320
|
var hook = this._createHook(title, fn);
|
|
308
321
|
this._afterEach.push(hook);
|
|
309
|
-
this.emit(
|
|
322
|
+
this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_EACH, hook);
|
|
310
323
|
return this;
|
|
311
324
|
};
|
|
312
325
|
|
|
313
326
|
/**
|
|
314
327
|
* Add a test `suite`.
|
|
315
328
|
*
|
|
316
|
-
* @
|
|
329
|
+
* @private
|
|
317
330
|
* @param {Suite} suite
|
|
318
331
|
* @return {Suite} for chaining
|
|
319
332
|
*/
|
|
320
|
-
Suite.prototype.addSuite = function
|
|
333
|
+
Suite.prototype.addSuite = function(suite) {
|
|
321
334
|
suite.parent = this;
|
|
335
|
+
suite.root = false;
|
|
322
336
|
suite.timeout(this.timeout());
|
|
323
337
|
suite.retries(this.retries());
|
|
324
338
|
suite.enableTimeouts(this.enableTimeouts());
|
|
325
339
|
suite.slow(this.slow());
|
|
326
340
|
suite.bail(this.bail());
|
|
327
341
|
this.suites.push(suite);
|
|
328
|
-
this.emit(
|
|
342
|
+
this.emit(constants.EVENT_SUITE_ADD_SUITE, suite);
|
|
329
343
|
return this;
|
|
330
344
|
};
|
|
331
345
|
|
|
332
346
|
/**
|
|
333
347
|
* Add a `test` to this suite.
|
|
334
348
|
*
|
|
335
|
-
* @
|
|
349
|
+
* @private
|
|
336
350
|
* @param {Test} test
|
|
337
351
|
* @return {Suite} for chaining
|
|
338
352
|
*/
|
|
339
|
-
Suite.prototype.addTest = function
|
|
353
|
+
Suite.prototype.addTest = function(test) {
|
|
340
354
|
test.parent = this;
|
|
341
355
|
test.timeout(this.timeout());
|
|
342
356
|
test.retries(this.retries());
|
|
@@ -344,7 +358,7 @@ Suite.prototype.addTest = function (test) {
|
|
|
344
358
|
test.slow(this.slow());
|
|
345
359
|
test.ctx = this.ctx;
|
|
346
360
|
this.tests.push(test);
|
|
347
|
-
this.emit(
|
|
361
|
+
this.emit(constants.EVENT_SUITE_ADD_TEST, test);
|
|
348
362
|
return this;
|
|
349
363
|
};
|
|
350
364
|
|
|
@@ -352,12 +366,11 @@ Suite.prototype.addTest = function (test) {
|
|
|
352
366
|
* Return the full title generated by recursively concatenating the parent's
|
|
353
367
|
* full title.
|
|
354
368
|
*
|
|
355
|
-
* @memberof
|
|
369
|
+
* @memberof Suite
|
|
356
370
|
* @public
|
|
357
|
-
* @api public
|
|
358
371
|
* @return {string}
|
|
359
372
|
*/
|
|
360
|
-
Suite.prototype.fullTitle = function
|
|
373
|
+
Suite.prototype.fullTitle = function() {
|
|
361
374
|
return this.titlePath().join(' ');
|
|
362
375
|
};
|
|
363
376
|
|
|
@@ -365,12 +378,11 @@ Suite.prototype.fullTitle = function () {
|
|
|
365
378
|
* Return the title path generated by recursively concatenating the parent's
|
|
366
379
|
* title path.
|
|
367
380
|
*
|
|
368
|
-
* @memberof
|
|
381
|
+
* @memberof Suite
|
|
369
382
|
* @public
|
|
370
|
-
* @api public
|
|
371
383
|
* @return {string}
|
|
372
384
|
*/
|
|
373
|
-
Suite.prototype.titlePath = function
|
|
385
|
+
Suite.prototype.titlePath = function() {
|
|
374
386
|
var result = [];
|
|
375
387
|
if (this.parent) {
|
|
376
388
|
result = result.concat(this.parent.titlePath());
|
|
@@ -384,28 +396,29 @@ Suite.prototype.titlePath = function () {
|
|
|
384
396
|
/**
|
|
385
397
|
* Return the total number of tests.
|
|
386
398
|
*
|
|
387
|
-
* @memberof
|
|
399
|
+
* @memberof Suite
|
|
388
400
|
* @public
|
|
389
|
-
* @api public
|
|
390
401
|
* @return {number}
|
|
391
402
|
*/
|
|
392
|
-
Suite.prototype.total = function
|
|
393
|
-
return
|
|
394
|
-
|
|
395
|
-
|
|
403
|
+
Suite.prototype.total = function() {
|
|
404
|
+
return (
|
|
405
|
+
this.suites.reduce(function(sum, suite) {
|
|
406
|
+
return sum + suite.total();
|
|
407
|
+
}, 0) + this.tests.length
|
|
408
|
+
);
|
|
396
409
|
};
|
|
397
410
|
|
|
398
411
|
/**
|
|
399
412
|
* Iterates through each suite recursively to find all tests. Applies a
|
|
400
413
|
* function in the format `fn(test)`.
|
|
401
414
|
*
|
|
402
|
-
* @
|
|
415
|
+
* @private
|
|
403
416
|
* @param {Function} fn
|
|
404
417
|
* @return {Suite}
|
|
405
418
|
*/
|
|
406
|
-
Suite.prototype.eachTest = function
|
|
419
|
+
Suite.prototype.eachTest = function(fn) {
|
|
407
420
|
this.tests.forEach(fn);
|
|
408
|
-
this.suites.forEach(function
|
|
421
|
+
this.suites.forEach(function(suite) {
|
|
409
422
|
suite.eachTest(fn);
|
|
410
423
|
});
|
|
411
424
|
return this;
|
|
@@ -413,9 +426,215 @@ Suite.prototype.eachTest = function (fn) {
|
|
|
413
426
|
|
|
414
427
|
/**
|
|
415
428
|
* This will run the root suite if we happen to be running in delayed mode.
|
|
429
|
+
* @private
|
|
416
430
|
*/
|
|
417
|
-
Suite.prototype.run = function run
|
|
431
|
+
Suite.prototype.run = function run() {
|
|
418
432
|
if (this.root) {
|
|
419
|
-
this.emit(
|
|
433
|
+
this.emit(constants.EVENT_ROOT_SUITE_RUN);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Determines whether a suite has an `only` test or suite as a descendant.
|
|
439
|
+
*
|
|
440
|
+
* @private
|
|
441
|
+
* @returns {Boolean}
|
|
442
|
+
*/
|
|
443
|
+
Suite.prototype.hasOnly = function hasOnly() {
|
|
444
|
+
return (
|
|
445
|
+
this._onlyTests.length > 0 ||
|
|
446
|
+
this._onlySuites.length > 0 ||
|
|
447
|
+
this.suites.some(function(suite) {
|
|
448
|
+
return suite.hasOnly();
|
|
449
|
+
})
|
|
450
|
+
);
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Filter suites based on `isOnly` logic.
|
|
455
|
+
*
|
|
456
|
+
* @private
|
|
457
|
+
* @returns {Boolean}
|
|
458
|
+
*/
|
|
459
|
+
Suite.prototype.filterOnly = function filterOnly() {
|
|
460
|
+
if (this._onlyTests.length) {
|
|
461
|
+
// If the suite contains `only` tests, run those and ignore any nested suites.
|
|
462
|
+
this.tests = this._onlyTests;
|
|
463
|
+
this.suites = [];
|
|
464
|
+
} else {
|
|
465
|
+
// Otherwise, do not run any of the tests in this suite.
|
|
466
|
+
this.tests = [];
|
|
467
|
+
this._onlySuites.forEach(function(onlySuite) {
|
|
468
|
+
// If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
|
|
469
|
+
// Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
|
|
470
|
+
if (onlySuite.hasOnly()) {
|
|
471
|
+
onlySuite.filterOnly();
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
// Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
|
|
475
|
+
var onlySuites = this._onlySuites;
|
|
476
|
+
this.suites = this.suites.filter(function(childSuite) {
|
|
477
|
+
return onlySuites.indexOf(childSuite) !== -1 || childSuite.filterOnly();
|
|
478
|
+
});
|
|
420
479
|
}
|
|
480
|
+
// Keep the suite only if there is something to run
|
|
481
|
+
return this.tests.length > 0 || this.suites.length > 0;
|
|
421
482
|
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Adds a suite to the list of subsuites marked `only`.
|
|
486
|
+
*
|
|
487
|
+
* @private
|
|
488
|
+
* @param {Suite} suite
|
|
489
|
+
*/
|
|
490
|
+
Suite.prototype.appendOnlySuite = function(suite) {
|
|
491
|
+
this._onlySuites.push(suite);
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Adds a test to the list of tests marked `only`.
|
|
496
|
+
*
|
|
497
|
+
* @private
|
|
498
|
+
* @param {Test} test
|
|
499
|
+
*/
|
|
500
|
+
Suite.prototype.appendOnlyTest = function(test) {
|
|
501
|
+
this._onlyTests.push(test);
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Returns the array of hooks by hook name; see `HOOK_TYPE_*` constants.
|
|
506
|
+
* @private
|
|
507
|
+
*/
|
|
508
|
+
Suite.prototype.getHooks = function getHooks(name) {
|
|
509
|
+
return this['_' + name];
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Cleans up the references to all the deferred functions
|
|
514
|
+
* (before/after/beforeEach/afterEach) and tests of a Suite.
|
|
515
|
+
* These must be deleted otherwise a memory leak can happen,
|
|
516
|
+
* as those functions may reference variables from closures,
|
|
517
|
+
* thus those variables can never be garbage collected as long
|
|
518
|
+
* as the deferred functions exist.
|
|
519
|
+
*
|
|
520
|
+
* @private
|
|
521
|
+
*/
|
|
522
|
+
Suite.prototype.cleanReferences = function cleanReferences() {
|
|
523
|
+
function cleanArrReferences(arr) {
|
|
524
|
+
for (var i = 0; i < arr.length; i++) {
|
|
525
|
+
delete arr[i].fn;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (Array.isArray(this._beforeAll)) {
|
|
530
|
+
cleanArrReferences(this._beforeAll);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (Array.isArray(this._beforeEach)) {
|
|
534
|
+
cleanArrReferences(this._beforeEach);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (Array.isArray(this._afterAll)) {
|
|
538
|
+
cleanArrReferences(this._afterAll);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (Array.isArray(this._afterEach)) {
|
|
542
|
+
cleanArrReferences(this._afterEach);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
for (var i = 0; i < this.tests.length; i++) {
|
|
546
|
+
delete this.tests[i].fn;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
var constants = utils.defineConstants(
|
|
551
|
+
/**
|
|
552
|
+
* {@link Suite}-related constants.
|
|
553
|
+
* @public
|
|
554
|
+
* @memberof Suite
|
|
555
|
+
* @alias constants
|
|
556
|
+
* @readonly
|
|
557
|
+
* @static
|
|
558
|
+
* @enum {string}
|
|
559
|
+
*/
|
|
560
|
+
{
|
|
561
|
+
/**
|
|
562
|
+
* Event emitted after a test file has been loaded Not emitted in browser.
|
|
563
|
+
*/
|
|
564
|
+
EVENT_FILE_POST_REQUIRE: 'post-require',
|
|
565
|
+
/**
|
|
566
|
+
* Event emitted before a test file has been loaded. In browser, this is emitted once an interface has been selected.
|
|
567
|
+
*/
|
|
568
|
+
EVENT_FILE_PRE_REQUIRE: 'pre-require',
|
|
569
|
+
/**
|
|
570
|
+
* Event emitted immediately after a test file has been loaded. Not emitted in browser.
|
|
571
|
+
*/
|
|
572
|
+
EVENT_FILE_REQUIRE: 'require',
|
|
573
|
+
/**
|
|
574
|
+
* Event emitted when `global.run()` is called (use with `delay` option)
|
|
575
|
+
*/
|
|
576
|
+
EVENT_ROOT_SUITE_RUN: 'run',
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Namespace for collection of a `Suite`'s "after all" hooks
|
|
580
|
+
*/
|
|
581
|
+
HOOK_TYPE_AFTER_ALL: 'afterAll',
|
|
582
|
+
/**
|
|
583
|
+
* Namespace for collection of a `Suite`'s "after each" hooks
|
|
584
|
+
*/
|
|
585
|
+
HOOK_TYPE_AFTER_EACH: 'afterEach',
|
|
586
|
+
/**
|
|
587
|
+
* Namespace for collection of a `Suite`'s "before all" hooks
|
|
588
|
+
*/
|
|
589
|
+
HOOK_TYPE_BEFORE_ALL: 'beforeAll',
|
|
590
|
+
/**
|
|
591
|
+
* Namespace for collection of a `Suite`'s "before all" hooks
|
|
592
|
+
*/
|
|
593
|
+
HOOK_TYPE_BEFORE_EACH: 'beforeEach',
|
|
594
|
+
|
|
595
|
+
// the following events are all deprecated
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Emitted after an "after all" `Hook` has been added to a `Suite`. Deprecated
|
|
599
|
+
*/
|
|
600
|
+
EVENT_SUITE_ADD_HOOK_AFTER_ALL: 'afterAll',
|
|
601
|
+
/**
|
|
602
|
+
* Emitted after an "after each" `Hook` has been added to a `Suite` Deprecated
|
|
603
|
+
*/
|
|
604
|
+
EVENT_SUITE_ADD_HOOK_AFTER_EACH: 'afterEach',
|
|
605
|
+
/**
|
|
606
|
+
* Emitted after an "before all" `Hook` has been added to a `Suite` Deprecated
|
|
607
|
+
*/
|
|
608
|
+
EVENT_SUITE_ADD_HOOK_BEFORE_ALL: 'beforeAll',
|
|
609
|
+
/**
|
|
610
|
+
* Emitted after an "before each" `Hook` has been added to a `Suite` Deprecated
|
|
611
|
+
*/
|
|
612
|
+
EVENT_SUITE_ADD_HOOK_BEFORE_EACH: 'beforeEach',
|
|
613
|
+
/**
|
|
614
|
+
* Emitted after a child `Suite` has been added to a `Suite`. Deprecated
|
|
615
|
+
*/
|
|
616
|
+
EVENT_SUITE_ADD_SUITE: 'suite',
|
|
617
|
+
/**
|
|
618
|
+
* Emitted after a `Test` has been added to a `Suite`. Deprecated
|
|
619
|
+
*/
|
|
620
|
+
EVENT_SUITE_ADD_TEST: 'test'
|
|
621
|
+
}
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* @summary There are no known use cases for these events.
|
|
626
|
+
* @desc This is a `Set`-like object having all keys being the constant's string value and the value being `true`.
|
|
627
|
+
* @todo Remove eventually
|
|
628
|
+
* @type {Object<string,boolean>}
|
|
629
|
+
* @ignore
|
|
630
|
+
*/
|
|
631
|
+
var deprecatedEvents = Object.keys(constants)
|
|
632
|
+
.filter(function(constant) {
|
|
633
|
+
return constant.substring(0, 15) === 'EVENT_SUITE_ADD';
|
|
634
|
+
})
|
|
635
|
+
.reduce(function(acc, constant) {
|
|
636
|
+
acc[constants[constant]] = true;
|
|
637
|
+
return acc;
|
|
638
|
+
}, utils.createMap());
|
|
639
|
+
|
|
640
|
+
Suite.constants = constants;
|