mocha 6.2.3 → 7.1.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 +102 -1347
- package/LICENSE +1 -1
- package/README.md +6 -6
- package/bin/mocha +12 -41
- package/browser-entry.js +2 -2
- package/lib/cli/config.js +2 -1
- package/lib/cli/node-flags.js +1 -1
- package/lib/cli/one-and-dones.js +2 -2
- package/lib/cli/options.js +4 -35
- package/lib/cli/run-helpers.js +12 -10
- package/lib/cli/run-option-metadata.js +6 -5
- package/lib/cli/run.js +32 -14
- package/lib/cli/watch-run.js +116 -31
- package/lib/esm-utils.js +31 -0
- package/lib/mocha.js +194 -103
- package/lib/mocharc.json +3 -2
- package/lib/reporters/base.js +15 -5
- package/lib/reporters/xunit.js +3 -3
- package/lib/runnable.js +26 -18
- package/lib/runner.js +99 -87
- package/lib/test.js +13 -0
- package/lib/utils.js +22 -74
- package/mocha.js +483 -452
- package/package.json +25 -504
- package/bin/options.js +0 -10
package/lib/reporters/base.js
CHANGED
|
@@ -154,14 +154,14 @@ exports.cursor = {
|
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
var showDiff = (exports.showDiff = function(err) {
|
|
158
158
|
return (
|
|
159
159
|
err &&
|
|
160
160
|
err.showDiff !== false &&
|
|
161
161
|
sameType(err.actual, err.expected) &&
|
|
162
162
|
err.expected !== undefined
|
|
163
163
|
);
|
|
164
|
-
}
|
|
164
|
+
});
|
|
165
165
|
|
|
166
166
|
function stringifyDiffObjs(err) {
|
|
167
167
|
if (!utils.isString(err.actual) || !utils.isString(err.expected)) {
|
|
@@ -182,9 +182,19 @@ function stringifyDiffObjs(err) {
|
|
|
182
182
|
* @return {string} Diff
|
|
183
183
|
*/
|
|
184
184
|
var generateDiff = (exports.generateDiff = function(actual, expected) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
try {
|
|
186
|
+
return exports.inlineDiffs
|
|
187
|
+
? inlineDiff(actual, expected)
|
|
188
|
+
: unifiedDiff(actual, expected);
|
|
189
|
+
} catch (err) {
|
|
190
|
+
var msg =
|
|
191
|
+
'\n ' +
|
|
192
|
+
color('diff added', '+ expected') +
|
|
193
|
+
' ' +
|
|
194
|
+
color('diff removed', '- actual: failed to generate Mocha diff') +
|
|
195
|
+
'\n';
|
|
196
|
+
return msg;
|
|
197
|
+
}
|
|
188
198
|
});
|
|
189
199
|
|
|
190
200
|
/**
|
package/lib/reporters/xunit.js
CHANGED
|
@@ -163,9 +163,9 @@ XUnit.prototype.test = function(test) {
|
|
|
163
163
|
if (test.state === STATE_FAILED) {
|
|
164
164
|
var err = test.err;
|
|
165
165
|
var diff =
|
|
166
|
-
Base.hideDiff
|
|
167
|
-
? ''
|
|
168
|
-
: '
|
|
166
|
+
!Base.hideDiff && Base.showDiff(err)
|
|
167
|
+
? '\n' + Base.generateDiff(err.actual, err.expected)
|
|
168
|
+
: '';
|
|
169
169
|
this.write(
|
|
170
170
|
tag(
|
|
171
171
|
'testcase',
|
package/lib/runnable.js
CHANGED
|
@@ -135,7 +135,8 @@ Runnable.prototype.enableTimeouts = function(enabled) {
|
|
|
135
135
|
* @public
|
|
136
136
|
*/
|
|
137
137
|
Runnable.prototype.skip = function() {
|
|
138
|
-
|
|
138
|
+
this.pending = true;
|
|
139
|
+
throw new Pending('sync skip; aborting execution');
|
|
139
140
|
};
|
|
140
141
|
|
|
141
142
|
/**
|
|
@@ -334,43 +335,45 @@ Runnable.prototype.run = function(fn) {
|
|
|
334
335
|
fn(err);
|
|
335
336
|
}
|
|
336
337
|
|
|
337
|
-
// for .resetTimeout()
|
|
338
|
+
// for .resetTimeout() and Runner#uncaught()
|
|
338
339
|
this.callback = done;
|
|
339
340
|
|
|
341
|
+
if (this.fn && typeof this.fn.call !== 'function') {
|
|
342
|
+
done(
|
|
343
|
+
new TypeError(
|
|
344
|
+
'A runnable must be passed a function as its second argument.'
|
|
345
|
+
)
|
|
346
|
+
);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
340
350
|
// explicit async with `done` argument
|
|
341
351
|
if (this.async) {
|
|
342
352
|
this.resetTimeout();
|
|
343
353
|
|
|
344
354
|
// allows skip() to be used in an explicit async context
|
|
345
355
|
this.skip = function asyncSkip() {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
//
|
|
349
|
-
// the failure.
|
|
356
|
+
this.pending = true;
|
|
357
|
+
done();
|
|
358
|
+
// halt execution, the uncaught handler will ignore the failure.
|
|
350
359
|
throw new Pending('async skip; aborting execution');
|
|
351
360
|
};
|
|
352
361
|
|
|
353
|
-
if (this.allowUncaught) {
|
|
354
|
-
return callFnAsync(this.fn);
|
|
355
|
-
}
|
|
356
362
|
try {
|
|
357
363
|
callFnAsync(this.fn);
|
|
358
364
|
} catch (err) {
|
|
365
|
+
// handles async runnables which actually run synchronously
|
|
359
366
|
emitted = true;
|
|
367
|
+
if (err instanceof Pending) {
|
|
368
|
+
return; // done() is already called in this.skip()
|
|
369
|
+
} else if (this.allowUncaught) {
|
|
370
|
+
throw err;
|
|
371
|
+
}
|
|
360
372
|
done(Runnable.toValueOrError(err));
|
|
361
373
|
}
|
|
362
374
|
return;
|
|
363
375
|
}
|
|
364
376
|
|
|
365
|
-
if (this.allowUncaught) {
|
|
366
|
-
if (this.isPending()) {
|
|
367
|
-
done();
|
|
368
|
-
} else {
|
|
369
|
-
callFn(this.fn);
|
|
370
|
-
}
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
377
|
// sync or promise-returning
|
|
375
378
|
try {
|
|
376
379
|
if (this.isPending()) {
|
|
@@ -380,6 +383,11 @@ Runnable.prototype.run = function(fn) {
|
|
|
380
383
|
}
|
|
381
384
|
} catch (err) {
|
|
382
385
|
emitted = true;
|
|
386
|
+
if (err instanceof Pending) {
|
|
387
|
+
return done();
|
|
388
|
+
} else if (this.allowUncaught) {
|
|
389
|
+
throw err;
|
|
390
|
+
}
|
|
383
391
|
done(Runnable.toValueOrError(err));
|
|
384
392
|
}
|
|
385
393
|
|
package/lib/runner.js
CHANGED
|
@@ -24,8 +24,9 @@ var sQuote = utils.sQuote;
|
|
|
24
24
|
var stackFilter = utils.stackTraceFilter();
|
|
25
25
|
var stringify = utils.stringify;
|
|
26
26
|
var type = utils.type;
|
|
27
|
-
var
|
|
28
|
-
|
|
27
|
+
var errors = require('./errors');
|
|
28
|
+
var createInvalidExceptionError = errors.createInvalidExceptionError;
|
|
29
|
+
var createUnsupportedError = errors.createUnsupportedError;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Non-enumerable globals.
|
|
@@ -134,6 +135,11 @@ function Runner(suite, delay) {
|
|
|
134
135
|
this.total = suite.total();
|
|
135
136
|
this.failures = 0;
|
|
136
137
|
this.on(constants.EVENT_TEST_END, function(test) {
|
|
138
|
+
if (test.retriedTest() && test.parent) {
|
|
139
|
+
var idx =
|
|
140
|
+
test.parent.tests && test.parent.tests.indexOf(test.retriedTest());
|
|
141
|
+
if (idx > -1) test.parent.tests[idx] = test;
|
|
142
|
+
}
|
|
137
143
|
self.checkGlobals(test);
|
|
138
144
|
});
|
|
139
145
|
this.on(constants.EVENT_HOOK_END, function(hook) {
|
|
@@ -244,7 +250,7 @@ Runner.prototype.globals = function(arr) {
|
|
|
244
250
|
* @private
|
|
245
251
|
*/
|
|
246
252
|
Runner.prototype.checkGlobals = function(test) {
|
|
247
|
-
if (this.
|
|
253
|
+
if (!this.checkLeaks) {
|
|
248
254
|
return;
|
|
249
255
|
}
|
|
250
256
|
var ok = this._globals;
|
|
@@ -315,8 +321,7 @@ Runner.prototype.fail = function(test, err) {
|
|
|
315
321
|
* - Failed `before each` hook skips remaining tests in a
|
|
316
322
|
* suite and jumps to corresponding `after each` hook,
|
|
317
323
|
* which is run only once
|
|
318
|
-
* - Failed `after` hook does not alter
|
|
319
|
-
* execution order
|
|
324
|
+
* - Failed `after` hook does not alter execution order
|
|
320
325
|
* - Failed `after each` hook skips remaining tests in a
|
|
321
326
|
* suite and subsuites, but executes other `after each`
|
|
322
327
|
* hooks
|
|
@@ -386,34 +391,37 @@ Runner.prototype.hook = function(name, fn) {
|
|
|
386
391
|
if (testError) {
|
|
387
392
|
self.fail(self.test, testError);
|
|
388
393
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
);
|
|
394
|
+
// conditional skip
|
|
395
|
+
if (hook.pending) {
|
|
396
|
+
if (name === HOOK_TYPE_AFTER_EACH) {
|
|
397
|
+
// TODO define and implement use case
|
|
398
|
+
if (self.test) {
|
|
399
|
+
self.test.pending = true;
|
|
396
400
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
} else {
|
|
402
|
-
suite.tests.forEach(function(test) {
|
|
403
|
-
test.pending = true;
|
|
404
|
-
});
|
|
405
|
-
suite.suites.forEach(function(suite) {
|
|
406
|
-
suite.pending = true;
|
|
407
|
-
});
|
|
408
|
-
// a pending hook won't be executed twice.
|
|
409
|
-
hook.pending = true;
|
|
401
|
+
} else if (name === HOOK_TYPE_BEFORE_EACH) {
|
|
402
|
+
if (self.test) {
|
|
403
|
+
self.test.pending = true;
|
|
410
404
|
}
|
|
405
|
+
self.emit(constants.EVENT_HOOK_END, hook);
|
|
406
|
+
hook.pending = false; // activates hook for next test
|
|
407
|
+
return fn(new Error('abort hookDown'));
|
|
408
|
+
} else if (name === HOOK_TYPE_BEFORE_ALL) {
|
|
409
|
+
suite.tests.forEach(function(test) {
|
|
410
|
+
test.pending = true;
|
|
411
|
+
});
|
|
412
|
+
suite.suites.forEach(function(suite) {
|
|
413
|
+
suite.pending = true;
|
|
414
|
+
});
|
|
411
415
|
} else {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return fn(
|
|
416
|
+
hook.pending = false;
|
|
417
|
+
var errForbid = createUnsupportedError('`this.skip` forbidden');
|
|
418
|
+
self.failHook(hook, errForbid);
|
|
419
|
+
return fn(errForbid);
|
|
416
420
|
}
|
|
421
|
+
} else if (err) {
|
|
422
|
+
self.failHook(hook, err);
|
|
423
|
+
// stop executing hooks, notify callee of hook err
|
|
424
|
+
return fn(err);
|
|
417
425
|
}
|
|
418
426
|
self.emit(constants.EVENT_HOOK_END, hook);
|
|
419
427
|
delete hook.ctx.currentTest;
|
|
@@ -525,6 +533,9 @@ Runner.prototype.runTest = function(fn) {
|
|
|
525
533
|
test.asyncOnly = true;
|
|
526
534
|
}
|
|
527
535
|
test.on('error', function(err) {
|
|
536
|
+
if (err instanceof Pending) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
528
539
|
self.fail(test, err);
|
|
529
540
|
});
|
|
530
541
|
if (this.allowUncaught) {
|
|
@@ -620,6 +631,7 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
620
631
|
return;
|
|
621
632
|
}
|
|
622
633
|
|
|
634
|
+
// static skip, no hooks are executed
|
|
623
635
|
if (test.isPending()) {
|
|
624
636
|
if (self.forbidPending) {
|
|
625
637
|
test.isPending = alwaysFalse;
|
|
@@ -635,6 +647,7 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
635
647
|
// execute test and hook(s)
|
|
636
648
|
self.emit(constants.EVENT_TEST_BEGIN, (self.test = test));
|
|
637
649
|
self.hookDown(HOOK_TYPE_BEFORE_EACH, function(err, errSuite) {
|
|
650
|
+
// conditional skip within beforeEach
|
|
638
651
|
if (test.isPending()) {
|
|
639
652
|
if (self.forbidPending) {
|
|
640
653
|
test.isPending = alwaysFalse;
|
|
@@ -644,7 +657,13 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
644
657
|
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
645
658
|
}
|
|
646
659
|
self.emit(constants.EVENT_TEST_END, test);
|
|
647
|
-
|
|
660
|
+
// skip inner afterEach hooks below errSuite level
|
|
661
|
+
var origSuite = self.suite;
|
|
662
|
+
self.suite = errSuite || self.suite;
|
|
663
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, function(e, eSuite) {
|
|
664
|
+
self.suite = origSuite;
|
|
665
|
+
next(e, eSuite);
|
|
666
|
+
});
|
|
648
667
|
}
|
|
649
668
|
if (err) {
|
|
650
669
|
return hookErr(err, errSuite, false);
|
|
@@ -652,14 +671,20 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
652
671
|
self.currentRunnable = self.test;
|
|
653
672
|
self.runTest(function(err) {
|
|
654
673
|
test = self.test;
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
if (
|
|
674
|
+
// conditional skip within it
|
|
675
|
+
if (test.pending) {
|
|
676
|
+
if (self.forbidPending) {
|
|
677
|
+
test.isPending = alwaysFalse;
|
|
658
678
|
self.fail(test, new Error('Pending test forbidden'));
|
|
659
|
-
|
|
660
|
-
|
|
679
|
+
delete test.isPending;
|
|
680
|
+
} else {
|
|
661
681
|
self.emit(constants.EVENT_TEST_PENDING, test);
|
|
662
|
-
}
|
|
682
|
+
}
|
|
683
|
+
self.emit(constants.EVENT_TEST_END, test);
|
|
684
|
+
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
685
|
+
} else if (err) {
|
|
686
|
+
var retry = test.currentRetry();
|
|
687
|
+
if (retry < test.retries()) {
|
|
663
688
|
var clonedTest = test.clone();
|
|
664
689
|
clonedTest.currentRetry(retry + 1);
|
|
665
690
|
tests.unshift(clonedTest);
|
|
@@ -673,11 +698,6 @@ Runner.prototype.runTests = function(suite, fn) {
|
|
|
673
698
|
self.fail(test, err);
|
|
674
699
|
}
|
|
675
700
|
self.emit(constants.EVENT_TEST_END, test);
|
|
676
|
-
|
|
677
|
-
if (err instanceof Pending) {
|
|
678
|
-
return next();
|
|
679
|
-
}
|
|
680
|
-
|
|
681
701
|
return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
|
|
682
702
|
}
|
|
683
703
|
|
|
@@ -709,7 +729,6 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
709
729
|
var i = 0;
|
|
710
730
|
var self = this;
|
|
711
731
|
var total = this.grepTotal(suite);
|
|
712
|
-
var afterAllHookCalled = false;
|
|
713
732
|
|
|
714
733
|
debug('run suite %s', suite.fullTitle());
|
|
715
734
|
|
|
@@ -757,21 +776,13 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
757
776
|
self.suite = suite;
|
|
758
777
|
self.nextSuite = next;
|
|
759
778
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
} else {
|
|
763
|
-
// mark that the afterAll block has been called once
|
|
764
|
-
// and so can be skipped if there is an error in it.
|
|
765
|
-
afterAllHookCalled = true;
|
|
779
|
+
// remove reference to test
|
|
780
|
+
delete self.test;
|
|
766
781
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
self.emit(constants.EVENT_SUITE_END, suite);
|
|
772
|
-
fn(errSuite);
|
|
773
|
-
});
|
|
774
|
-
}
|
|
782
|
+
self.hook(HOOK_TYPE_AFTER_ALL, function() {
|
|
783
|
+
self.emit(constants.EVENT_SUITE_END, suite);
|
|
784
|
+
fn(errSuite);
|
|
785
|
+
});
|
|
775
786
|
}
|
|
776
787
|
|
|
777
788
|
this.nextSuite = next;
|
|
@@ -785,7 +796,7 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
785
796
|
};
|
|
786
797
|
|
|
787
798
|
/**
|
|
788
|
-
* Handle uncaught exceptions.
|
|
799
|
+
* Handle uncaught exceptions within runner.
|
|
789
800
|
*
|
|
790
801
|
* @param {Error} err
|
|
791
802
|
* @private
|
|
@@ -794,6 +805,11 @@ Runner.prototype.uncaught = function(err) {
|
|
|
794
805
|
if (err instanceof Pending) {
|
|
795
806
|
return;
|
|
796
807
|
}
|
|
808
|
+
// browser does not exit script when throwing in global.onerror()
|
|
809
|
+
if (this.allowUncaught && !process.browser) {
|
|
810
|
+
throw err;
|
|
811
|
+
}
|
|
812
|
+
|
|
797
813
|
if (err) {
|
|
798
814
|
debug('uncaught exception %O', err);
|
|
799
815
|
} else {
|
|
@@ -829,43 +845,37 @@ Runner.prototype.uncaught = function(err) {
|
|
|
829
845
|
|
|
830
846
|
runnable.clearTimeout();
|
|
831
847
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
848
|
+
if (runnable.isFailed()) {
|
|
849
|
+
// Ignore error if already failed
|
|
850
|
+
return;
|
|
851
|
+
} else if (runnable.isPending()) {
|
|
852
|
+
// report 'pending test' retrospectively as failed
|
|
853
|
+
runnable.isPending = alwaysFalse;
|
|
854
|
+
this.fail(runnable, err);
|
|
855
|
+
delete runnable.isPending;
|
|
835
856
|
return;
|
|
836
857
|
}
|
|
858
|
+
|
|
837
859
|
// we cannot recover gracefully if a Runnable has already passed
|
|
838
860
|
// then fails asynchronously
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
// recover from test
|
|
844
|
-
if (runnable.type === constants.EVENT_TEST_BEGIN) {
|
|
845
|
-
this.emit(constants.EVENT_TEST_END, runnable);
|
|
846
|
-
this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
861
|
+
if (runnable.isPassed()) {
|
|
862
|
+
this.fail(runnable, err);
|
|
863
|
+
this.abort();
|
|
864
|
+
} else {
|
|
849
865
|
debug(runnable);
|
|
850
|
-
|
|
851
|
-
// recover from hooks
|
|
852
|
-
var errSuite = this.suite;
|
|
853
|
-
|
|
854
|
-
// XXX how about a less awful way to determine this?
|
|
855
|
-
// if hook failure is in afterEach block
|
|
856
|
-
if (runnable.fullTitle().indexOf('after each') > -1) {
|
|
857
|
-
return this.hookErr(err, errSuite, true);
|
|
858
|
-
}
|
|
859
|
-
// if hook failure is in beforeEach block
|
|
860
|
-
if (runnable.fullTitle().indexOf('before each') > -1) {
|
|
861
|
-
return this.hookErr(err, errSuite, false);
|
|
862
|
-
}
|
|
863
|
-
// if hook failure is in after or before blocks
|
|
864
|
-
return this.nextSuite(errSuite);
|
|
866
|
+
return runnable.callback(err);
|
|
865
867
|
}
|
|
868
|
+
};
|
|
866
869
|
|
|
867
|
-
|
|
868
|
-
|
|
870
|
+
/**
|
|
871
|
+
* Handle uncaught exceptions after runner's end event.
|
|
872
|
+
*
|
|
873
|
+
* @param {Error} err
|
|
874
|
+
* @private
|
|
875
|
+
*/
|
|
876
|
+
Runner.prototype.uncaughtEnd = function uncaughtEnd(err) {
|
|
877
|
+
if (err instanceof Pending) return;
|
|
878
|
+
throw err;
|
|
869
879
|
};
|
|
870
880
|
|
|
871
881
|
/**
|
|
@@ -915,10 +925,12 @@ Runner.prototype.run = function(fn) {
|
|
|
915
925
|
this.on(constants.EVENT_RUN_END, function() {
|
|
916
926
|
debug(constants.EVENT_RUN_END);
|
|
917
927
|
process.removeListener('uncaughtException', uncaught);
|
|
928
|
+
process.on('uncaughtException', self.uncaughtEnd);
|
|
918
929
|
fn(self.failures);
|
|
919
930
|
});
|
|
920
931
|
|
|
921
932
|
// uncaught exception
|
|
933
|
+
process.removeListener('uncaughtException', self.uncaughtEnd);
|
|
922
934
|
process.on('uncaughtException', uncaught);
|
|
923
935
|
|
|
924
936
|
if (this._delay) {
|
package/lib/test.js
CHANGED
|
@@ -36,6 +36,18 @@ function Test(title, fn) {
|
|
|
36
36
|
*/
|
|
37
37
|
utils.inherits(Test, Runnable);
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Set or get retried test
|
|
41
|
+
*
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
Test.prototype.retriedTest = function(n) {
|
|
45
|
+
if (!arguments.length) {
|
|
46
|
+
return this._retriedTest;
|
|
47
|
+
}
|
|
48
|
+
this._retriedTest = n;
|
|
49
|
+
};
|
|
50
|
+
|
|
39
51
|
Test.prototype.clone = function() {
|
|
40
52
|
var test = new Test(this.title, this.fn);
|
|
41
53
|
test.timeout(this.timeout());
|
|
@@ -43,6 +55,7 @@ Test.prototype.clone = function() {
|
|
|
43
55
|
test.enableTimeouts(this.enableTimeouts());
|
|
44
56
|
test.retries(this.retries());
|
|
45
57
|
test.currentRetry(this.currentRetry());
|
|
58
|
+
test.retriedTest(this.retriedTest() || this);
|
|
46
59
|
test.globals(this.globals());
|
|
47
60
|
test.parent = this.parent;
|
|
48
61
|
test.file = this.file;
|
package/lib/utils.js
CHANGED
|
@@ -53,80 +53,6 @@ exports.isString = function(obj) {
|
|
|
53
53
|
return typeof obj === 'string';
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
/**
|
|
57
|
-
* Watch the given `files` for changes
|
|
58
|
-
* and invoke `fn(file)` on modification.
|
|
59
|
-
*
|
|
60
|
-
* @private
|
|
61
|
-
* @param {Array} files
|
|
62
|
-
* @param {Function} fn
|
|
63
|
-
*/
|
|
64
|
-
exports.watch = function(files, fn) {
|
|
65
|
-
var options = {interval: 100};
|
|
66
|
-
var debug = require('debug')('mocha:watch');
|
|
67
|
-
files.forEach(function(file) {
|
|
68
|
-
debug('file %s', file);
|
|
69
|
-
fs.watchFile(file, options, function(curr, prev) {
|
|
70
|
-
if (prev.mtime < curr.mtime) {
|
|
71
|
-
fn(file);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Predicate to screen `pathname` for further consideration.
|
|
79
|
-
*
|
|
80
|
-
* @description
|
|
81
|
-
* Returns <code>false</code> for pathname referencing:
|
|
82
|
-
* <ul>
|
|
83
|
-
* <li>'npm' package installation directory
|
|
84
|
-
* <li>'git' version control directory
|
|
85
|
-
* </ul>
|
|
86
|
-
*
|
|
87
|
-
* @private
|
|
88
|
-
* @param {string} pathname - File or directory name to screen
|
|
89
|
-
* @return {boolean} whether pathname should be further considered
|
|
90
|
-
* @example
|
|
91
|
-
* ['node_modules', 'test.js'].filter(considerFurther); // => ['test.js']
|
|
92
|
-
*/
|
|
93
|
-
function considerFurther(pathname) {
|
|
94
|
-
var ignore = ['node_modules', '.git'];
|
|
95
|
-
|
|
96
|
-
return !~ignore.indexOf(pathname);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Lookup files in the given `dir`.
|
|
101
|
-
*
|
|
102
|
-
* @description
|
|
103
|
-
* Filenames are returned in _traversal_ order by the OS/filesystem.
|
|
104
|
-
* **Make no assumption that the names will be sorted in any fashion.**
|
|
105
|
-
*
|
|
106
|
-
* @private
|
|
107
|
-
* @param {string} dir
|
|
108
|
-
* @param {string[]} [exts=['js']]
|
|
109
|
-
* @param {Array} [ret=[]]
|
|
110
|
-
* @return {Array}
|
|
111
|
-
*/
|
|
112
|
-
exports.files = function(dir, exts, ret) {
|
|
113
|
-
ret = ret || [];
|
|
114
|
-
exts = exts || ['js'];
|
|
115
|
-
|
|
116
|
-
fs.readdirSync(dir)
|
|
117
|
-
.filter(considerFurther)
|
|
118
|
-
.forEach(function(dirent) {
|
|
119
|
-
var pathname = path.join(dir, dirent);
|
|
120
|
-
if (fs.lstatSync(pathname).isDirectory()) {
|
|
121
|
-
exports.files(pathname, exts, ret);
|
|
122
|
-
} else if (hasMatchingExtname(pathname, exts)) {
|
|
123
|
-
ret.push(pathname);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
return ret;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
56
|
/**
|
|
131
57
|
* Compute a slug from the given `str`.
|
|
132
58
|
*
|
|
@@ -905,3 +831,25 @@ exports.defineConstants = function(obj) {
|
|
|
905
831
|
}
|
|
906
832
|
return Object.freeze(exports.createMap(obj));
|
|
907
833
|
};
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* Whether current version of Node support ES modules
|
|
837
|
+
*
|
|
838
|
+
* @description
|
|
839
|
+
* Versions prior to 10 did not support ES Modules, and version 10 has an old incompatibile version of ESM.
|
|
840
|
+
* This function returns whether Node.JS has ES Module supports that is compatible with Mocha's needs,
|
|
841
|
+
* which is version >=12.11.
|
|
842
|
+
*
|
|
843
|
+
* @returns {Boolean} whether the current version of Node.JS supports ES Modules in a way that is compatible with Mocha
|
|
844
|
+
*/
|
|
845
|
+
exports.supportsEsModules = function() {
|
|
846
|
+
if (!process.browser && process.versions && process.versions.node) {
|
|
847
|
+
var versionFields = process.versions.node.split('.');
|
|
848
|
+
var major = +versionFields[0];
|
|
849
|
+
var minor = +versionFields[1];
|
|
850
|
+
|
|
851
|
+
if (major >= 13 || (major === 12 && minor >= 11)) {
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
};
|