mocha 7.1.2 → 7.2.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 +33 -2
- package/bin/mocha +7 -2
- package/browser-entry.js +11 -0
- package/lib/cli/cli.js +4 -1
- package/lib/cli/collect-files.js +2 -1
- package/lib/cli/config.js +6 -5
- package/lib/cli/options.js +3 -3
- package/lib/cli/run-helpers.js +85 -26
- package/lib/cli/run.js +15 -2
- package/lib/errors.js +179 -9
- package/lib/hook.js +8 -0
- package/lib/interfaces/common.js +6 -3
- package/lib/mocha.js +171 -12
- package/lib/reporters/doc.js +6 -0
- package/lib/reporters/json-stream.js +1 -0
- package/lib/reporters/json.js +1 -0
- package/lib/reporters/landing.js +8 -0
- package/lib/runnable.js +21 -17
- package/lib/runner.js +161 -54
- package/lib/suite.js +29 -3
- package/lib/test.js +20 -2
- package/lib/utils.js +14 -3
- package/mocha.js +639 -106
- package/package.json +41 -32
package/lib/runner.js
CHANGED
|
@@ -26,6 +26,7 @@ var type = utils.type;
|
|
|
26
26
|
var errors = require('./errors');
|
|
27
27
|
var createInvalidExceptionError = errors.createInvalidExceptionError;
|
|
28
28
|
var createUnsupportedError = errors.createUnsupportedError;
|
|
29
|
+
var createFatalError = errors.createFatalError;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Non-enumerable globals.
|
|
@@ -108,7 +109,19 @@ var constants = utils.defineConstants(
|
|
|
108
109
|
/**
|
|
109
110
|
* Emitted when {@link Test} execution has failed, but will retry
|
|
110
111
|
*/
|
|
111
|
-
EVENT_TEST_RETRY: 'retry'
|
|
112
|
+
EVENT_TEST_RETRY: 'retry',
|
|
113
|
+
/**
|
|
114
|
+
* Initial state of Runner
|
|
115
|
+
*/
|
|
116
|
+
STATE_IDLE: 'idle',
|
|
117
|
+
/**
|
|
118
|
+
* State set to this value when the Runner has started running
|
|
119
|
+
*/
|
|
120
|
+
STATE_RUNNING: 'running',
|
|
121
|
+
/**
|
|
122
|
+
* State set to this value when the Runner has stopped
|
|
123
|
+
*/
|
|
124
|
+
STATE_STOPPED: 'stopped'
|
|
112
125
|
}
|
|
113
126
|
);
|
|
114
127
|
|
|
@@ -120,19 +133,30 @@ module.exports = Runner;
|
|
|
120
133
|
* @extends external:EventEmitter
|
|
121
134
|
* @public
|
|
122
135
|
* @class
|
|
123
|
-
* @param {Suite} suite Root suite
|
|
124
|
-
* @param {boolean} [
|
|
125
|
-
* until ready.
|
|
136
|
+
* @param {Suite} suite - Root suite
|
|
137
|
+
* @param {Object|boolean} [opts] - Options. If `boolean`, whether or not to delay execution of root suite until ready (for backwards compatibility).
|
|
138
|
+
* @param {boolean} [opts.delay] - Whether to delay execution of root suite until ready.
|
|
139
|
+
* @param {boolean} [opts.cleanReferencesAfterRun] - Whether to clean references to test fns and hooks when a suite is done.
|
|
126
140
|
*/
|
|
127
|
-
function Runner(suite,
|
|
141
|
+
function Runner(suite, opts) {
|
|
142
|
+
if (opts === undefined) {
|
|
143
|
+
opts = {};
|
|
144
|
+
}
|
|
145
|
+
if (typeof opts === 'boolean') {
|
|
146
|
+
this._delay = opts;
|
|
147
|
+
opts = {};
|
|
148
|
+
} else {
|
|
149
|
+
this._delay = opts.delay;
|
|
150
|
+
}
|
|
128
151
|
var self = this;
|
|
129
152
|
this._globals = [];
|
|
130
153
|
this._abort = false;
|
|
131
|
-
this._delay = delay;
|
|
132
154
|
this.suite = suite;
|
|
133
|
-
this.
|
|
155
|
+
this._opts = opts;
|
|
156
|
+
this.state = constants.STATE_IDLE;
|
|
134
157
|
this.total = suite.total();
|
|
135
158
|
this.failures = 0;
|
|
159
|
+
this._eventListeners = [];
|
|
136
160
|
this.on(constants.EVENT_TEST_END, function(test) {
|
|
137
161
|
if (test.type === 'test' && test.retriedTest() && test.parent) {
|
|
138
162
|
var idx =
|
|
@@ -147,6 +171,8 @@ function Runner(suite, delay) {
|
|
|
147
171
|
this._defaultGrep = /.*/;
|
|
148
172
|
this.grep(this._defaultGrep);
|
|
149
173
|
this.globals(this.globalProps());
|
|
174
|
+
|
|
175
|
+
this.uncaught = this._uncaught.bind(this);
|
|
150
176
|
}
|
|
151
177
|
|
|
152
178
|
/**
|
|
@@ -162,6 +188,56 @@ Runner.immediately = global.setImmediate || process.nextTick;
|
|
|
162
188
|
*/
|
|
163
189
|
inherits(Runner, EventEmitter);
|
|
164
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Replacement for `target.on(eventName, listener)` that does bookkeeping to remove them when this runner instance is disposed.
|
|
193
|
+
* @param {EventEmitter} target - The `EventEmitter`
|
|
194
|
+
* @param {string} eventName - The event name
|
|
195
|
+
* @param {string} fn - Listener function
|
|
196
|
+
*/
|
|
197
|
+
Runner.prototype._addEventListener = function(target, eventName, listener) {
|
|
198
|
+
target.on(eventName, listener);
|
|
199
|
+
this._eventListeners.push([target, eventName, listener]);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Replacement for `target.removeListener(eventName, listener)` that also updates the bookkeeping.
|
|
204
|
+
* @param {EventEmitter} target - The `EventEmitter`
|
|
205
|
+
* @param {string} eventName - The event anme
|
|
206
|
+
* @param {function} listener - Listener function
|
|
207
|
+
*/
|
|
208
|
+
Runner.prototype._removeEventListener = function(target, eventName, listener) {
|
|
209
|
+
var eventListenerIndex = -1;
|
|
210
|
+
for (var i = 0; i < this._eventListeners.length; i++) {
|
|
211
|
+
var eventListenerDescriptor = this._eventListeners[i];
|
|
212
|
+
if (
|
|
213
|
+
eventListenerDescriptor[0] === target &&
|
|
214
|
+
eventListenerDescriptor[1] === eventName &&
|
|
215
|
+
eventListenerDescriptor[2] === listener
|
|
216
|
+
) {
|
|
217
|
+
eventListenerIndex = i;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (eventListenerIndex !== -1) {
|
|
222
|
+
var removedListener = this._eventListeners.splice(eventListenerIndex, 1)[0];
|
|
223
|
+
removedListener[0].removeListener(removedListener[1], removedListener[2]);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Removes all event handlers set during a run on this instance.
|
|
229
|
+
* Remark: this does _not_ clean/dispose the tests or suites themselves.
|
|
230
|
+
*/
|
|
231
|
+
Runner.prototype.dispose = function() {
|
|
232
|
+
this.removeAllListeners();
|
|
233
|
+
this._eventListeners.forEach(function(eventListenerDescriptor) {
|
|
234
|
+
eventListenerDescriptor[0].removeListener(
|
|
235
|
+
eventListenerDescriptor[1],
|
|
236
|
+
eventListenerDescriptor[2]
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
165
241
|
/**
|
|
166
242
|
* Run tests with full titles matching `re`. Updates runner.total
|
|
167
243
|
* with number of tests matched.
|
|
@@ -173,7 +249,7 @@ inherits(Runner, EventEmitter);
|
|
|
173
249
|
* @return {Runner} Runner instance.
|
|
174
250
|
*/
|
|
175
251
|
Runner.prototype.grep = function(re, invert) {
|
|
176
|
-
debug('grep %s', re);
|
|
252
|
+
debug('grep(): setting to %s', re);
|
|
177
253
|
this._grep = re;
|
|
178
254
|
this._invert = invert;
|
|
179
255
|
this.total = this.grepTotal(this.suite);
|
|
@@ -238,7 +314,7 @@ Runner.prototype.globals = function(arr) {
|
|
|
238
314
|
if (!arguments.length) {
|
|
239
315
|
return this._globals;
|
|
240
316
|
}
|
|
241
|
-
debug('globals %
|
|
317
|
+
debug('globals(): setting to %O', arr);
|
|
242
318
|
this._globals = this._globals.concat(arr);
|
|
243
319
|
return this;
|
|
244
320
|
};
|
|
@@ -287,8 +363,18 @@ Runner.prototype.fail = function(test, err) {
|
|
|
287
363
|
if (test.isPending()) {
|
|
288
364
|
return;
|
|
289
365
|
}
|
|
366
|
+
if (this.state === constants.STATE_STOPPED) {
|
|
367
|
+
if (err.code === errors.constants.MULTIPLE_DONE) {
|
|
368
|
+
throw err;
|
|
369
|
+
}
|
|
370
|
+
throw createFatalError(
|
|
371
|
+
'Test failed after root suite execution completed!',
|
|
372
|
+
err
|
|
373
|
+
);
|
|
374
|
+
}
|
|
290
375
|
|
|
291
376
|
++this.failures;
|
|
377
|
+
debug('total number of failures: %d', this.failures);
|
|
292
378
|
test.state = STATE_FAILED;
|
|
293
379
|
|
|
294
380
|
if (!isError(err)) {
|
|
@@ -376,7 +462,7 @@ Runner.prototype.hook = function(name, fn) {
|
|
|
376
462
|
self.emit(constants.EVENT_HOOK_BEGIN, hook);
|
|
377
463
|
|
|
378
464
|
if (!hook.listeners('error').length) {
|
|
379
|
-
|
|
465
|
+
self._addEventListener(hook, 'error', function(err) {
|
|
380
466
|
self.failHook(hook, err);
|
|
381
467
|
});
|
|
382
468
|
}
|
|
@@ -519,18 +605,10 @@ Runner.prototype.runTest = function(fn) {
|
|
|
519
605
|
return;
|
|
520
606
|
}
|
|
521
607
|
|
|
522
|
-
var suite = this.parents().reverse()[0] || this.suite;
|
|
523
|
-
if (this.forbidOnly && suite.hasOnly()) {
|
|
524
|
-
fn(new Error('`.only` forbidden'));
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
608
|
if (this.asyncOnly) {
|
|
528
609
|
test.asyncOnly = true;
|
|
529
610
|
}
|
|
530
|
-
|
|
531
|
-
if (err instanceof Pending) {
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
611
|
+
this._addEventListener(test, 'error', function(err) {
|
|
534
612
|
self.fail(test, err);
|
|
535
613
|
});
|
|
536
614
|
if (this.allowUncaught) {
|
|
@@ -725,9 +803,10 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
725
803
|
var self = this;
|
|
726
804
|
var total = this.grepTotal(suite);
|
|
727
805
|
|
|
728
|
-
debug('
|
|
806
|
+
debug('runSuite(): running %s', suite.fullTitle());
|
|
729
807
|
|
|
730
808
|
if (!total || (self.failures && suite._bail)) {
|
|
809
|
+
debug('runSuite(): bailing');
|
|
731
810
|
return fn();
|
|
732
811
|
}
|
|
733
812
|
|
|
@@ -793,22 +872,49 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
793
872
|
/**
|
|
794
873
|
* Handle uncaught exceptions within runner.
|
|
795
874
|
*
|
|
796
|
-
*
|
|
875
|
+
* This function is bound to the instance as `Runner#uncaught` at instantiation
|
|
876
|
+
* time. It's intended to be listening on the `Process.uncaughtException` event.
|
|
877
|
+
* In order to not leak EE listeners, we need to ensure no more than a single
|
|
878
|
+
* `uncaughtException` listener exists per `Runner`. The only way to do
|
|
879
|
+
* this--because this function needs the context (and we don't have lambdas)--is
|
|
880
|
+
* to use `Function.prototype.bind`. We need strict equality to unregister and
|
|
881
|
+
* _only_ unregister the _one_ listener we set from the
|
|
882
|
+
* `Process.uncaughtException` event; would be poor form to just remove
|
|
883
|
+
* everything. See {@link Runner#run} for where the event listener is registered
|
|
884
|
+
* and unregistered.
|
|
885
|
+
* @param {Error} err - Some uncaught error
|
|
797
886
|
* @private
|
|
798
887
|
*/
|
|
799
|
-
Runner.prototype.
|
|
888
|
+
Runner.prototype._uncaught = function(err) {
|
|
889
|
+
// this is defensive to prevent future developers from mis-calling this function.
|
|
890
|
+
// it's more likely that it'd be called with the incorrect context--say, the global
|
|
891
|
+
// `process` object--than it would to be called with a context that is not a "subclass"
|
|
892
|
+
// of `Runner`.
|
|
893
|
+
if (!(this instanceof Runner)) {
|
|
894
|
+
throw createFatalError(
|
|
895
|
+
'Runner#uncaught() called with invalid context',
|
|
896
|
+
this
|
|
897
|
+
);
|
|
898
|
+
}
|
|
800
899
|
if (err instanceof Pending) {
|
|
900
|
+
debug('uncaught(): caught a Pending');
|
|
801
901
|
return;
|
|
802
902
|
}
|
|
803
903
|
// browser does not exit script when throwing in global.onerror()
|
|
804
904
|
if (this.allowUncaught && !process.browser) {
|
|
905
|
+
debug('uncaught(): bubbling exception due to --allow-uncaught');
|
|
906
|
+
throw err;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (this.state === constants.STATE_STOPPED) {
|
|
910
|
+
debug('uncaught(): throwing after run has completed!');
|
|
805
911
|
throw err;
|
|
806
912
|
}
|
|
807
913
|
|
|
808
914
|
if (err) {
|
|
809
|
-
debug('uncaught exception %O', err);
|
|
915
|
+
debug('uncaught(): got truthy exception %O', err);
|
|
810
916
|
} else {
|
|
811
|
-
debug('uncaught undefined/falsy exception');
|
|
917
|
+
debug('uncaught(): undefined/falsy exception');
|
|
812
918
|
err = createInvalidExceptionError(
|
|
813
919
|
'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
|
|
814
920
|
err
|
|
@@ -817,6 +923,7 @@ Runner.prototype.uncaught = function(err) {
|
|
|
817
923
|
|
|
818
924
|
if (!isError(err)) {
|
|
819
925
|
err = thrown2Error(err);
|
|
926
|
+
debug('uncaught(): converted "error" %o to Error', err);
|
|
820
927
|
}
|
|
821
928
|
err.uncaught = true;
|
|
822
929
|
|
|
@@ -824,12 +931,15 @@ Runner.prototype.uncaught = function(err) {
|
|
|
824
931
|
|
|
825
932
|
if (!runnable) {
|
|
826
933
|
runnable = new Runnable('Uncaught error outside test suite');
|
|
934
|
+
debug('uncaught(): no current Runnable; created a phony one');
|
|
827
935
|
runnable.parent = this.suite;
|
|
828
936
|
|
|
829
|
-
if (this.
|
|
937
|
+
if (this.state === constants.STATE_RUNNING) {
|
|
938
|
+
debug('uncaught(): failing gracefully');
|
|
830
939
|
this.fail(runnable, err);
|
|
831
940
|
} else {
|
|
832
941
|
// Can't recover from this failure
|
|
942
|
+
debug('uncaught(): test run has not yet started; unrecoverable');
|
|
833
943
|
this.emit(constants.EVENT_RUN_BEGIN);
|
|
834
944
|
this.fail(runnable, err);
|
|
835
945
|
this.emit(constants.EVENT_RUN_END);
|
|
@@ -841,9 +951,11 @@ Runner.prototype.uncaught = function(err) {
|
|
|
841
951
|
runnable.clearTimeout();
|
|
842
952
|
|
|
843
953
|
if (runnable.isFailed()) {
|
|
954
|
+
debug('uncaught(): Runnable has already failed');
|
|
844
955
|
// Ignore error if already failed
|
|
845
956
|
return;
|
|
846
957
|
} else if (runnable.isPending()) {
|
|
958
|
+
debug('uncaught(): pending Runnable wound up failing!');
|
|
847
959
|
// report 'pending test' retrospectively as failed
|
|
848
960
|
runnable.isPending = alwaysFalse;
|
|
849
961
|
this.fail(runnable, err);
|
|
@@ -854,25 +966,15 @@ Runner.prototype.uncaught = function(err) {
|
|
|
854
966
|
// we cannot recover gracefully if a Runnable has already passed
|
|
855
967
|
// then fails asynchronously
|
|
856
968
|
if (runnable.isPassed()) {
|
|
969
|
+
debug('uncaught(): Runnable has already passed; bailing gracefully');
|
|
857
970
|
this.fail(runnable, err);
|
|
858
971
|
this.abort();
|
|
859
972
|
} else {
|
|
860
|
-
debug(
|
|
973
|
+
debug('uncaught(): forcing Runnable to complete with Error');
|
|
861
974
|
return runnable.callback(err);
|
|
862
975
|
}
|
|
863
976
|
};
|
|
864
977
|
|
|
865
|
-
/**
|
|
866
|
-
* Handle uncaught exceptions after runner's end event.
|
|
867
|
-
*
|
|
868
|
-
* @param {Error} err
|
|
869
|
-
* @private
|
|
870
|
-
*/
|
|
871
|
-
Runner.prototype.uncaughtEnd = function uncaughtEnd(err) {
|
|
872
|
-
if (err instanceof Pending) return;
|
|
873
|
-
throw err;
|
|
874
|
-
};
|
|
875
|
-
|
|
876
978
|
/**
|
|
877
979
|
* Run the root suite and invoke `fn(failures)`
|
|
878
980
|
* on completion.
|
|
@@ -888,51 +990,56 @@ Runner.prototype.run = function(fn) {
|
|
|
888
990
|
|
|
889
991
|
fn = fn || function() {};
|
|
890
992
|
|
|
891
|
-
function uncaught(err) {
|
|
892
|
-
self.uncaught(err);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
993
|
function start() {
|
|
994
|
+
debug('run(): starting');
|
|
896
995
|
// If there is an `only` filter
|
|
897
996
|
if (rootSuite.hasOnly()) {
|
|
898
997
|
rootSuite.filterOnly();
|
|
998
|
+
debug('run(): filtered exclusive Runnables');
|
|
899
999
|
}
|
|
900
|
-
self.
|
|
1000
|
+
self.state = constants.STATE_RUNNING;
|
|
901
1001
|
if (self._delay) {
|
|
902
1002
|
self.emit(constants.EVENT_DELAY_END);
|
|
1003
|
+
debug('run(): "delay" ended');
|
|
903
1004
|
}
|
|
1005
|
+
debug('run(): emitting %s', constants.EVENT_RUN_BEGIN);
|
|
904
1006
|
self.emit(constants.EVENT_RUN_BEGIN);
|
|
1007
|
+
debug('run(): emitted %s', constants.EVENT_RUN_BEGIN);
|
|
905
1008
|
|
|
906
1009
|
self.runSuite(rootSuite, function() {
|
|
907
|
-
debug(
|
|
1010
|
+
debug(
|
|
1011
|
+
'run(): root suite completed; emitting %s',
|
|
1012
|
+
constants.EVENT_RUN_END
|
|
1013
|
+
);
|
|
908
1014
|
self.emit(constants.EVENT_RUN_END);
|
|
1015
|
+
debug('run(): emitted %s', constants.EVENT_RUN_END);
|
|
909
1016
|
});
|
|
910
1017
|
}
|
|
911
1018
|
|
|
912
|
-
debug(constants.EVENT_RUN_BEGIN);
|
|
913
|
-
|
|
914
1019
|
// references cleanup to avoid memory leaks
|
|
915
|
-
this.
|
|
916
|
-
|
|
917
|
-
|
|
1020
|
+
if (this._opts.cleanReferencesAfterRun) {
|
|
1021
|
+
this.on(constants.EVENT_SUITE_END, function(suite) {
|
|
1022
|
+
suite.cleanReferences();
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
918
1025
|
|
|
919
1026
|
// callback
|
|
920
1027
|
this.on(constants.EVENT_RUN_END, function() {
|
|
1028
|
+
self.state = constants.STATE_STOPPED;
|
|
921
1029
|
debug(constants.EVENT_RUN_END);
|
|
922
|
-
|
|
923
|
-
process.on('uncaughtException', self.uncaughtEnd);
|
|
1030
|
+
debug('run(): emitted %s', constants.EVENT_RUN_END);
|
|
924
1031
|
fn(self.failures);
|
|
925
1032
|
});
|
|
926
1033
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
process.on('uncaughtException', uncaught);
|
|
1034
|
+
self._removeEventListener(process, 'uncaughtException', self.uncaught);
|
|
1035
|
+
self._addEventListener(process, 'uncaughtException', self.uncaught);
|
|
930
1036
|
|
|
931
1037
|
if (this._delay) {
|
|
932
1038
|
// for reporters, I guess.
|
|
933
1039
|
// might be nice to debounce some dots while we wait.
|
|
934
1040
|
this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
|
|
935
1041
|
rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
|
|
1042
|
+
debug('run(): waiting for green light due to --delay');
|
|
936
1043
|
} else {
|
|
937
1044
|
Runner.immediately(function() {
|
|
938
1045
|
start();
|
|
@@ -950,7 +1057,7 @@ Runner.prototype.run = function(fn) {
|
|
|
950
1057
|
* @return {Runner} Runner instance.
|
|
951
1058
|
*/
|
|
952
1059
|
Runner.prototype.abort = function() {
|
|
953
|
-
debug('aborting');
|
|
1060
|
+
debug('abort(): aborting');
|
|
954
1061
|
this._abort = true;
|
|
955
1062
|
|
|
956
1063
|
return this;
|
package/lib/suite.js
CHANGED
|
@@ -61,20 +61,20 @@ function Suite(title, parentContext, isRoot) {
|
|
|
61
61
|
this.ctx = new Context();
|
|
62
62
|
this.suites = [];
|
|
63
63
|
this.tests = [];
|
|
64
|
+
this.root = isRoot === true;
|
|
64
65
|
this.pending = false;
|
|
66
|
+
this._retries = -1;
|
|
65
67
|
this._beforeEach = [];
|
|
66
68
|
this._beforeAll = [];
|
|
67
69
|
this._afterEach = [];
|
|
68
70
|
this._afterAll = [];
|
|
69
|
-
this.root = isRoot === true;
|
|
70
71
|
this._timeout = 2000;
|
|
71
72
|
this._enableTimeouts = true;
|
|
72
73
|
this._slow = 75;
|
|
73
74
|
this._bail = false;
|
|
74
|
-
this._retries = -1;
|
|
75
75
|
this._onlyTests = [];
|
|
76
76
|
this._onlySuites = [];
|
|
77
|
-
this.
|
|
77
|
+
this.reset();
|
|
78
78
|
|
|
79
79
|
this.on('newListener', function(event) {
|
|
80
80
|
if (deprecatedEvents[event]) {
|
|
@@ -92,6 +92,22 @@ function Suite(title, parentContext, isRoot) {
|
|
|
92
92
|
*/
|
|
93
93
|
inherits(Suite, EventEmitter);
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Resets the state initially or for a next run.
|
|
97
|
+
*/
|
|
98
|
+
Suite.prototype.reset = function() {
|
|
99
|
+
this.delayed = false;
|
|
100
|
+
function doReset(thingToReset) {
|
|
101
|
+
thingToReset.reset();
|
|
102
|
+
}
|
|
103
|
+
this.suites.forEach(doReset);
|
|
104
|
+
this.tests.forEach(doReset);
|
|
105
|
+
this._beforeEach.forEach(doReset);
|
|
106
|
+
this._afterEach.forEach(doReset);
|
|
107
|
+
this._beforeAll.forEach(doReset);
|
|
108
|
+
this._afterAll.forEach(doReset);
|
|
109
|
+
};
|
|
110
|
+
|
|
95
111
|
/**
|
|
96
112
|
* Return a clone of this `Suite`.
|
|
97
113
|
*
|
|
@@ -511,6 +527,16 @@ Suite.prototype.getHooks = function getHooks(name) {
|
|
|
511
527
|
return this['_' + name];
|
|
512
528
|
};
|
|
513
529
|
|
|
530
|
+
/**
|
|
531
|
+
* cleans all references from this suite and all child suites.
|
|
532
|
+
*/
|
|
533
|
+
Suite.prototype.dispose = function() {
|
|
534
|
+
this.suites.forEach(function(suite) {
|
|
535
|
+
suite.dispose();
|
|
536
|
+
});
|
|
537
|
+
this.cleanReferences();
|
|
538
|
+
};
|
|
539
|
+
|
|
514
540
|
/**
|
|
515
541
|
* Cleans up the references to all the deferred functions
|
|
516
542
|
* (before/after/beforeEach/afterEach) and tests of a Suite.
|
package/lib/test.js
CHANGED
|
@@ -26,9 +26,9 @@ function Test(title, fn) {
|
|
|
26
26
|
'string'
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
|
-
Runnable.call(this, title, fn);
|
|
30
|
-
this.pending = !fn;
|
|
31
29
|
this.type = 'test';
|
|
30
|
+
Runnable.call(this, title, fn);
|
|
31
|
+
this.reset();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -36,6 +36,15 @@ function Test(title, fn) {
|
|
|
36
36
|
*/
|
|
37
37
|
utils.inherits(Test, Runnable);
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Resets the state initially or for a next run.
|
|
41
|
+
*/
|
|
42
|
+
Test.prototype.reset = function() {
|
|
43
|
+
Runnable.prototype.reset.call(this);
|
|
44
|
+
this.pending = !this.fn;
|
|
45
|
+
delete this.state;
|
|
46
|
+
};
|
|
47
|
+
|
|
39
48
|
/**
|
|
40
49
|
* Set or get retried test
|
|
41
50
|
*
|
|
@@ -48,6 +57,15 @@ Test.prototype.retriedTest = function(n) {
|
|
|
48
57
|
this._retriedTest = n;
|
|
49
58
|
};
|
|
50
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Add test to the list of tests marked `only`.
|
|
62
|
+
*
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
Test.prototype.markOnly = function() {
|
|
66
|
+
this.parent.appendOnlyTest(this);
|
|
67
|
+
};
|
|
68
|
+
|
|
51
69
|
Test.prototype.clone = function() {
|
|
52
70
|
var test = new Test(this.title, this.fn);
|
|
53
71
|
test.timeout(this.timeout());
|
package/lib/utils.js
CHANGED
|
@@ -63,8 +63,9 @@ exports.isString = function(obj) {
|
|
|
63
63
|
exports.slug = function(str) {
|
|
64
64
|
return str
|
|
65
65
|
.toLowerCase()
|
|
66
|
-
.replace(
|
|
67
|
-
.replace(/[^-\w]/g, '')
|
|
66
|
+
.replace(/\s+/g, '-')
|
|
67
|
+
.replace(/[^-\w]/g, '')
|
|
68
|
+
.replace(/-{2,}/g, '-');
|
|
68
69
|
};
|
|
69
70
|
|
|
70
71
|
/**
|
|
@@ -637,7 +638,7 @@ exports.stackTraceFilter = function() {
|
|
|
637
638
|
var slash = path.sep;
|
|
638
639
|
var cwd;
|
|
639
640
|
if (is.node) {
|
|
640
|
-
cwd =
|
|
641
|
+
cwd = exports.cwd() + slash;
|
|
641
642
|
} else {
|
|
642
643
|
cwd = (typeof location === 'undefined'
|
|
643
644
|
? window.location
|
|
@@ -821,3 +822,13 @@ exports.supportsEsModules = function() {
|
|
|
821
822
|
}
|
|
822
823
|
}
|
|
823
824
|
};
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Returns current working directory
|
|
828
|
+
*
|
|
829
|
+
* Wrapper around `process.cwd()` for isolation
|
|
830
|
+
* @private
|
|
831
|
+
*/
|
|
832
|
+
exports.cwd = function cwd() {
|
|
833
|
+
return process.cwd();
|
|
834
|
+
};
|