mocha 7.0.1 → 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 +86 -2
- package/bin/mocha +7 -2
- package/browser-entry.js +13 -2
- package/lib/cli/cli.js +4 -1
- package/lib/cli/collect-files.js +2 -1
- package/lib/cli/config.js +8 -6
- package/lib/cli/options.js +4 -4
- package/lib/cli/run-helpers.js +93 -33
- package/lib/cli/run.js +23 -5
- package/lib/errors.js +179 -9
- package/lib/esm-utils.js +31 -0
- package/lib/hook.js +8 -0
- package/lib/interfaces/common.js +6 -3
- package/lib/mocha.js +226 -16
- package/lib/mocharc.json +1 -1
- 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 -42
- package/lib/runner.js +173 -63
- package/lib/suite.js +29 -3
- package/lib/test.js +33 -2
- package/lib/utils.js +36 -35
- package/mocha.js +749 -185
- package/package.json +56 -549
package/mocha.js
CHANGED
|
@@ -54,6 +54,17 @@ process.removeListener = function(e, fn) {
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Implements listenerCount for 'uncaughtException'.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
process.listenerCount = function(name) {
|
|
62
|
+
if (name === 'uncaughtException') {
|
|
63
|
+
return uncaughtExceptionHandlers.length;
|
|
64
|
+
}
|
|
65
|
+
return 0;
|
|
66
|
+
};
|
|
67
|
+
|
|
57
68
|
/**
|
|
58
69
|
* Implements uncaughtException listener.
|
|
59
70
|
*/
|
|
@@ -62,7 +73,7 @@ process.on = function(e, fn) {
|
|
|
62
73
|
if (e === 'uncaughtException') {
|
|
63
74
|
global.onerror = function(err, url, line) {
|
|
64
75
|
fn(new Error(err + ' (' + url + ':' + line + ')'));
|
|
65
|
-
return !mocha.allowUncaught;
|
|
76
|
+
return !mocha.options.allowUncaught;
|
|
66
77
|
};
|
|
67
78
|
uncaughtExceptionHandlers.push(fn);
|
|
68
79
|
}
|
|
@@ -131,7 +142,7 @@ mocha.setup = function(opts) {
|
|
|
131
142
|
opts = {ui: opts};
|
|
132
143
|
}
|
|
133
144
|
for (var opt in opts) {
|
|
134
|
-
if (
|
|
145
|
+
if (Object.prototype.hasOwnProperty.call(opts, opt)) {
|
|
135
146
|
this[opt](opts[opt]);
|
|
136
147
|
}
|
|
137
148
|
}
|
|
@@ -608,12 +619,75 @@ Context.prototype.retries = function(n) {
|
|
|
608
619
|
|
|
609
620
|
},{}],6:[function(require,module,exports){
|
|
610
621
|
'use strict';
|
|
622
|
+
|
|
623
|
+
var format = require('util').format;
|
|
624
|
+
|
|
611
625
|
/**
|
|
626
|
+
* Factory functions to create throwable error objects
|
|
612
627
|
* @module Errors
|
|
613
628
|
*/
|
|
629
|
+
|
|
614
630
|
/**
|
|
615
|
-
*
|
|
631
|
+
* When Mocha throw exceptions (or otherwise errors), it attempts to assign a
|
|
632
|
+
* `code` property to the `Error` object, for easier handling. These are the
|
|
633
|
+
* potential values of `code`.
|
|
616
634
|
*/
|
|
635
|
+
var constants = {
|
|
636
|
+
/**
|
|
637
|
+
* An unrecoverable error.
|
|
638
|
+
*/
|
|
639
|
+
FATAL: 'ERR_MOCHA_FATAL',
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* The type of an argument to a function call is invalid
|
|
643
|
+
*/
|
|
644
|
+
INVALID_ARG_TYPE: 'ERR_MOCHA_INVALID_ARG_TYPE',
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* The value of an argument to a function call is invalid
|
|
648
|
+
*/
|
|
649
|
+
INVALID_ARG_VALUE: 'ERR_MOCHA_INVALID_ARG_VALUE',
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Something was thrown, but it wasn't an `Error`
|
|
653
|
+
*/
|
|
654
|
+
INVALID_EXCEPTION: 'ERR_MOCHA_INVALID_EXCEPTION',
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* An interface (e.g., `Mocha.interfaces`) is unknown or invalid
|
|
658
|
+
*/
|
|
659
|
+
INVALID_INTERFACE: 'ERR_MOCHA_INVALID_INTERFACE',
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* A reporter (.e.g, `Mocha.reporters`) is unknown or invalid
|
|
663
|
+
*/
|
|
664
|
+
INVALID_REPORTER: 'ERR_MOCHA_INVALID_REPORTER',
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* `done()` was called twice in a `Test` or `Hook` callback
|
|
668
|
+
*/
|
|
669
|
+
MULTIPLE_DONE: 'ERR_MOCHA_MULTIPLE_DONE',
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* No files matched the pattern provided by the user
|
|
673
|
+
*/
|
|
674
|
+
NO_FILES_MATCH_PATTERN: 'ERR_MOCHA_NO_FILES_MATCH_PATTERN',
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Known, but unsupported behavior of some kind
|
|
678
|
+
*/
|
|
679
|
+
UNSUPPORTED: 'ERR_MOCHA_UNSUPPORTED',
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Invalid state transition occuring in `Mocha` instance
|
|
683
|
+
*/
|
|
684
|
+
INSTANCE_ALREADY_RUNNING: 'ERR_MOCHA_INSTANCE_ALREADY_RUNNING',
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Invalid state transition occuring in `Mocha` instance
|
|
688
|
+
*/
|
|
689
|
+
INSTANCE_ALREADY_DISPOSED: 'ERR_MOCHA_INSTANCE_ALREADY_DISPOSED'
|
|
690
|
+
};
|
|
617
691
|
|
|
618
692
|
/**
|
|
619
693
|
* Creates an error object to be thrown when no files to be tested could be found using specified pattern.
|
|
@@ -625,7 +699,7 @@ Context.prototype.retries = function(n) {
|
|
|
625
699
|
*/
|
|
626
700
|
function createNoFilesMatchPatternError(message, pattern) {
|
|
627
701
|
var err = new Error(message);
|
|
628
|
-
err.code =
|
|
702
|
+
err.code = constants.NO_FILES_MATCH_PATTERN;
|
|
629
703
|
err.pattern = pattern;
|
|
630
704
|
return err;
|
|
631
705
|
}
|
|
@@ -640,7 +714,7 @@ function createNoFilesMatchPatternError(message, pattern) {
|
|
|
640
714
|
*/
|
|
641
715
|
function createInvalidReporterError(message, reporter) {
|
|
642
716
|
var err = new TypeError(message);
|
|
643
|
-
err.code =
|
|
717
|
+
err.code = constants.INVALID_REPORTER;
|
|
644
718
|
err.reporter = reporter;
|
|
645
719
|
return err;
|
|
646
720
|
}
|
|
@@ -655,7 +729,7 @@ function createInvalidReporterError(message, reporter) {
|
|
|
655
729
|
*/
|
|
656
730
|
function createInvalidInterfaceError(message, ui) {
|
|
657
731
|
var err = new Error(message);
|
|
658
|
-
err.code =
|
|
732
|
+
err.code = constants.INVALID_INTERFACE;
|
|
659
733
|
err.interface = ui;
|
|
660
734
|
return err;
|
|
661
735
|
}
|
|
@@ -669,7 +743,7 @@ function createInvalidInterfaceError(message, ui) {
|
|
|
669
743
|
*/
|
|
670
744
|
function createUnsupportedError(message) {
|
|
671
745
|
var err = new Error(message);
|
|
672
|
-
err.code =
|
|
746
|
+
err.code = constants.UNSUPPORTED;
|
|
673
747
|
return err;
|
|
674
748
|
}
|
|
675
749
|
|
|
@@ -697,7 +771,7 @@ function createMissingArgumentError(message, argument, expected) {
|
|
|
697
771
|
*/
|
|
698
772
|
function createInvalidArgumentTypeError(message, argument, expected) {
|
|
699
773
|
var err = new TypeError(message);
|
|
700
|
-
err.code =
|
|
774
|
+
err.code = constants.INVALID_ARG_TYPE;
|
|
701
775
|
err.argument = argument;
|
|
702
776
|
err.expected = expected;
|
|
703
777
|
err.actual = typeof argument;
|
|
@@ -716,7 +790,7 @@ function createInvalidArgumentTypeError(message, argument, expected) {
|
|
|
716
790
|
*/
|
|
717
791
|
function createInvalidArgumentValueError(message, argument, value, reason) {
|
|
718
792
|
var err = new TypeError(message);
|
|
719
|
-
err.code =
|
|
793
|
+
err.code = constants.INVALID_ARG_VALUE;
|
|
720
794
|
err.argument = argument;
|
|
721
795
|
err.value = value;
|
|
722
796
|
err.reason = typeof reason !== 'undefined' ? reason : 'is invalid';
|
|
@@ -732,12 +806,113 @@ function createInvalidArgumentValueError(message, argument, value, reason) {
|
|
|
732
806
|
*/
|
|
733
807
|
function createInvalidExceptionError(message, value) {
|
|
734
808
|
var err = new Error(message);
|
|
735
|
-
err.code =
|
|
809
|
+
err.code = constants.INVALID_EXCEPTION;
|
|
736
810
|
err.valueType = typeof value;
|
|
737
811
|
err.value = value;
|
|
738
812
|
return err;
|
|
739
813
|
}
|
|
740
814
|
|
|
815
|
+
/**
|
|
816
|
+
* Creates an error object to be thrown when an unrecoverable error occurs.
|
|
817
|
+
*
|
|
818
|
+
* @public
|
|
819
|
+
* @param {string} message - Error message to be displayed.
|
|
820
|
+
* @returns {Error} instance detailing the error condition
|
|
821
|
+
*/
|
|
822
|
+
function createFatalError(message, value) {
|
|
823
|
+
var err = new Error(message);
|
|
824
|
+
err.code = constants.FATAL;
|
|
825
|
+
err.valueType = typeof value;
|
|
826
|
+
err.value = value;
|
|
827
|
+
return err;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Dynamically creates a plugin-type-specific error based on plugin type
|
|
832
|
+
* @param {string} message - Error message
|
|
833
|
+
* @param {"reporter"|"interface"} pluginType - Plugin type. Future: expand as needed
|
|
834
|
+
* @param {string} [pluginId] - Name/path of plugin, if any
|
|
835
|
+
* @throws When `pluginType` is not known
|
|
836
|
+
* @public
|
|
837
|
+
* @returns {Error}
|
|
838
|
+
*/
|
|
839
|
+
function createInvalidPluginError(message, pluginType, pluginId) {
|
|
840
|
+
switch (pluginType) {
|
|
841
|
+
case 'reporter':
|
|
842
|
+
return createInvalidReporterError(message, pluginId);
|
|
843
|
+
case 'interface':
|
|
844
|
+
return createInvalidInterfaceError(message, pluginId);
|
|
845
|
+
default:
|
|
846
|
+
throw new Error('unknown pluginType "' + pluginType + '"');
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Creates an error object to be thrown when a mocha object's `run` method is executed while it is already disposed.
|
|
852
|
+
* @param {string} message The error message to be displayed.
|
|
853
|
+
* @param {boolean} cleanReferencesAfterRun the value of `cleanReferencesAfterRun`
|
|
854
|
+
* @param {Mocha} instance the mocha instance that throw this error
|
|
855
|
+
*/
|
|
856
|
+
function createMochaInstanceAlreadyDisposedError(
|
|
857
|
+
message,
|
|
858
|
+
cleanReferencesAfterRun,
|
|
859
|
+
instance
|
|
860
|
+
) {
|
|
861
|
+
var err = new Error(message);
|
|
862
|
+
err.code = constants.INSTANCE_ALREADY_DISPOSED;
|
|
863
|
+
err.cleanReferencesAfterRun = cleanReferencesAfterRun;
|
|
864
|
+
err.instance = instance;
|
|
865
|
+
return err;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Creates an error object to be thrown when a mocha object's `run` method is called while a test run is in progress.
|
|
870
|
+
* @param {string} message The error message to be displayed.
|
|
871
|
+
*/
|
|
872
|
+
function createMochaInstanceAlreadyRunningError(message, instance) {
|
|
873
|
+
var err = new Error(message);
|
|
874
|
+
err.code = constants.INSTANCE_ALREADY_RUNNING;
|
|
875
|
+
err.instance = instance;
|
|
876
|
+
return err;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/*
|
|
880
|
+
* Creates an error object to be thrown when done() is called multiple times in a test
|
|
881
|
+
*
|
|
882
|
+
* @public
|
|
883
|
+
* @param {Runnable} runnable - Original runnable
|
|
884
|
+
* @param {Error} [originalErr] - Original error, if any
|
|
885
|
+
* @returns {Error} instance detailing the error condition
|
|
886
|
+
*/
|
|
887
|
+
function createMultipleDoneError(runnable, originalErr) {
|
|
888
|
+
var title;
|
|
889
|
+
try {
|
|
890
|
+
title = format('<%s>', runnable.fullTitle());
|
|
891
|
+
if (runnable.parent.root) {
|
|
892
|
+
title += ' (of root suite)';
|
|
893
|
+
}
|
|
894
|
+
} catch (ignored) {
|
|
895
|
+
title = format('<%s> (of unknown suite)', runnable.title);
|
|
896
|
+
}
|
|
897
|
+
var message = format(
|
|
898
|
+
'done() called multiple times in %s %s',
|
|
899
|
+
runnable.type ? runnable.type : 'unknown runnable',
|
|
900
|
+
title
|
|
901
|
+
);
|
|
902
|
+
if (runnable.file) {
|
|
903
|
+
message += format(' of file %s', runnable.file);
|
|
904
|
+
}
|
|
905
|
+
if (originalErr) {
|
|
906
|
+
message += format('; in addition, done() received error: %s', originalErr);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
var err = new Error(message);
|
|
910
|
+
err.code = constants.MULTIPLE_DONE;
|
|
911
|
+
err.valueType = typeof originalErr;
|
|
912
|
+
err.value = originalErr;
|
|
913
|
+
return err;
|
|
914
|
+
}
|
|
915
|
+
|
|
741
916
|
module.exports = {
|
|
742
917
|
createInvalidArgumentTypeError: createInvalidArgumentTypeError,
|
|
743
918
|
createInvalidArgumentValueError: createInvalidArgumentValueError,
|
|
@@ -746,10 +921,16 @@ module.exports = {
|
|
|
746
921
|
createInvalidReporterError: createInvalidReporterError,
|
|
747
922
|
createMissingArgumentError: createMissingArgumentError,
|
|
748
923
|
createNoFilesMatchPatternError: createNoFilesMatchPatternError,
|
|
749
|
-
createUnsupportedError: createUnsupportedError
|
|
924
|
+
createUnsupportedError: createUnsupportedError,
|
|
925
|
+
createInvalidPluginError: createInvalidPluginError,
|
|
926
|
+
createMochaInstanceAlreadyDisposedError: createMochaInstanceAlreadyDisposedError,
|
|
927
|
+
createMochaInstanceAlreadyRunningError: createMochaInstanceAlreadyRunningError,
|
|
928
|
+
createFatalError: createFatalError,
|
|
929
|
+
createMultipleDoneError: createMultipleDoneError,
|
|
930
|
+
constants: constants
|
|
750
931
|
};
|
|
751
932
|
|
|
752
|
-
},{}],7:[function(require,module,exports){
|
|
933
|
+
},{"util":89}],7:[function(require,module,exports){
|
|
753
934
|
'use strict';
|
|
754
935
|
|
|
755
936
|
var Runnable = require('./runnable');
|
|
@@ -779,6 +960,14 @@ function Hook(title, fn) {
|
|
|
779
960
|
*/
|
|
780
961
|
inherits(Hook, Runnable);
|
|
781
962
|
|
|
963
|
+
/**
|
|
964
|
+
* Resets the state for a next run.
|
|
965
|
+
*/
|
|
966
|
+
Hook.prototype.reset = function() {
|
|
967
|
+
Runnable.prototype.reset.call(this);
|
|
968
|
+
delete this._error;
|
|
969
|
+
};
|
|
970
|
+
|
|
782
971
|
/**
|
|
783
972
|
* Get or set the test `err`.
|
|
784
973
|
*
|
|
@@ -923,6 +1112,7 @@ module.exports.description = 'BDD or RSpec style [default]';
|
|
|
923
1112
|
var Suite = require('../suite');
|
|
924
1113
|
var errors = require('../errors');
|
|
925
1114
|
var createMissingArgumentError = errors.createMissingArgumentError;
|
|
1115
|
+
var createUnsupportedError = errors.createUnsupportedError;
|
|
926
1116
|
|
|
927
1117
|
/**
|
|
928
1118
|
* Functions common to more than one interface.
|
|
@@ -1046,14 +1236,14 @@ module.exports = function(suites, context, mocha) {
|
|
|
1046
1236
|
suites.unshift(suite);
|
|
1047
1237
|
if (opts.isOnly) {
|
|
1048
1238
|
if (mocha.options.forbidOnly && shouldBeTested(suite)) {
|
|
1049
|
-
throw
|
|
1239
|
+
throw createUnsupportedError('`.only` forbidden');
|
|
1050
1240
|
}
|
|
1051
1241
|
|
|
1052
1242
|
suite.parent.appendOnlySuite(suite);
|
|
1053
1243
|
}
|
|
1054
1244
|
if (suite.pending) {
|
|
1055
1245
|
if (mocha.options.forbidPending && shouldBeTested(suite)) {
|
|
1056
|
-
throw
|
|
1246
|
+
throw createUnsupportedError('Pending test forbidden');
|
|
1057
1247
|
}
|
|
1058
1248
|
}
|
|
1059
1249
|
if (typeof opts.fn === 'function') {
|
|
@@ -1085,7 +1275,9 @@ module.exports = function(suites, context, mocha) {
|
|
|
1085
1275
|
* @returns {*}
|
|
1086
1276
|
*/
|
|
1087
1277
|
only: function(mocha, test) {
|
|
1088
|
-
|
|
1278
|
+
if (mocha.options.forbidOnly)
|
|
1279
|
+
throw createUnsupportedError('`.only` forbidden');
|
|
1280
|
+
test.markOnly();
|
|
1089
1281
|
return test;
|
|
1090
1282
|
},
|
|
1091
1283
|
|
|
@@ -1408,9 +1600,14 @@ var utils = require('./utils');
|
|
|
1408
1600
|
var mocharc = require('./mocharc.json');
|
|
1409
1601
|
var errors = require('./errors');
|
|
1410
1602
|
var Suite = require('./suite');
|
|
1603
|
+
var esmUtils = utils.supportsEsModules() ? require('./esm-utils') : undefined;
|
|
1411
1604
|
var createStatsCollector = require('./stats-collector');
|
|
1412
1605
|
var createInvalidReporterError = errors.createInvalidReporterError;
|
|
1413
1606
|
var createInvalidInterfaceError = errors.createInvalidInterfaceError;
|
|
1607
|
+
var createMochaInstanceAlreadyDisposedError =
|
|
1608
|
+
errors.createMochaInstanceAlreadyDisposedError;
|
|
1609
|
+
var createMochaInstanceAlreadyRunningError =
|
|
1610
|
+
errors.createMochaInstanceAlreadyRunningError;
|
|
1414
1611
|
var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
|
|
1415
1612
|
var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
|
|
1416
1613
|
var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
|
|
@@ -1418,12 +1615,36 @@ var sQuote = utils.sQuote;
|
|
|
1418
1615
|
|
|
1419
1616
|
exports = module.exports = Mocha;
|
|
1420
1617
|
|
|
1618
|
+
/**
|
|
1619
|
+
* A Mocha instance is a finite state machine.
|
|
1620
|
+
* These are the states it can be in.
|
|
1621
|
+
*/
|
|
1622
|
+
var mochaStates = utils.defineConstants({
|
|
1623
|
+
/**
|
|
1624
|
+
* Initial state of the mocha instance
|
|
1625
|
+
*/
|
|
1626
|
+
INIT: 'init',
|
|
1627
|
+
/**
|
|
1628
|
+
* Mocha instance is running tests
|
|
1629
|
+
*/
|
|
1630
|
+
RUNNING: 'running',
|
|
1631
|
+
/**
|
|
1632
|
+
* Mocha instance is done running tests and references to test functions and hooks are cleaned.
|
|
1633
|
+
* You can reset this state by unloading the test files.
|
|
1634
|
+
*/
|
|
1635
|
+
REFERENCES_CLEANED: 'referencesCleaned',
|
|
1636
|
+
/**
|
|
1637
|
+
* Mocha instance is disposed and can no longer be used.
|
|
1638
|
+
*/
|
|
1639
|
+
DISPOSED: 'disposed'
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1421
1642
|
/**
|
|
1422
1643
|
* To require local UIs and reporters when running in node.
|
|
1423
1644
|
*/
|
|
1424
1645
|
|
|
1425
|
-
if (!process.browser) {
|
|
1426
|
-
var cwd =
|
|
1646
|
+
if (!process.browser && typeof module.paths !== 'undefined') {
|
|
1647
|
+
var cwd = utils.cwd();
|
|
1427
1648
|
module.paths.push(cwd, path.join(cwd, 'node_modules'));
|
|
1428
1649
|
}
|
|
1429
1650
|
|
|
@@ -1483,6 +1704,8 @@ exports.Test = require('./test');
|
|
|
1483
1704
|
* @param {number} [options.slow] - Slow threshold value.
|
|
1484
1705
|
* @param {number|string} [options.timeout] - Timeout threshold value.
|
|
1485
1706
|
* @param {string} [options.ui] - Interface name.
|
|
1707
|
+
* @param {MochaRootHookObject} [options.rootHooks] - Hooks to bootstrap the root
|
|
1708
|
+
* suite with
|
|
1486
1709
|
*/
|
|
1487
1710
|
function Mocha(options) {
|
|
1488
1711
|
options = utils.assign({}, mocharc, options || {});
|
|
@@ -1490,6 +1713,7 @@ function Mocha(options) {
|
|
|
1490
1713
|
this.options = options;
|
|
1491
1714
|
// root suite
|
|
1492
1715
|
this.suite = new exports.Suite('', new exports.Context(), true);
|
|
1716
|
+
this._cleanReferencesAfterRun = true;
|
|
1493
1717
|
|
|
1494
1718
|
this.grep(options.grep)
|
|
1495
1719
|
.fgrep(options.fgrep)
|
|
@@ -1529,6 +1753,10 @@ function Mocha(options) {
|
|
|
1529
1753
|
this[opt]();
|
|
1530
1754
|
}
|
|
1531
1755
|
}, this);
|
|
1756
|
+
|
|
1757
|
+
if (options.rootHooks) {
|
|
1758
|
+
this.rootHooks(options.rootHooks);
|
|
1759
|
+
}
|
|
1532
1760
|
}
|
|
1533
1761
|
|
|
1534
1762
|
/**
|
|
@@ -1595,24 +1823,24 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) {
|
|
|
1595
1823
|
_reporter = require(reporter);
|
|
1596
1824
|
} catch (err) {
|
|
1597
1825
|
if (
|
|
1598
|
-
err.code
|
|
1599
|
-
err.message.indexOf('Cannot find module')
|
|
1826
|
+
err.code === 'MODULE_NOT_FOUND' ||
|
|
1827
|
+
err.message.indexOf('Cannot find module') >= 0
|
|
1600
1828
|
) {
|
|
1601
1829
|
// Try to load reporters from a path (absolute or relative)
|
|
1602
1830
|
try {
|
|
1603
|
-
_reporter = require(path.resolve(
|
|
1831
|
+
_reporter = require(path.resolve(utils.cwd(), reporter));
|
|
1604
1832
|
} catch (_err) {
|
|
1605
|
-
_err.code
|
|
1606
|
-
_err.message.indexOf('Cannot find module')
|
|
1607
|
-
?
|
|
1608
|
-
:
|
|
1833
|
+
_err.code === 'MODULE_NOT_FOUND' ||
|
|
1834
|
+
_err.message.indexOf('Cannot find module') >= 0
|
|
1835
|
+
? utils.warn(sQuote(reporter) + ' reporter not found')
|
|
1836
|
+
: utils.warn(
|
|
1609
1837
|
sQuote(reporter) +
|
|
1610
1838
|
' reporter blew up with error:\n' +
|
|
1611
1839
|
err.stack
|
|
1612
1840
|
);
|
|
1613
1841
|
}
|
|
1614
1842
|
} else {
|
|
1615
|
-
|
|
1843
|
+
utils.warn(
|
|
1616
1844
|
sQuote(reporter) + ' reporter blew up with error:\n' + err.stack
|
|
1617
1845
|
);
|
|
1618
1846
|
}
|
|
@@ -1684,16 +1912,18 @@ Mocha.prototype.ui = function(ui) {
|
|
|
1684
1912
|
};
|
|
1685
1913
|
|
|
1686
1914
|
/**
|
|
1687
|
-
* Loads `files` prior to execution.
|
|
1915
|
+
* Loads `files` prior to execution. Does not support ES Modules.
|
|
1688
1916
|
*
|
|
1689
1917
|
* @description
|
|
1690
1918
|
* The implementation relies on Node's `require` to execute
|
|
1691
1919
|
* the test interface functions and will be subject to its cache.
|
|
1920
|
+
* Supports only CommonJS modules. To load ES modules, use Mocha#loadFilesAsync.
|
|
1692
1921
|
*
|
|
1693
1922
|
* @private
|
|
1694
1923
|
* @see {@link Mocha#addFile}
|
|
1695
1924
|
* @see {@link Mocha#run}
|
|
1696
1925
|
* @see {@link Mocha#unloadFiles}
|
|
1926
|
+
* @see {@link Mocha#loadFilesAsync}
|
|
1697
1927
|
* @param {Function} [fn] - Callback invoked upon completion.
|
|
1698
1928
|
*/
|
|
1699
1929
|
Mocha.prototype.loadFiles = function(fn) {
|
|
@@ -1708,6 +1938,49 @@ Mocha.prototype.loadFiles = function(fn) {
|
|
|
1708
1938
|
fn && fn();
|
|
1709
1939
|
};
|
|
1710
1940
|
|
|
1941
|
+
/**
|
|
1942
|
+
* Loads `files` prior to execution. Supports Node ES Modules.
|
|
1943
|
+
*
|
|
1944
|
+
* @description
|
|
1945
|
+
* The implementation relies on Node's `require` and `import` to execute
|
|
1946
|
+
* the test interface functions and will be subject to its cache.
|
|
1947
|
+
* Supports both CJS and ESM modules.
|
|
1948
|
+
*
|
|
1949
|
+
* @public
|
|
1950
|
+
* @see {@link Mocha#addFile}
|
|
1951
|
+
* @see {@link Mocha#run}
|
|
1952
|
+
* @see {@link Mocha#unloadFiles}
|
|
1953
|
+
* @returns {Promise}
|
|
1954
|
+
* @example
|
|
1955
|
+
*
|
|
1956
|
+
* // loads ESM (and CJS) test files asynchronously, then runs root suite
|
|
1957
|
+
* mocha.loadFilesAsync()
|
|
1958
|
+
* .then(() => mocha.run(failures => process.exitCode = failures ? 1 : 0))
|
|
1959
|
+
* .catch(() => process.exitCode = 1);
|
|
1960
|
+
*/
|
|
1961
|
+
Mocha.prototype.loadFilesAsync = function() {
|
|
1962
|
+
var self = this;
|
|
1963
|
+
var suite = this.suite;
|
|
1964
|
+
this.loadAsync = true;
|
|
1965
|
+
|
|
1966
|
+
if (!esmUtils) {
|
|
1967
|
+
return new Promise(function(resolve) {
|
|
1968
|
+
self.loadFiles(resolve);
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
return esmUtils.loadFilesAsync(
|
|
1973
|
+
this.files,
|
|
1974
|
+
function(file) {
|
|
1975
|
+
suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
|
|
1976
|
+
},
|
|
1977
|
+
function(file, resultModule) {
|
|
1978
|
+
suite.emit(EVENT_FILE_REQUIRE, resultModule, file, self);
|
|
1979
|
+
suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
|
|
1980
|
+
}
|
|
1981
|
+
);
|
|
1982
|
+
};
|
|
1983
|
+
|
|
1711
1984
|
/**
|
|
1712
1985
|
* Removes a previously loaded file from Node's `require` cache.
|
|
1713
1986
|
*
|
|
@@ -1724,8 +1997,9 @@ Mocha.unloadFile = function(file) {
|
|
|
1724
1997
|
* Unloads `files` from Node's `require` cache.
|
|
1725
1998
|
*
|
|
1726
1999
|
* @description
|
|
1727
|
-
* This allows files to be "freshly" reloaded, providing the ability
|
|
2000
|
+
* This allows required files to be "freshly" reloaded, providing the ability
|
|
1728
2001
|
* to reuse a Mocha instance programmatically.
|
|
2002
|
+
* Note: does not clear ESM module files from the cache
|
|
1729
2003
|
*
|
|
1730
2004
|
* <strong>Intended for consumers — not used internally</strong>
|
|
1731
2005
|
*
|
|
@@ -1735,7 +2009,18 @@ Mocha.unloadFile = function(file) {
|
|
|
1735
2009
|
* @chainable
|
|
1736
2010
|
*/
|
|
1737
2011
|
Mocha.prototype.unloadFiles = function() {
|
|
1738
|
-
this.
|
|
2012
|
+
if (this._state === mochaStates.DISPOSED) {
|
|
2013
|
+
throw createMochaInstanceAlreadyDisposedError(
|
|
2014
|
+
'Mocha instance is already disposed, it cannot be used again.',
|
|
2015
|
+
this._cleanReferencesAfterRun,
|
|
2016
|
+
this
|
|
2017
|
+
);
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
this.files.forEach(function(file) {
|
|
2021
|
+
Mocha.unloadFile(file);
|
|
2022
|
+
});
|
|
2023
|
+
this._state = mochaStates.INIT;
|
|
1739
2024
|
return this;
|
|
1740
2025
|
};
|
|
1741
2026
|
|
|
@@ -1853,6 +2138,38 @@ Mocha.prototype.checkLeaks = function(checkLeaks) {
|
|
|
1853
2138
|
return this;
|
|
1854
2139
|
};
|
|
1855
2140
|
|
|
2141
|
+
/**
|
|
2142
|
+
* Enables or disables whether or not to dispose after each test run.
|
|
2143
|
+
* Disable this to ensure you can run the test suite multiple times.
|
|
2144
|
+
* If disabled, be sure to dispose mocha when you're done to prevent memory leaks.
|
|
2145
|
+
* @public
|
|
2146
|
+
* @see {@link Mocha#dispose}
|
|
2147
|
+
* @param {boolean} cleanReferencesAfterRun
|
|
2148
|
+
* @return {Mocha} this
|
|
2149
|
+
* @chainable
|
|
2150
|
+
*/
|
|
2151
|
+
Mocha.prototype.cleanReferencesAfterRun = function(cleanReferencesAfterRun) {
|
|
2152
|
+
this._cleanReferencesAfterRun = cleanReferencesAfterRun !== false;
|
|
2153
|
+
return this;
|
|
2154
|
+
};
|
|
2155
|
+
|
|
2156
|
+
/**
|
|
2157
|
+
* Manually dispose this mocha instance. Mark this instance as `disposed` and unable to run more tests.
|
|
2158
|
+
* It also removes function references to tests functions and hooks, so variables trapped in closures can be cleaned by the garbage collector.
|
|
2159
|
+
* @public
|
|
2160
|
+
*/
|
|
2161
|
+
Mocha.prototype.dispose = function() {
|
|
2162
|
+
if (this._state === mochaStates.RUNNING) {
|
|
2163
|
+
throw createMochaInstanceAlreadyRunningError(
|
|
2164
|
+
'Cannot dispose while the mocha instance is still running tests.'
|
|
2165
|
+
);
|
|
2166
|
+
}
|
|
2167
|
+
this.unloadFiles();
|
|
2168
|
+
this._previousRunner && this._previousRunner.dispose();
|
|
2169
|
+
this.suite.dispose();
|
|
2170
|
+
this._state = mochaStates.DISPOSED;
|
|
2171
|
+
};
|
|
2172
|
+
|
|
1856
2173
|
/**
|
|
1857
2174
|
* Displays full stack trace upon test failure.
|
|
1858
2175
|
*
|
|
@@ -2203,6 +2520,28 @@ Mocha.prototype.forbidPending = function(forbidPending) {
|
|
|
2203
2520
|
return this;
|
|
2204
2521
|
};
|
|
2205
2522
|
|
|
2523
|
+
/**
|
|
2524
|
+
* Throws an error if mocha is in the wrong state to be able to transition to a "running" state.
|
|
2525
|
+
*/
|
|
2526
|
+
Mocha.prototype._guardRunningStateTransition = function() {
|
|
2527
|
+
if (this._state === mochaStates.RUNNING) {
|
|
2528
|
+
throw createMochaInstanceAlreadyRunningError(
|
|
2529
|
+
'Mocha instance is currently running tests, cannot start a next test run until this one is done',
|
|
2530
|
+
this
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
if (
|
|
2534
|
+
this._state === mochaStates.DISPOSED ||
|
|
2535
|
+
this._state === mochaStates.REFERENCES_CLEANED
|
|
2536
|
+
) {
|
|
2537
|
+
throw createMochaInstanceAlreadyDisposedError(
|
|
2538
|
+
'Mocha instance is already disposed, cannot start a new test run. Please create a new mocha instance. Be sure to set disable `cleanReferencesAfterRun` when you want to reuse the same mocha instance for multiple test runs.',
|
|
2539
|
+
this._cleanReferencesAfterRun,
|
|
2540
|
+
this
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
};
|
|
2544
|
+
|
|
2206
2545
|
/**
|
|
2207
2546
|
* Mocha version as specified by "package.json".
|
|
2208
2547
|
*
|
|
@@ -2236,16 +2575,30 @@ Object.defineProperty(Mocha.prototype, 'version', {
|
|
|
2236
2575
|
* @see {@link Mocha#unloadFiles}
|
|
2237
2576
|
* @see {@link Runner#run}
|
|
2238
2577
|
* @param {DoneCB} [fn] - Callback invoked when test execution completed.
|
|
2239
|
-
* @
|
|
2578
|
+
* @returns {Runner} runner instance
|
|
2579
|
+
* @example
|
|
2580
|
+
*
|
|
2581
|
+
* // exit with non-zero status if there were test failures
|
|
2582
|
+
* mocha.run(failures => process.exitCode = failures ? 1 : 0);
|
|
2240
2583
|
*/
|
|
2241
2584
|
Mocha.prototype.run = function(fn) {
|
|
2242
|
-
|
|
2585
|
+
this._guardRunningStateTransition();
|
|
2586
|
+
this._state = mochaStates.RUNNING;
|
|
2587
|
+
if (this._previousRunner) {
|
|
2588
|
+
this._previousRunner.dispose();
|
|
2589
|
+
this.suite.reset();
|
|
2590
|
+
}
|
|
2591
|
+
if (this.files.length && !this.loadAsync) {
|
|
2243
2592
|
this.loadFiles();
|
|
2244
2593
|
}
|
|
2594
|
+
var self = this;
|
|
2245
2595
|
var suite = this.suite;
|
|
2246
2596
|
var options = this.options;
|
|
2247
2597
|
options.files = this.files;
|
|
2248
|
-
var runner = new exports.Runner(suite,
|
|
2598
|
+
var runner = new exports.Runner(suite, {
|
|
2599
|
+
delay: options.delay,
|
|
2600
|
+
cleanReferencesAfterRun: this._cleanReferencesAfterRun
|
|
2601
|
+
});
|
|
2249
2602
|
createStatsCollector(runner);
|
|
2250
2603
|
var reporter = new this._reporter(runner, options);
|
|
2251
2604
|
runner.checkLeaks = options.checkLeaks === true;
|
|
@@ -2270,6 +2623,12 @@ Mocha.prototype.run = function(fn) {
|
|
|
2270
2623
|
exports.reporters.Base.hideDiff = !options.diff;
|
|
2271
2624
|
|
|
2272
2625
|
function done(failures) {
|
|
2626
|
+
self._previousRunner = runner;
|
|
2627
|
+
if (self._cleanReferencesAfterRun) {
|
|
2628
|
+
self._state = mochaStates.REFERENCES_CLEANED;
|
|
2629
|
+
} else {
|
|
2630
|
+
self._state = mochaStates.INIT;
|
|
2631
|
+
}
|
|
2273
2632
|
fn = fn || utils.noop;
|
|
2274
2633
|
if (reporter.done) {
|
|
2275
2634
|
reporter.done(failures, fn);
|
|
@@ -2281,11 +2640,54 @@ Mocha.prototype.run = function(fn) {
|
|
|
2281
2640
|
return runner.run(done);
|
|
2282
2641
|
};
|
|
2283
2642
|
|
|
2643
|
+
/**
|
|
2644
|
+
* Assigns hooks to the root suite
|
|
2645
|
+
* @param {MochaRootHookObject} [hooks] - Hooks to assign to root suite
|
|
2646
|
+
* @chainable
|
|
2647
|
+
*/
|
|
2648
|
+
Mocha.prototype.rootHooks = function rootHooks(hooks) {
|
|
2649
|
+
if (utils.type(hooks) === 'object') {
|
|
2650
|
+
var beforeAll = [].concat(hooks.beforeAll || []);
|
|
2651
|
+
var beforeEach = [].concat(hooks.beforeEach || []);
|
|
2652
|
+
var afterAll = [].concat(hooks.afterAll || []);
|
|
2653
|
+
var afterEach = [].concat(hooks.afterEach || []);
|
|
2654
|
+
var rootSuite = this.suite;
|
|
2655
|
+
beforeAll.forEach(function(hook) {
|
|
2656
|
+
rootSuite.beforeAll(hook);
|
|
2657
|
+
});
|
|
2658
|
+
beforeEach.forEach(function(hook) {
|
|
2659
|
+
rootSuite.beforeEach(hook);
|
|
2660
|
+
});
|
|
2661
|
+
afterAll.forEach(function(hook) {
|
|
2662
|
+
rootSuite.afterAll(hook);
|
|
2663
|
+
});
|
|
2664
|
+
afterEach.forEach(function(hook) {
|
|
2665
|
+
rootSuite.afterEach(hook);
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
return this;
|
|
2669
|
+
};
|
|
2670
|
+
|
|
2671
|
+
/**
|
|
2672
|
+
* An alternative way to define root hooks that works with parallel runs.
|
|
2673
|
+
* @typedef {Object} MochaRootHookObject
|
|
2674
|
+
* @property {Function|Function[]} [beforeAll] - "Before all" hook(s)
|
|
2675
|
+
* @property {Function|Function[]} [beforeEach] - "Before each" hook(s)
|
|
2676
|
+
* @property {Function|Function[]} [afterAll] - "After all" hook(s)
|
|
2677
|
+
* @property {Function|Function[]} [afterEach] - "After each" hook(s)
|
|
2678
|
+
*/
|
|
2679
|
+
|
|
2680
|
+
/**
|
|
2681
|
+
* An function that returns a {@link MochaRootHookObject}, either sync or async.
|
|
2682
|
+
* @callback MochaRootHookFunction
|
|
2683
|
+
* @returns {MochaRootHookObject|Promise<MochaRootHookObject>}
|
|
2684
|
+
*/
|
|
2685
|
+
|
|
2284
2686
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
2285
|
-
},{"../package.json":90,"./context":5,"./errors":6,"./growl":2,"./hook":7,"./interfaces":11,"./mocharc.json":15,"./reporters":21,"./runnable":33,"./runner":34,"./stats-collector":35,"./suite":36,"./test":37,"./utils":38,"_process":69,"escape-string-regexp":49,"path":42}],15:[function(require,module,exports){
|
|
2687
|
+
},{"../package.json":90,"./context":5,"./errors":6,"./esm-utils":42,"./growl":2,"./hook":7,"./interfaces":11,"./mocharc.json":15,"./reporters":21,"./runnable":33,"./runner":34,"./stats-collector":35,"./suite":36,"./test":37,"./utils":38,"_process":69,"escape-string-regexp":49,"path":42}],15:[function(require,module,exports){
|
|
2286
2688
|
module.exports={
|
|
2287
2689
|
"diff": true,
|
|
2288
|
-
"extension": ["js"],
|
|
2690
|
+
"extension": ["js", "cjs", "mjs"],
|
|
2289
2691
|
"opts": "./test/mocha.opts",
|
|
2290
2692
|
"package": "./package.json",
|
|
2291
2693
|
"reporter": "spec",
|
|
@@ -2901,6 +3303,7 @@ function Doc(runner, options) {
|
|
|
2901
3303
|
|
|
2902
3304
|
runner.on(EVENT_TEST_PASS, function(test) {
|
|
2903
3305
|
Base.consoleLog('%s <dt>%s</dt>', indent(), utils.escape(test.title));
|
|
3306
|
+
Base.consoleLog('%s <dt>%s</dt>', indent(), utils.escape(test.file));
|
|
2904
3307
|
var code = utils.escape(utils.clean(test.body));
|
|
2905
3308
|
Base.consoleLog('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
|
|
2906
3309
|
});
|
|
@@ -2911,6 +3314,11 @@ function Doc(runner, options) {
|
|
|
2911
3314
|
indent(),
|
|
2912
3315
|
utils.escape(test.title)
|
|
2913
3316
|
);
|
|
3317
|
+
Base.consoleLog(
|
|
3318
|
+
'%s <dt class="error">%s</dt>',
|
|
3319
|
+
indent(),
|
|
3320
|
+
utils.escape(test.file)
|
|
3321
|
+
);
|
|
2914
3322
|
var code = utils.escape(utils.clean(test.body));
|
|
2915
3323
|
Base.consoleLog(
|
|
2916
3324
|
'%s <dd class="error"><pre><code>%s</code></pre></dd>',
|
|
@@ -3513,6 +3921,7 @@ function clean(test) {
|
|
|
3513
3921
|
return {
|
|
3514
3922
|
title: test.title,
|
|
3515
3923
|
fullTitle: test.fullTitle(),
|
|
3924
|
+
file: test.file,
|
|
3516
3925
|
duration: test.duration,
|
|
3517
3926
|
currentRetry: test.currentRetry()
|
|
3518
3927
|
};
|
|
@@ -3612,6 +4021,7 @@ function clean(test) {
|
|
|
3612
4021
|
return {
|
|
3613
4022
|
title: test.title,
|
|
3614
4023
|
fullTitle: test.fullTitle(),
|
|
4024
|
+
file: test.file,
|
|
3615
4025
|
duration: test.duration,
|
|
3616
4026
|
currentRetry: test.currentRetry(),
|
|
3617
4027
|
err: cleanCycles(err)
|
|
@@ -3762,6 +4172,14 @@ function Landing(runner, options) {
|
|
|
3762
4172
|
process.stdout.write('\n');
|
|
3763
4173
|
self.epilogue();
|
|
3764
4174
|
});
|
|
4175
|
+
|
|
4176
|
+
// if cursor is hidden when we ctrl-C, then it will remain hidden unless...
|
|
4177
|
+
process.once('SIGINT', function() {
|
|
4178
|
+
cursor.show();
|
|
4179
|
+
process.nextTick(function() {
|
|
4180
|
+
process.kill(process.pid, 'SIGINT');
|
|
4181
|
+
});
|
|
4182
|
+
});
|
|
3765
4183
|
}
|
|
3766
4184
|
|
|
3767
4185
|
/**
|
|
@@ -5042,8 +5460,9 @@ var Pending = require('./pending');
|
|
|
5042
5460
|
var debug = require('debug')('mocha:runnable');
|
|
5043
5461
|
var milliseconds = require('ms');
|
|
5044
5462
|
var utils = require('./utils');
|
|
5045
|
-
var
|
|
5046
|
-
|
|
5463
|
+
var errors = require('./errors');
|
|
5464
|
+
var createInvalidExceptionError = errors.createInvalidExceptionError;
|
|
5465
|
+
var createMultipleDoneError = errors.createMultipleDoneError;
|
|
5047
5466
|
|
|
5048
5467
|
/**
|
|
5049
5468
|
* Save timer references to avoid Sinon interfering (see GH-237).
|
|
@@ -5073,10 +5492,8 @@ function Runnable(title, fn) {
|
|
|
5073
5492
|
this._timeout = 2000;
|
|
5074
5493
|
this._slow = 75;
|
|
5075
5494
|
this._enableTimeouts = true;
|
|
5076
|
-
this.timedOut = false;
|
|
5077
5495
|
this._retries = -1;
|
|
5078
|
-
this.
|
|
5079
|
-
this.pending = false;
|
|
5496
|
+
this.reset();
|
|
5080
5497
|
}
|
|
5081
5498
|
|
|
5082
5499
|
/**
|
|
@@ -5084,6 +5501,17 @@ function Runnable(title, fn) {
|
|
|
5084
5501
|
*/
|
|
5085
5502
|
utils.inherits(Runnable, EventEmitter);
|
|
5086
5503
|
|
|
5504
|
+
/**
|
|
5505
|
+
* Resets the state initially or for a next run.
|
|
5506
|
+
*/
|
|
5507
|
+
Runnable.prototype.reset = function() {
|
|
5508
|
+
this.timedOut = false;
|
|
5509
|
+
this._currentRetry = 0;
|
|
5510
|
+
this.pending = false;
|
|
5511
|
+
delete this.state;
|
|
5512
|
+
delete this.err;
|
|
5513
|
+
};
|
|
5514
|
+
|
|
5087
5515
|
/**
|
|
5088
5516
|
* Get current timeout value in msecs.
|
|
5089
5517
|
*
|
|
@@ -5259,31 +5687,6 @@ Runnable.prototype.clearTimeout = function() {
|
|
|
5259
5687
|
clearTimeout(this.timer);
|
|
5260
5688
|
};
|
|
5261
5689
|
|
|
5262
|
-
/**
|
|
5263
|
-
* Inspect the runnable void of private properties.
|
|
5264
|
-
*
|
|
5265
|
-
* @private
|
|
5266
|
-
* @return {string}
|
|
5267
|
-
*/
|
|
5268
|
-
Runnable.prototype.inspect = function() {
|
|
5269
|
-
return JSON.stringify(
|
|
5270
|
-
this,
|
|
5271
|
-
function(key, val) {
|
|
5272
|
-
if (key[0] === '_') {
|
|
5273
|
-
return;
|
|
5274
|
-
}
|
|
5275
|
-
if (key === 'parent') {
|
|
5276
|
-
return '#<Suite>';
|
|
5277
|
-
}
|
|
5278
|
-
if (key === 'ctx') {
|
|
5279
|
-
return '#<Context>';
|
|
5280
|
-
}
|
|
5281
|
-
return val;
|
|
5282
|
-
},
|
|
5283
|
-
2
|
|
5284
|
-
);
|
|
5285
|
-
};
|
|
5286
|
-
|
|
5287
5690
|
/**
|
|
5288
5691
|
* Reset the timeout.
|
|
5289
5692
|
*
|
|
@@ -5330,7 +5733,7 @@ Runnable.prototype.run = function(fn) {
|
|
|
5330
5733
|
var start = new Date();
|
|
5331
5734
|
var ctx = this.ctx;
|
|
5332
5735
|
var finished;
|
|
5333
|
-
var
|
|
5736
|
+
var errorWasHandled = false;
|
|
5334
5737
|
|
|
5335
5738
|
// Sometimes the ctx exists, but it is not runnable
|
|
5336
5739
|
if (ctx && ctx.runnable) {
|
|
@@ -5339,17 +5742,11 @@ Runnable.prototype.run = function(fn) {
|
|
|
5339
5742
|
|
|
5340
5743
|
// called multiple times
|
|
5341
5744
|
function multiple(err) {
|
|
5342
|
-
if (
|
|
5745
|
+
if (errorWasHandled) {
|
|
5343
5746
|
return;
|
|
5344
5747
|
}
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
if (err && err.message) {
|
|
5348
|
-
err.message += " (and Mocha's " + msg + ')';
|
|
5349
|
-
self.emit('error', err);
|
|
5350
|
-
} else {
|
|
5351
|
-
self.emit('error', new Error(msg));
|
|
5352
|
-
}
|
|
5748
|
+
errorWasHandled = true;
|
|
5749
|
+
self.emit('error', createMultipleDoneError(self, err));
|
|
5353
5750
|
}
|
|
5354
5751
|
|
|
5355
5752
|
// finished
|
|
@@ -5400,7 +5797,7 @@ Runnable.prototype.run = function(fn) {
|
|
|
5400
5797
|
callFnAsync(this.fn);
|
|
5401
5798
|
} catch (err) {
|
|
5402
5799
|
// handles async runnables which actually run synchronously
|
|
5403
|
-
|
|
5800
|
+
errorWasHandled = true;
|
|
5404
5801
|
if (err instanceof Pending) {
|
|
5405
5802
|
return; // done() is already called in this.skip()
|
|
5406
5803
|
} else if (this.allowUncaught) {
|
|
@@ -5419,7 +5816,7 @@ Runnable.prototype.run = function(fn) {
|
|
|
5419
5816
|
callFn(this.fn);
|
|
5420
5817
|
}
|
|
5421
5818
|
} catch (err) {
|
|
5422
|
-
|
|
5819
|
+
errorWasHandled = true;
|
|
5423
5820
|
if (err instanceof Pending) {
|
|
5424
5821
|
return done();
|
|
5425
5822
|
} else if (this.allowUncaught) {
|
|
@@ -5564,7 +5961,6 @@ var EVENT_ROOT_SUITE_RUN = Suite.constants.EVENT_ROOT_SUITE_RUN;
|
|
|
5564
5961
|
var STATE_FAILED = Runnable.constants.STATE_FAILED;
|
|
5565
5962
|
var STATE_PASSED = Runnable.constants.STATE_PASSED;
|
|
5566
5963
|
var dQuote = utils.dQuote;
|
|
5567
|
-
var ngettext = utils.ngettext;
|
|
5568
5964
|
var sQuote = utils.sQuote;
|
|
5569
5965
|
var stackFilter = utils.stackTraceFilter();
|
|
5570
5966
|
var stringify = utils.stringify;
|
|
@@ -5572,6 +5968,7 @@ var type = utils.type;
|
|
|
5572
5968
|
var errors = require('./errors');
|
|
5573
5969
|
var createInvalidExceptionError = errors.createInvalidExceptionError;
|
|
5574
5970
|
var createUnsupportedError = errors.createUnsupportedError;
|
|
5971
|
+
var createFatalError = errors.createFatalError;
|
|
5575
5972
|
|
|
5576
5973
|
/**
|
|
5577
5974
|
* Non-enumerable globals.
|
|
@@ -5654,7 +6051,19 @@ var constants = utils.defineConstants(
|
|
|
5654
6051
|
/**
|
|
5655
6052
|
* Emitted when {@link Test} execution has failed, but will retry
|
|
5656
6053
|
*/
|
|
5657
|
-
EVENT_TEST_RETRY: 'retry'
|
|
6054
|
+
EVENT_TEST_RETRY: 'retry',
|
|
6055
|
+
/**
|
|
6056
|
+
* Initial state of Runner
|
|
6057
|
+
*/
|
|
6058
|
+
STATE_IDLE: 'idle',
|
|
6059
|
+
/**
|
|
6060
|
+
* State set to this value when the Runner has started running
|
|
6061
|
+
*/
|
|
6062
|
+
STATE_RUNNING: 'running',
|
|
6063
|
+
/**
|
|
6064
|
+
* State set to this value when the Runner has stopped
|
|
6065
|
+
*/
|
|
6066
|
+
STATE_STOPPED: 'stopped'
|
|
5658
6067
|
}
|
|
5659
6068
|
);
|
|
5660
6069
|
|
|
@@ -5666,20 +6075,36 @@ module.exports = Runner;
|
|
|
5666
6075
|
* @extends external:EventEmitter
|
|
5667
6076
|
* @public
|
|
5668
6077
|
* @class
|
|
5669
|
-
* @param {Suite} suite Root suite
|
|
5670
|
-
* @param {boolean} [
|
|
5671
|
-
* until ready.
|
|
5672
|
-
|
|
5673
|
-
|
|
6078
|
+
* @param {Suite} suite - Root suite
|
|
6079
|
+
* @param {Object|boolean} [opts] - Options. If `boolean`, whether or not to delay execution of root suite until ready (for backwards compatibility).
|
|
6080
|
+
* @param {boolean} [opts.delay] - Whether to delay execution of root suite until ready.
|
|
6081
|
+
* @param {boolean} [opts.cleanReferencesAfterRun] - Whether to clean references to test fns and hooks when a suite is done.
|
|
6082
|
+
*/
|
|
6083
|
+
function Runner(suite, opts) {
|
|
6084
|
+
if (opts === undefined) {
|
|
6085
|
+
opts = {};
|
|
6086
|
+
}
|
|
6087
|
+
if (typeof opts === 'boolean') {
|
|
6088
|
+
this._delay = opts;
|
|
6089
|
+
opts = {};
|
|
6090
|
+
} else {
|
|
6091
|
+
this._delay = opts.delay;
|
|
6092
|
+
}
|
|
5674
6093
|
var self = this;
|
|
5675
6094
|
this._globals = [];
|
|
5676
6095
|
this._abort = false;
|
|
5677
|
-
this._delay = delay;
|
|
5678
6096
|
this.suite = suite;
|
|
5679
|
-
this.
|
|
6097
|
+
this._opts = opts;
|
|
6098
|
+
this.state = constants.STATE_IDLE;
|
|
5680
6099
|
this.total = suite.total();
|
|
5681
6100
|
this.failures = 0;
|
|
6101
|
+
this._eventListeners = [];
|
|
5682
6102
|
this.on(constants.EVENT_TEST_END, function(test) {
|
|
6103
|
+
if (test.type === 'test' && test.retriedTest() && test.parent) {
|
|
6104
|
+
var idx =
|
|
6105
|
+
test.parent.tests && test.parent.tests.indexOf(test.retriedTest());
|
|
6106
|
+
if (idx > -1) test.parent.tests[idx] = test;
|
|
6107
|
+
}
|
|
5683
6108
|
self.checkGlobals(test);
|
|
5684
6109
|
});
|
|
5685
6110
|
this.on(constants.EVENT_HOOK_END, function(hook) {
|
|
@@ -5688,6 +6113,8 @@ function Runner(suite, delay) {
|
|
|
5688
6113
|
this._defaultGrep = /.*/;
|
|
5689
6114
|
this.grep(this._defaultGrep);
|
|
5690
6115
|
this.globals(this.globalProps());
|
|
6116
|
+
|
|
6117
|
+
this.uncaught = this._uncaught.bind(this);
|
|
5691
6118
|
}
|
|
5692
6119
|
|
|
5693
6120
|
/**
|
|
@@ -5703,6 +6130,56 @@ Runner.immediately = global.setImmediate || process.nextTick;
|
|
|
5703
6130
|
*/
|
|
5704
6131
|
inherits(Runner, EventEmitter);
|
|
5705
6132
|
|
|
6133
|
+
/**
|
|
6134
|
+
* Replacement for `target.on(eventName, listener)` that does bookkeeping to remove them when this runner instance is disposed.
|
|
6135
|
+
* @param {EventEmitter} target - The `EventEmitter`
|
|
6136
|
+
* @param {string} eventName - The event name
|
|
6137
|
+
* @param {string} fn - Listener function
|
|
6138
|
+
*/
|
|
6139
|
+
Runner.prototype._addEventListener = function(target, eventName, listener) {
|
|
6140
|
+
target.on(eventName, listener);
|
|
6141
|
+
this._eventListeners.push([target, eventName, listener]);
|
|
6142
|
+
};
|
|
6143
|
+
|
|
6144
|
+
/**
|
|
6145
|
+
* Replacement for `target.removeListener(eventName, listener)` that also updates the bookkeeping.
|
|
6146
|
+
* @param {EventEmitter} target - The `EventEmitter`
|
|
6147
|
+
* @param {string} eventName - The event anme
|
|
6148
|
+
* @param {function} listener - Listener function
|
|
6149
|
+
*/
|
|
6150
|
+
Runner.prototype._removeEventListener = function(target, eventName, listener) {
|
|
6151
|
+
var eventListenerIndex = -1;
|
|
6152
|
+
for (var i = 0; i < this._eventListeners.length; i++) {
|
|
6153
|
+
var eventListenerDescriptor = this._eventListeners[i];
|
|
6154
|
+
if (
|
|
6155
|
+
eventListenerDescriptor[0] === target &&
|
|
6156
|
+
eventListenerDescriptor[1] === eventName &&
|
|
6157
|
+
eventListenerDescriptor[2] === listener
|
|
6158
|
+
) {
|
|
6159
|
+
eventListenerIndex = i;
|
|
6160
|
+
break;
|
|
6161
|
+
}
|
|
6162
|
+
}
|
|
6163
|
+
if (eventListenerIndex !== -1) {
|
|
6164
|
+
var removedListener = this._eventListeners.splice(eventListenerIndex, 1)[0];
|
|
6165
|
+
removedListener[0].removeListener(removedListener[1], removedListener[2]);
|
|
6166
|
+
}
|
|
6167
|
+
};
|
|
6168
|
+
|
|
6169
|
+
/**
|
|
6170
|
+
* Removes all event handlers set during a run on this instance.
|
|
6171
|
+
* Remark: this does _not_ clean/dispose the tests or suites themselves.
|
|
6172
|
+
*/
|
|
6173
|
+
Runner.prototype.dispose = function() {
|
|
6174
|
+
this.removeAllListeners();
|
|
6175
|
+
this._eventListeners.forEach(function(eventListenerDescriptor) {
|
|
6176
|
+
eventListenerDescriptor[0].removeListener(
|
|
6177
|
+
eventListenerDescriptor[1],
|
|
6178
|
+
eventListenerDescriptor[2]
|
|
6179
|
+
);
|
|
6180
|
+
});
|
|
6181
|
+
};
|
|
6182
|
+
|
|
5706
6183
|
/**
|
|
5707
6184
|
* Run tests with full titles matching `re`. Updates runner.total
|
|
5708
6185
|
* with number of tests matched.
|
|
@@ -5714,7 +6191,7 @@ inherits(Runner, EventEmitter);
|
|
|
5714
6191
|
* @return {Runner} Runner instance.
|
|
5715
6192
|
*/
|
|
5716
6193
|
Runner.prototype.grep = function(re, invert) {
|
|
5717
|
-
debug('grep %s', re);
|
|
6194
|
+
debug('grep(): setting to %s', re);
|
|
5718
6195
|
this._grep = re;
|
|
5719
6196
|
this._invert = invert;
|
|
5720
6197
|
this.total = this.grepTotal(this.suite);
|
|
@@ -5779,7 +6256,7 @@ Runner.prototype.globals = function(arr) {
|
|
|
5779
6256
|
if (!arguments.length) {
|
|
5780
6257
|
return this._globals;
|
|
5781
6258
|
}
|
|
5782
|
-
debug('globals %
|
|
6259
|
+
debug('globals(): setting to %O', arr);
|
|
5783
6260
|
this._globals = this._globals.concat(arr);
|
|
5784
6261
|
return this;
|
|
5785
6262
|
};
|
|
@@ -5811,12 +6288,8 @@ Runner.prototype.checkGlobals = function(test) {
|
|
|
5811
6288
|
this._globals = this._globals.concat(leaks);
|
|
5812
6289
|
|
|
5813
6290
|
if (leaks.length) {
|
|
5814
|
-
var
|
|
5815
|
-
|
|
5816
|
-
'global leak detected: %s',
|
|
5817
|
-
'global leaks detected: %s'
|
|
5818
|
-
);
|
|
5819
|
-
var error = new Error(util.format(format, leaks.map(sQuote).join(', ')));
|
|
6291
|
+
var msg = 'global leak(s) detected: %s';
|
|
6292
|
+
var error = new Error(util.format(msg, leaks.map(sQuote).join(', ')));
|
|
5820
6293
|
this.fail(test, error);
|
|
5821
6294
|
}
|
|
5822
6295
|
};
|
|
@@ -5832,8 +6305,18 @@ Runner.prototype.fail = function(test, err) {
|
|
|
5832
6305
|
if (test.isPending()) {
|
|
5833
6306
|
return;
|
|
5834
6307
|
}
|
|
6308
|
+
if (this.state === constants.STATE_STOPPED) {
|
|
6309
|
+
if (err.code === errors.constants.MULTIPLE_DONE) {
|
|
6310
|
+
throw err;
|
|
6311
|
+
}
|
|
6312
|
+
throw createFatalError(
|
|
6313
|
+
'Test failed after root suite execution completed!',
|
|
6314
|
+
err
|
|
6315
|
+
);
|
|
6316
|
+
}
|
|
5835
6317
|
|
|
5836
6318
|
++this.failures;
|
|
6319
|
+
debug('total number of failures: %d', this.failures);
|
|
5837
6320
|
test.state = STATE_FAILED;
|
|
5838
6321
|
|
|
5839
6322
|
if (!isError(err)) {
|
|
@@ -5921,7 +6404,7 @@ Runner.prototype.hook = function(name, fn) {
|
|
|
5921
6404
|
self.emit(constants.EVENT_HOOK_BEGIN, hook);
|
|
5922
6405
|
|
|
5923
6406
|
if (!hook.listeners('error').length) {
|
|
5924
|
-
|
|
6407
|
+
self._addEventListener(hook, 'error', function(err) {
|
|
5925
6408
|
self.failHook(hook, err);
|
|
5926
6409
|
});
|
|
5927
6410
|
}
|
|
@@ -6064,18 +6547,10 @@ Runner.prototype.runTest = function(fn) {
|
|
|
6064
6547
|
return;
|
|
6065
6548
|
}
|
|
6066
6549
|
|
|
6067
|
-
var suite = this.parents().reverse()[0] || this.suite;
|
|
6068
|
-
if (this.forbidOnly && suite.hasOnly()) {
|
|
6069
|
-
fn(new Error('`.only` forbidden'));
|
|
6070
|
-
return;
|
|
6071
|
-
}
|
|
6072
6550
|
if (this.asyncOnly) {
|
|
6073
6551
|
test.asyncOnly = true;
|
|
6074
6552
|
}
|
|
6075
|
-
|
|
6076
|
-
if (err instanceof Pending) {
|
|
6077
|
-
return;
|
|
6078
|
-
}
|
|
6553
|
+
this._addEventListener(test, 'error', function(err) {
|
|
6079
6554
|
self.fail(test, err);
|
|
6080
6555
|
});
|
|
6081
6556
|
if (this.allowUncaught) {
|
|
@@ -6270,9 +6745,10 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
6270
6745
|
var self = this;
|
|
6271
6746
|
var total = this.grepTotal(suite);
|
|
6272
6747
|
|
|
6273
|
-
debug('
|
|
6748
|
+
debug('runSuite(): running %s', suite.fullTitle());
|
|
6274
6749
|
|
|
6275
6750
|
if (!total || (self.failures && suite._bail)) {
|
|
6751
|
+
debug('runSuite(): bailing');
|
|
6276
6752
|
return fn();
|
|
6277
6753
|
}
|
|
6278
6754
|
|
|
@@ -6338,21 +6814,49 @@ Runner.prototype.runSuite = function(suite, fn) {
|
|
|
6338
6814
|
/**
|
|
6339
6815
|
* Handle uncaught exceptions within runner.
|
|
6340
6816
|
*
|
|
6341
|
-
*
|
|
6817
|
+
* This function is bound to the instance as `Runner#uncaught` at instantiation
|
|
6818
|
+
* time. It's intended to be listening on the `Process.uncaughtException` event.
|
|
6819
|
+
* In order to not leak EE listeners, we need to ensure no more than a single
|
|
6820
|
+
* `uncaughtException` listener exists per `Runner`. The only way to do
|
|
6821
|
+
* this--because this function needs the context (and we don't have lambdas)--is
|
|
6822
|
+
* to use `Function.prototype.bind`. We need strict equality to unregister and
|
|
6823
|
+
* _only_ unregister the _one_ listener we set from the
|
|
6824
|
+
* `Process.uncaughtException` event; would be poor form to just remove
|
|
6825
|
+
* everything. See {@link Runner#run} for where the event listener is registered
|
|
6826
|
+
* and unregistered.
|
|
6827
|
+
* @param {Error} err - Some uncaught error
|
|
6342
6828
|
* @private
|
|
6343
6829
|
*/
|
|
6344
|
-
Runner.prototype.
|
|
6830
|
+
Runner.prototype._uncaught = function(err) {
|
|
6831
|
+
// this is defensive to prevent future developers from mis-calling this function.
|
|
6832
|
+
// it's more likely that it'd be called with the incorrect context--say, the global
|
|
6833
|
+
// `process` object--than it would to be called with a context that is not a "subclass"
|
|
6834
|
+
// of `Runner`.
|
|
6835
|
+
if (!(this instanceof Runner)) {
|
|
6836
|
+
throw createFatalError(
|
|
6837
|
+
'Runner#uncaught() called with invalid context',
|
|
6838
|
+
this
|
|
6839
|
+
);
|
|
6840
|
+
}
|
|
6345
6841
|
if (err instanceof Pending) {
|
|
6842
|
+
debug('uncaught(): caught a Pending');
|
|
6346
6843
|
return;
|
|
6347
6844
|
}
|
|
6348
|
-
|
|
6845
|
+
// browser does not exit script when throwing in global.onerror()
|
|
6846
|
+
if (this.allowUncaught && !process.browser) {
|
|
6847
|
+
debug('uncaught(): bubbling exception due to --allow-uncaught');
|
|
6848
|
+
throw err;
|
|
6849
|
+
}
|
|
6850
|
+
|
|
6851
|
+
if (this.state === constants.STATE_STOPPED) {
|
|
6852
|
+
debug('uncaught(): throwing after run has completed!');
|
|
6349
6853
|
throw err;
|
|
6350
6854
|
}
|
|
6351
6855
|
|
|
6352
6856
|
if (err) {
|
|
6353
|
-
debug('uncaught exception %O', err);
|
|
6857
|
+
debug('uncaught(): got truthy exception %O', err);
|
|
6354
6858
|
} else {
|
|
6355
|
-
debug('uncaught undefined/falsy exception');
|
|
6859
|
+
debug('uncaught(): undefined/falsy exception');
|
|
6356
6860
|
err = createInvalidExceptionError(
|
|
6357
6861
|
'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
|
|
6358
6862
|
err
|
|
@@ -6361,6 +6865,7 @@ Runner.prototype.uncaught = function(err) {
|
|
|
6361
6865
|
|
|
6362
6866
|
if (!isError(err)) {
|
|
6363
6867
|
err = thrown2Error(err);
|
|
6868
|
+
debug('uncaught(): converted "error" %o to Error', err);
|
|
6364
6869
|
}
|
|
6365
6870
|
err.uncaught = true;
|
|
6366
6871
|
|
|
@@ -6368,12 +6873,15 @@ Runner.prototype.uncaught = function(err) {
|
|
|
6368
6873
|
|
|
6369
6874
|
if (!runnable) {
|
|
6370
6875
|
runnable = new Runnable('Uncaught error outside test suite');
|
|
6876
|
+
debug('uncaught(): no current Runnable; created a phony one');
|
|
6371
6877
|
runnable.parent = this.suite;
|
|
6372
6878
|
|
|
6373
|
-
if (this.
|
|
6879
|
+
if (this.state === constants.STATE_RUNNING) {
|
|
6880
|
+
debug('uncaught(): failing gracefully');
|
|
6374
6881
|
this.fail(runnable, err);
|
|
6375
6882
|
} else {
|
|
6376
6883
|
// Can't recover from this failure
|
|
6884
|
+
debug('uncaught(): test run has not yet started; unrecoverable');
|
|
6377
6885
|
this.emit(constants.EVENT_RUN_BEGIN);
|
|
6378
6886
|
this.fail(runnable, err);
|
|
6379
6887
|
this.emit(constants.EVENT_RUN_END);
|
|
@@ -6385,9 +6893,11 @@ Runner.prototype.uncaught = function(err) {
|
|
|
6385
6893
|
runnable.clearTimeout();
|
|
6386
6894
|
|
|
6387
6895
|
if (runnable.isFailed()) {
|
|
6896
|
+
debug('uncaught(): Runnable has already failed');
|
|
6388
6897
|
// Ignore error if already failed
|
|
6389
6898
|
return;
|
|
6390
6899
|
} else if (runnable.isPending()) {
|
|
6900
|
+
debug('uncaught(): pending Runnable wound up failing!');
|
|
6391
6901
|
// report 'pending test' retrospectively as failed
|
|
6392
6902
|
runnable.isPending = alwaysFalse;
|
|
6393
6903
|
this.fail(runnable, err);
|
|
@@ -6398,25 +6908,15 @@ Runner.prototype.uncaught = function(err) {
|
|
|
6398
6908
|
// we cannot recover gracefully if a Runnable has already passed
|
|
6399
6909
|
// then fails asynchronously
|
|
6400
6910
|
if (runnable.isPassed()) {
|
|
6911
|
+
debug('uncaught(): Runnable has already passed; bailing gracefully');
|
|
6401
6912
|
this.fail(runnable, err);
|
|
6402
6913
|
this.abort();
|
|
6403
6914
|
} else {
|
|
6404
|
-
debug(
|
|
6915
|
+
debug('uncaught(): forcing Runnable to complete with Error');
|
|
6405
6916
|
return runnable.callback(err);
|
|
6406
6917
|
}
|
|
6407
6918
|
};
|
|
6408
6919
|
|
|
6409
|
-
/**
|
|
6410
|
-
* Handle uncaught exceptions after runner's end event.
|
|
6411
|
-
*
|
|
6412
|
-
* @param {Error} err
|
|
6413
|
-
* @private
|
|
6414
|
-
*/
|
|
6415
|
-
Runner.prototype.uncaughtEnd = function uncaughtEnd(err) {
|
|
6416
|
-
if (err instanceof Pending) return;
|
|
6417
|
-
throw err;
|
|
6418
|
-
};
|
|
6419
|
-
|
|
6420
6920
|
/**
|
|
6421
6921
|
* Run the root suite and invoke `fn(failures)`
|
|
6422
6922
|
* on completion.
|
|
@@ -6432,53 +6932,60 @@ Runner.prototype.run = function(fn) {
|
|
|
6432
6932
|
|
|
6433
6933
|
fn = fn || function() {};
|
|
6434
6934
|
|
|
6435
|
-
function uncaught(err) {
|
|
6436
|
-
self.uncaught(err);
|
|
6437
|
-
}
|
|
6438
|
-
|
|
6439
6935
|
function start() {
|
|
6936
|
+
debug('run(): starting');
|
|
6440
6937
|
// If there is an `only` filter
|
|
6441
6938
|
if (rootSuite.hasOnly()) {
|
|
6442
6939
|
rootSuite.filterOnly();
|
|
6940
|
+
debug('run(): filtered exclusive Runnables');
|
|
6443
6941
|
}
|
|
6444
|
-
self.
|
|
6942
|
+
self.state = constants.STATE_RUNNING;
|
|
6445
6943
|
if (self._delay) {
|
|
6446
6944
|
self.emit(constants.EVENT_DELAY_END);
|
|
6945
|
+
debug('run(): "delay" ended');
|
|
6447
6946
|
}
|
|
6947
|
+
debug('run(): emitting %s', constants.EVENT_RUN_BEGIN);
|
|
6448
6948
|
self.emit(constants.EVENT_RUN_BEGIN);
|
|
6949
|
+
debug('run(): emitted %s', constants.EVENT_RUN_BEGIN);
|
|
6449
6950
|
|
|
6450
6951
|
self.runSuite(rootSuite, function() {
|
|
6451
|
-
debug(
|
|
6952
|
+
debug(
|
|
6953
|
+
'run(): root suite completed; emitting %s',
|
|
6954
|
+
constants.EVENT_RUN_END
|
|
6955
|
+
);
|
|
6452
6956
|
self.emit(constants.EVENT_RUN_END);
|
|
6957
|
+
debug('run(): emitted %s', constants.EVENT_RUN_END);
|
|
6453
6958
|
});
|
|
6454
6959
|
}
|
|
6455
6960
|
|
|
6456
|
-
debug(constants.EVENT_RUN_BEGIN);
|
|
6457
|
-
|
|
6458
6961
|
// references cleanup to avoid memory leaks
|
|
6459
|
-
this.
|
|
6460
|
-
|
|
6461
|
-
|
|
6962
|
+
if (this._opts.cleanReferencesAfterRun) {
|
|
6963
|
+
this.on(constants.EVENT_SUITE_END, function(suite) {
|
|
6964
|
+
suite.cleanReferences();
|
|
6965
|
+
});
|
|
6966
|
+
}
|
|
6462
6967
|
|
|
6463
6968
|
// callback
|
|
6464
6969
|
this.on(constants.EVENT_RUN_END, function() {
|
|
6970
|
+
self.state = constants.STATE_STOPPED;
|
|
6465
6971
|
debug(constants.EVENT_RUN_END);
|
|
6466
|
-
|
|
6467
|
-
process.on('uncaughtException', self.uncaughtEnd);
|
|
6972
|
+
debug('run(): emitted %s', constants.EVENT_RUN_END);
|
|
6468
6973
|
fn(self.failures);
|
|
6469
6974
|
});
|
|
6470
6975
|
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
process.on('uncaughtException', uncaught);
|
|
6976
|
+
self._removeEventListener(process, 'uncaughtException', self.uncaught);
|
|
6977
|
+
self._addEventListener(process, 'uncaughtException', self.uncaught);
|
|
6474
6978
|
|
|
6475
6979
|
if (this._delay) {
|
|
6476
6980
|
// for reporters, I guess.
|
|
6477
6981
|
// might be nice to debounce some dots while we wait.
|
|
6478
6982
|
this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
|
|
6479
6983
|
rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
|
|
6984
|
+
debug('run(): waiting for green light due to --delay');
|
|
6480
6985
|
} else {
|
|
6481
|
-
|
|
6986
|
+
Runner.immediately(function() {
|
|
6987
|
+
start();
|
|
6988
|
+
});
|
|
6482
6989
|
}
|
|
6483
6990
|
|
|
6484
6991
|
return this;
|
|
@@ -6492,7 +6999,7 @@ Runner.prototype.run = function(fn) {
|
|
|
6492
6999
|
* @return {Runner} Runner instance.
|
|
6493
7000
|
*/
|
|
6494
7001
|
Runner.prototype.abort = function() {
|
|
6495
|
-
debug('aborting');
|
|
7002
|
+
debug('abort(): aborting');
|
|
6496
7003
|
this._abort = true;
|
|
6497
7004
|
|
|
6498
7005
|
return this;
|
|
@@ -6727,20 +7234,20 @@ function Suite(title, parentContext, isRoot) {
|
|
|
6727
7234
|
this.ctx = new Context();
|
|
6728
7235
|
this.suites = [];
|
|
6729
7236
|
this.tests = [];
|
|
7237
|
+
this.root = isRoot === true;
|
|
6730
7238
|
this.pending = false;
|
|
7239
|
+
this._retries = -1;
|
|
6731
7240
|
this._beforeEach = [];
|
|
6732
7241
|
this._beforeAll = [];
|
|
6733
7242
|
this._afterEach = [];
|
|
6734
7243
|
this._afterAll = [];
|
|
6735
|
-
this.root = isRoot === true;
|
|
6736
7244
|
this._timeout = 2000;
|
|
6737
7245
|
this._enableTimeouts = true;
|
|
6738
7246
|
this._slow = 75;
|
|
6739
7247
|
this._bail = false;
|
|
6740
|
-
this._retries = -1;
|
|
6741
7248
|
this._onlyTests = [];
|
|
6742
7249
|
this._onlySuites = [];
|
|
6743
|
-
this.
|
|
7250
|
+
this.reset();
|
|
6744
7251
|
|
|
6745
7252
|
this.on('newListener', function(event) {
|
|
6746
7253
|
if (deprecatedEvents[event]) {
|
|
@@ -6758,6 +7265,22 @@ function Suite(title, parentContext, isRoot) {
|
|
|
6758
7265
|
*/
|
|
6759
7266
|
inherits(Suite, EventEmitter);
|
|
6760
7267
|
|
|
7268
|
+
/**
|
|
7269
|
+
* Resets the state initially or for a next run.
|
|
7270
|
+
*/
|
|
7271
|
+
Suite.prototype.reset = function() {
|
|
7272
|
+
this.delayed = false;
|
|
7273
|
+
function doReset(thingToReset) {
|
|
7274
|
+
thingToReset.reset();
|
|
7275
|
+
}
|
|
7276
|
+
this.suites.forEach(doReset);
|
|
7277
|
+
this.tests.forEach(doReset);
|
|
7278
|
+
this._beforeEach.forEach(doReset);
|
|
7279
|
+
this._afterEach.forEach(doReset);
|
|
7280
|
+
this._beforeAll.forEach(doReset);
|
|
7281
|
+
this._afterAll.forEach(doReset);
|
|
7282
|
+
};
|
|
7283
|
+
|
|
6761
7284
|
/**
|
|
6762
7285
|
* Return a clone of this `Suite`.
|
|
6763
7286
|
*
|
|
@@ -7177,6 +7700,16 @@ Suite.prototype.getHooks = function getHooks(name) {
|
|
|
7177
7700
|
return this['_' + name];
|
|
7178
7701
|
};
|
|
7179
7702
|
|
|
7703
|
+
/**
|
|
7704
|
+
* cleans all references from this suite and all child suites.
|
|
7705
|
+
*/
|
|
7706
|
+
Suite.prototype.dispose = function() {
|
|
7707
|
+
this.suites.forEach(function(suite) {
|
|
7708
|
+
suite.dispose();
|
|
7709
|
+
});
|
|
7710
|
+
this.cleanReferences();
|
|
7711
|
+
};
|
|
7712
|
+
|
|
7180
7713
|
/**
|
|
7181
7714
|
* Cleans up the references to all the deferred functions
|
|
7182
7715
|
* (before/after/beforeEach/afterEach) and tests of a Suite.
|
|
@@ -7336,9 +7869,9 @@ function Test(title, fn) {
|
|
|
7336
7869
|
'string'
|
|
7337
7870
|
);
|
|
7338
7871
|
}
|
|
7339
|
-
Runnable.call(this, title, fn);
|
|
7340
|
-
this.pending = !fn;
|
|
7341
7872
|
this.type = 'test';
|
|
7873
|
+
Runnable.call(this, title, fn);
|
|
7874
|
+
this.reset();
|
|
7342
7875
|
}
|
|
7343
7876
|
|
|
7344
7877
|
/**
|
|
@@ -7346,6 +7879,36 @@ function Test(title, fn) {
|
|
|
7346
7879
|
*/
|
|
7347
7880
|
utils.inherits(Test, Runnable);
|
|
7348
7881
|
|
|
7882
|
+
/**
|
|
7883
|
+
* Resets the state initially or for a next run.
|
|
7884
|
+
*/
|
|
7885
|
+
Test.prototype.reset = function() {
|
|
7886
|
+
Runnable.prototype.reset.call(this);
|
|
7887
|
+
this.pending = !this.fn;
|
|
7888
|
+
delete this.state;
|
|
7889
|
+
};
|
|
7890
|
+
|
|
7891
|
+
/**
|
|
7892
|
+
* Set or get retried test
|
|
7893
|
+
*
|
|
7894
|
+
* @private
|
|
7895
|
+
*/
|
|
7896
|
+
Test.prototype.retriedTest = function(n) {
|
|
7897
|
+
if (!arguments.length) {
|
|
7898
|
+
return this._retriedTest;
|
|
7899
|
+
}
|
|
7900
|
+
this._retriedTest = n;
|
|
7901
|
+
};
|
|
7902
|
+
|
|
7903
|
+
/**
|
|
7904
|
+
* Add test to the list of tests marked `only`.
|
|
7905
|
+
*
|
|
7906
|
+
* @private
|
|
7907
|
+
*/
|
|
7908
|
+
Test.prototype.markOnly = function() {
|
|
7909
|
+
this.parent.appendOnlyTest(this);
|
|
7910
|
+
};
|
|
7911
|
+
|
|
7349
7912
|
Test.prototype.clone = function() {
|
|
7350
7913
|
var test = new Test(this.title, this.fn);
|
|
7351
7914
|
test.timeout(this.timeout());
|
|
@@ -7353,6 +7916,7 @@ Test.prototype.clone = function() {
|
|
|
7353
7916
|
test.enableTimeouts(this.enableTimeouts());
|
|
7354
7917
|
test.retries(this.retries());
|
|
7355
7918
|
test.currentRetry(this.currentRetry());
|
|
7919
|
+
test.retriedTest(this.retriedTest() || this);
|
|
7356
7920
|
test.globals(this.globals());
|
|
7357
7921
|
test.parent = this.parent;
|
|
7358
7922
|
test.file = this.file;
|
|
@@ -7427,8 +7991,9 @@ exports.isString = function(obj) {
|
|
|
7427
7991
|
exports.slug = function(str) {
|
|
7428
7992
|
return str
|
|
7429
7993
|
.toLowerCase()
|
|
7430
|
-
.replace(
|
|
7431
|
-
.replace(/[^-\w]/g, '')
|
|
7994
|
+
.replace(/\s+/g, '-')
|
|
7995
|
+
.replace(/[^-\w]/g, '')
|
|
7996
|
+
.replace(/-{2,}/g, '-');
|
|
7432
7997
|
};
|
|
7433
7998
|
|
|
7434
7999
|
/**
|
|
@@ -8001,7 +8566,7 @@ exports.stackTraceFilter = function() {
|
|
|
8001
8566
|
var slash = path.sep;
|
|
8002
8567
|
var cwd;
|
|
8003
8568
|
if (is.node) {
|
|
8004
|
-
cwd =
|
|
8569
|
+
cwd = exports.cwd() + slash;
|
|
8005
8570
|
} else {
|
|
8006
8571
|
cwd = (typeof location === 'undefined'
|
|
8007
8572
|
? window.location
|
|
@@ -8117,38 +8682,6 @@ exports.dQuote = function(str) {
|
|
|
8117
8682
|
return '"' + str + '"';
|
|
8118
8683
|
};
|
|
8119
8684
|
|
|
8120
|
-
/**
|
|
8121
|
-
* Provides simplistic message translation for dealing with plurality.
|
|
8122
|
-
*
|
|
8123
|
-
* @description
|
|
8124
|
-
* Use this to create messages which need to be singular or plural.
|
|
8125
|
-
* Some languages have several plural forms, so _complete_ message clauses
|
|
8126
|
-
* are preferable to generating the message on the fly.
|
|
8127
|
-
*
|
|
8128
|
-
* @private
|
|
8129
|
-
* @param {number} n - Non-negative integer
|
|
8130
|
-
* @param {string} msg1 - Message to be used in English for `n = 1`
|
|
8131
|
-
* @param {string} msg2 - Message to be used in English for `n = 0, 2, 3, ...`
|
|
8132
|
-
* @returns {string} message corresponding to value of `n`
|
|
8133
|
-
* @example
|
|
8134
|
-
* var sprintf = require('util').format;
|
|
8135
|
-
* var pkgs = ['one', 'two'];
|
|
8136
|
-
* var msg = sprintf(
|
|
8137
|
-
* ngettext(
|
|
8138
|
-
* pkgs.length,
|
|
8139
|
-
* 'cannot load package: %s',
|
|
8140
|
-
* 'cannot load packages: %s'
|
|
8141
|
-
* ),
|
|
8142
|
-
* pkgs.map(sQuote).join(', ')
|
|
8143
|
-
* );
|
|
8144
|
-
* console.log(msg); // => cannot load packages: 'one', 'two'
|
|
8145
|
-
*/
|
|
8146
|
-
exports.ngettext = function(n, msg1, msg2) {
|
|
8147
|
-
if (typeof n === 'number' && n >= 0) {
|
|
8148
|
-
return n === 1 ? msg1 : msg2;
|
|
8149
|
-
}
|
|
8150
|
-
};
|
|
8151
|
-
|
|
8152
8685
|
/**
|
|
8153
8686
|
* It's a noop.
|
|
8154
8687
|
* @public
|
|
@@ -8196,6 +8729,38 @@ exports.defineConstants = function(obj) {
|
|
|
8196
8729
|
return Object.freeze(exports.createMap(obj));
|
|
8197
8730
|
};
|
|
8198
8731
|
|
|
8732
|
+
/**
|
|
8733
|
+
* Whether current version of Node support ES modules
|
|
8734
|
+
*
|
|
8735
|
+
* @description
|
|
8736
|
+
* Versions prior to 10 did not support ES Modules, and version 10 has an old incompatibile version of ESM.
|
|
8737
|
+
* This function returns whether Node.JS has ES Module supports that is compatible with Mocha's needs,
|
|
8738
|
+
* which is version >=12.11.
|
|
8739
|
+
*
|
|
8740
|
+
* @returns {Boolean} whether the current version of Node.JS supports ES Modules in a way that is compatible with Mocha
|
|
8741
|
+
*/
|
|
8742
|
+
exports.supportsEsModules = function() {
|
|
8743
|
+
if (!process.browser && process.versions && process.versions.node) {
|
|
8744
|
+
var versionFields = process.versions.node.split('.');
|
|
8745
|
+
var major = +versionFields[0];
|
|
8746
|
+
var minor = +versionFields[1];
|
|
8747
|
+
|
|
8748
|
+
if (major >= 13 || (major === 12 && minor >= 11)) {
|
|
8749
|
+
return true;
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
};
|
|
8753
|
+
|
|
8754
|
+
/**
|
|
8755
|
+
* Returns current working directory
|
|
8756
|
+
*
|
|
8757
|
+
* Wrapper around `process.cwd()` for isolation
|
|
8758
|
+
* @private
|
|
8759
|
+
*/
|
|
8760
|
+
exports.cwd = function cwd() {
|
|
8761
|
+
return process.cwd();
|
|
8762
|
+
};
|
|
8763
|
+
|
|
8199
8764
|
}).call(this,require('_process'),require("buffer").Buffer)
|
|
8200
8765
|
},{"./errors":6,"_process":69,"buffer":43,"fs":42,"glob":42,"he":54,"object.assign":65,"path":42,"util":89}],39:[function(require,module,exports){
|
|
8201
8766
|
'use strict'
|
|
@@ -13746,7 +14311,6 @@ module.exports = Array.isArray || function (arr) {
|
|
|
13746
14311
|
};
|
|
13747
14312
|
|
|
13748
14313
|
},{}],59:[function(require,module,exports){
|
|
13749
|
-
(function (process){
|
|
13750
14314
|
var path = require('path');
|
|
13751
14315
|
var fs = require('fs');
|
|
13752
14316
|
var _0777 = parseInt('0777', 8);
|
|
@@ -13766,7 +14330,7 @@ function mkdirP (p, opts, f, made) {
|
|
|
13766
14330
|
var xfs = opts.fs || fs;
|
|
13767
14331
|
|
|
13768
14332
|
if (mode === undefined) {
|
|
13769
|
-
mode = _0777
|
|
14333
|
+
mode = _0777
|
|
13770
14334
|
}
|
|
13771
14335
|
if (!made) made = null;
|
|
13772
14336
|
|
|
@@ -13780,6 +14344,7 @@ function mkdirP (p, opts, f, made) {
|
|
|
13780
14344
|
}
|
|
13781
14345
|
switch (er.code) {
|
|
13782
14346
|
case 'ENOENT':
|
|
14347
|
+
if (path.dirname(p) === p) return cb(er);
|
|
13783
14348
|
mkdirP(path.dirname(p), opts, function (er, made) {
|
|
13784
14349
|
if (er) cb(er, made);
|
|
13785
14350
|
else mkdirP(p, opts, cb, made);
|
|
@@ -13810,7 +14375,7 @@ mkdirP.sync = function sync (p, opts, made) {
|
|
|
13810
14375
|
var xfs = opts.fs || fs;
|
|
13811
14376
|
|
|
13812
14377
|
if (mode === undefined) {
|
|
13813
|
-
mode = _0777
|
|
14378
|
+
mode = _0777
|
|
13814
14379
|
}
|
|
13815
14380
|
if (!made) made = null;
|
|
13816
14381
|
|
|
@@ -13846,8 +14411,7 @@ mkdirP.sync = function sync (p, opts, made) {
|
|
|
13846
14411
|
return made;
|
|
13847
14412
|
};
|
|
13848
14413
|
|
|
13849
|
-
}
|
|
13850
|
-
},{"_process":69,"fs":42,"path":42}],60:[function(require,module,exports){
|
|
14414
|
+
},{"fs":42,"path":42}],60:[function(require,module,exports){
|
|
13851
14415
|
/**
|
|
13852
14416
|
* Helpers.
|
|
13853
14417
|
*/
|
|
@@ -18077,7 +18641,7 @@ function hasOwnProperty(obj, prop) {
|
|
|
18077
18641
|
},{"./support/isBuffer":88,"_process":69,"inherits":56}],90:[function(require,module,exports){
|
|
18078
18642
|
module.exports={
|
|
18079
18643
|
"name": "mocha",
|
|
18080
|
-
"version": "7.0
|
|
18644
|
+
"version": "7.2.0",
|
|
18081
18645
|
"homepage": "https://mochajs.org/",
|
|
18082
18646
|
"notifyLogo": "https://ibin.co/4QuRuGjXvl36.png"
|
|
18083
18647
|
}
|