mocha 7.0.0-esm1 → 7.1.1

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2011-2018 JS Foundation and contributors, https://js.foundation
3
+ Copyright (c) 2011-2020 OpenJS Foundation and contributors, https://openjsf.org
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -100,6 +100,6 @@ Finally, come [chat with the maintainers](https://gitter.im/mochajs/contributors
100
100
 
101
101
  ## License
102
102
 
103
- [MIT](LICENSE)
103
+ Copyright 2011-2020 OpenJS Foundation and contributors. Licensed [MIT](https://github.com/mochajs/mocha/blob/master/LICENSE).
104
104
 
105
105
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_large)
package/browser-entry.js CHANGED
@@ -60,7 +60,7 @@ process.on = function(e, fn) {
60
60
  if (e === 'uncaughtException') {
61
61
  global.onerror = function(err, url, line) {
62
62
  fn(new Error(err + ' (' + url + ':' + line + ')'));
63
- return !mocha.allowUncaught;
63
+ return !mocha.options.allowUncaught;
64
64
  };
65
65
  uncaughtExceptionHandlers.push(fn);
66
66
  }
@@ -129,7 +129,7 @@ mocha.setup = function(opts) {
129
129
  opts = {ui: opts};
130
130
  }
131
131
  for (var opt in opts) {
132
- if (opts.hasOwnProperty(opt)) {
132
+ if (Object.prototype.hasOwnProperty.call(opts, opt)) {
133
133
  this[opt](opts[opt]);
134
134
  }
135
135
  }
@@ -15,8 +15,6 @@ const collectFiles = require('./collect-files');
15
15
 
16
16
  const cwd = (exports.cwd = process.cwd());
17
17
 
18
- exports.watchRun = watchRun;
19
-
20
18
  /**
21
19
  * Exits Mocha when tests + code under test has finished execution (default)
22
20
  * @param {number} code - Exit code; typically # of failures
@@ -92,7 +90,7 @@ exports.handleRequires = (requires = []) => {
92
90
  };
93
91
 
94
92
  /**
95
- * Collect test files and run mocha instance.
93
+ * Collect and load test files, then run mocha instance.
96
94
  * @param {Mocha} mocha - Mocha instance
97
95
  * @param {Options} [opts] - Command line options
98
96
  * @param {boolean} [opts.exit] - Whether or not to force-exit after tests are complete
@@ -101,18 +99,13 @@ exports.handleRequires = (requires = []) => {
101
99
  * @returns {Promise<Runner>}
102
100
  * @private
103
101
  */
104
- exports.singleRun = (mocha, {exit}, fileCollectParams) => {
102
+ const singleRun = async (mocha, {exit}, fileCollectParams) => {
105
103
  const files = collectFiles(fileCollectParams);
106
104
  debug('running tests with files', files);
107
105
  mocha.files = files;
108
106
 
109
- return mocha.runAsync().then(exitCode => {
110
- if (exit) {
111
- exitMocha(exitCode);
112
- } else {
113
- exitMochaLater(exitCode);
114
- }
115
- });
107
+ await mocha.loadFilesAsync();
108
+ return mocha.run(exit ? exitMocha : exitMochaLater);
116
109
  };
117
110
 
118
111
  /**
@@ -122,7 +115,7 @@ exports.singleRun = (mocha, {exit}, fileCollectParams) => {
122
115
  * @private
123
116
  * @returns {Promise}
124
117
  */
125
- exports.runMocha = (mocha, options) => {
118
+ exports.runMocha = async (mocha, options) => {
126
119
  const {
127
120
  watch = false,
128
121
  extension = [],
@@ -148,7 +141,7 @@ exports.runMocha = (mocha, options) => {
148
141
  if (watch) {
149
142
  watchRun(mocha, {watchFiles, watchIgnore}, fileCollectParams);
150
143
  } else {
151
- return exports.singleRun(mocha, {exit}, fileCollectParams);
144
+ await singleRun(mocha, {exit}, fileCollectParams);
152
145
  }
153
146
  };
154
147
 
package/lib/cli/run.js CHANGED
@@ -87,7 +87,6 @@ exports.builder = yargs =>
87
87
  },
88
88
  extension: {
89
89
  default: defaults.extension,
90
- defaultDescription: 'js',
91
90
  description: 'File extension(s) to load',
92
91
  group: GROUPS.FILES,
93
92
  requiresArg: true,
@@ -306,7 +305,7 @@ exports.handler = async function(argv) {
306
305
  try {
307
306
  await runMocha(mocha, argv);
308
307
  } catch (err) {
309
- console.error(err.stack || `Error: ${err.message || err}`);
308
+ console.error('\n' + (err.stack || `Error: ${err.message || err}`));
310
309
  process.exit(1);
311
310
  }
312
311
  };
package/lib/esm-utils.js CHANGED
@@ -1,17 +1,13 @@
1
- // This file is allowed to use async/await because it is not exposed to browsers (see the `eslintrc`),
2
- // and Node supports async/await in all its non-dead version.
3
-
4
1
  const url = require('url');
5
2
  const path = require('path');
6
3
 
7
- exports.requireOrImport = async file => {
4
+ const requireOrImport = async file => {
8
5
  file = path.resolve(file);
9
6
 
10
7
  if (path.extname(file) === '.mjs') {
11
8
  return import(url.pathToFileURL(file));
12
9
  }
13
- // This way of figuring out whether a test file is CJS or ESM is currently the only known
14
- // way of figuring out whether a file is CJS or ESM.
10
+ // This is currently the only known way of figuring out whether a file is CJS or ESM.
15
11
  // If Node.js or the community establish a better procedure for that, we can fix this code.
16
12
  // Another option here would be to always use `import()`, as this also supports CJS, but I would be
17
13
  // wary of using it for _all_ existing test files, till ESM is fully stable.
@@ -29,7 +25,7 @@ exports.requireOrImport = async file => {
29
25
  exports.loadFilesAsync = async (files, preLoadFunc, postLoadFunc) => {
30
26
  for (const file of files) {
31
27
  preLoadFunc(file);
32
- const result = await exports.requireOrImport(file);
28
+ const result = await requireOrImport(file);
33
29
  postLoadFunc(file, result);
34
30
  }
35
31
  };
package/lib/mocha.js CHANGED
@@ -101,7 +101,10 @@ function Mocha(options) {
101
101
  this.grep(options.grep)
102
102
  .fgrep(options.fgrep)
103
103
  .ui(options.ui)
104
- .reporter(options.reporter, options.reporterOption)
104
+ .reporter(
105
+ options.reporter,
106
+ options.reporterOption || options.reporterOptions // reporterOptions was previously the only way to specify options to reporter
107
+ )
105
108
  .slow(options.slow)
106
109
  .global(options.global);
107
110
 
@@ -322,16 +325,22 @@ Mocha.prototype.loadFiles = function(fn) {
322
325
  * the test interface functions and will be subject to its cache.
323
326
  * Supports both CJS and ESM modules.
324
327
  *
325
- * @private
328
+ * @public
326
329
  * @see {@link Mocha#addFile}
327
330
  * @see {@link Mocha#run}
328
331
  * @see {@link Mocha#unloadFiles}
329
- *
330
332
  * @returns {Promise}
333
+ * @example
334
+ *
335
+ * // loads ESM (and CJS) test files asynchronously, then runs root suite
336
+ * mocha.loadFilesAsync()
337
+ * .then(() => mocha.run(failures => process.exitCode = failures ? 1 : 0))
338
+ * .catch(() => process.exitCode = 1);
331
339
  */
332
340
  Mocha.prototype.loadFilesAsync = function() {
333
341
  var self = this;
334
342
  var suite = this.suite;
343
+ this.loadAsync = true;
335
344
 
336
345
  if (!esmUtils) {
337
346
  return new Promise(function(resolve) {
@@ -367,8 +376,9 @@ Mocha.unloadFile = function(file) {
367
376
  * Unloads `files` from Node's `require` cache.
368
377
  *
369
378
  * @description
370
- * This allows files to be "freshly" reloaded, providing the ability
379
+ * This allows required files to be "freshly" reloaded, providing the ability
371
380
  * to reuse a Mocha instance programmatically.
381
+ * Note: does not clear ESM module files from the cache
372
382
  *
373
383
  * <strong>Intended for consumers &mdash; not used internally</strong>
374
384
  *
@@ -875,31 +885,26 @@ Object.defineProperty(Mocha.prototype, 'version', {
875
885
  * already in the `require` cache), make sure to clear them from
876
886
  * the cache first!
877
887
  *
878
- * This method supports only CommonJS test files, and not ES modules ones.
879
- * To use ES module (and CommonJS) test files, call Mocha#runAsync instead.
880
- *
881
888
  * @public
882
- * @see {@link Mocha#runAsync}
883
889
  * @see {@link Mocha#unloadFiles}
884
890
  * @see {@link Runner#run}
885
891
  * @param {DoneCB} [fn] - Callback invoked when test execution completed.
886
- * @return {Runner} runner instance
892
+ * @returns {Runner} runner instance
893
+ * @example
894
+ *
895
+ * // exit with non-zero status if there were test failures
896
+ * mocha.run(failures => process.exitCode = failures ? 1 : 0);
887
897
  */
888
898
  Mocha.prototype.run = function(fn) {
889
- if (this.files.length) {
899
+ if (this.files.length && !this.loadAsync) {
890
900
  this.loadFiles();
891
901
  }
892
- return this._startRunning(fn);
893
- };
894
-
895
- Mocha.prototype._startRunning = function(fn) {
896
- var self = this;
897
- var suite = self.suite;
898
- var options = self.options;
899
- options.files = self.files;
902
+ var suite = this.suite;
903
+ var options = this.options;
904
+ options.files = this.files;
900
905
  var runner = new exports.Runner(suite, options.delay);
901
906
  createStatsCollector(runner);
902
- var reporter = new self._reporter(runner, options);
907
+ var reporter = new this._reporter(runner, options);
903
908
  runner.checkLeaks = options.checkLeaks === true;
904
909
  runner.fullStackTrace = options.fullTrace;
905
910
  runner.asyncOnly = options.asyncOnly;
@@ -913,7 +918,7 @@ Mocha.prototype._startRunning = function(fn) {
913
918
  runner.globals(options.global);
914
919
  }
915
920
  if (options.growl) {
916
- self._growl(runner);
921
+ this._growl(runner);
917
922
  }
918
923
  if (options.color !== undefined) {
919
924
  exports.reporters.Base.useColors = options.color;
@@ -932,33 +937,3 @@ Mocha.prototype._startRunning = function(fn) {
932
937
 
933
938
  return runner.run(done);
934
939
  };
935
-
936
- /**
937
- * Runs root suite and invokes `fn()` when complete. Supports ES Modules.
938
- *
939
- * @description
940
- * To run tests multiple times (or to run tests in files that are
941
- * already in the `require` cache), make sure to clear them from
942
- * the cache first!
943
- *
944
- * This method supports both ES Modules and CommonJS test files.
945
- *
946
- * @public
947
- * @see {@link Mocha#unloadFiles}
948
- * @see {@link Runner#run}
949
- * @return {Promise<Runner>} runner instance
950
- */
951
- Mocha.prototype.runAsync = function() {
952
- var loadResult = this.files.length
953
- ? this.loadFilesAsync()
954
- : Promise.resolve();
955
-
956
- var self = this;
957
- return loadResult.then(function() {
958
- return new Promise(function(resolve) {
959
- self._startRunning(function(result) {
960
- resolve(result);
961
- });
962
- });
963
- });
964
- };
package/lib/runnable.js CHANGED
@@ -335,9 +335,18 @@ Runnable.prototype.run = function(fn) {
335
335
  fn(err);
336
336
  }
337
337
 
338
- // for .resetTimeout()
338
+ // for .resetTimeout() and Runner#uncaught()
339
339
  this.callback = done;
340
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
+
341
350
  // explicit async with `done` argument
342
351
  if (this.async) {
343
352
  this.resetTimeout();
package/lib/runner.js CHANGED
@@ -135,6 +135,11 @@ function Runner(suite, delay) {
135
135
  this.total = suite.total();
136
136
  this.failures = 0;
137
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
+ }
138
143
  self.checkGlobals(test);
139
144
  });
140
145
  this.on(constants.EVENT_HOOK_END, function(hook) {
@@ -654,7 +659,7 @@ Runner.prototype.runTests = function(suite, fn) {
654
659
  self.emit(constants.EVENT_TEST_END, test);
655
660
  // skip inner afterEach hooks below errSuite level
656
661
  var origSuite = self.suite;
657
- self.suite = errSuite;
662
+ self.suite = errSuite || self.suite;
658
663
  return self.hookUp(HOOK_TYPE_AFTER_EACH, function(e, eSuite) {
659
664
  self.suite = origSuite;
660
665
  next(e, eSuite);
@@ -724,7 +729,6 @@ Runner.prototype.runSuite = function(suite, fn) {
724
729
  var i = 0;
725
730
  var self = this;
726
731
  var total = this.grepTotal(suite);
727
- var afterAllHookCalled = false;
728
732
 
729
733
  debug('run suite %s', suite.fullTitle());
730
734
 
@@ -772,21 +776,13 @@ Runner.prototype.runSuite = function(suite, fn) {
772
776
  self.suite = suite;
773
777
  self.nextSuite = next;
774
778
 
775
- if (afterAllHookCalled) {
776
- fn(errSuite);
777
- } else {
778
- // mark that the afterAll block has been called once
779
- // and so can be skipped if there is an error in it.
780
- afterAllHookCalled = true;
781
-
782
- // remove reference to test
783
- delete self.test;
779
+ // remove reference to test
780
+ delete self.test;
784
781
 
785
- self.hook(HOOK_TYPE_AFTER_ALL, function() {
786
- self.emit(constants.EVENT_SUITE_END, suite);
787
- fn(errSuite);
788
- });
789
- }
782
+ self.hook(HOOK_TYPE_AFTER_ALL, function() {
783
+ self.emit(constants.EVENT_SUITE_END, suite);
784
+ fn(errSuite);
785
+ });
790
786
  }
791
787
 
792
788
  this.nextSuite = next;
@@ -800,7 +796,7 @@ Runner.prototype.runSuite = function(suite, fn) {
800
796
  };
801
797
 
802
798
  /**
803
- * Handle uncaught exceptions.
799
+ * Handle uncaught exceptions within runner.
804
800
  *
805
801
  * @param {Error} err
806
802
  * @private
@@ -809,7 +805,8 @@ Runner.prototype.uncaught = function(err) {
809
805
  if (err instanceof Pending) {
810
806
  return;
811
807
  }
812
- if (this.allowUncaught) {
808
+ // browser does not exit script when throwing in global.onerror()
809
+ if (this.allowUncaught && !process.browser) {
813
810
  throw err;
814
811
  }
815
812
 
@@ -861,36 +858,24 @@ Runner.prototype.uncaught = function(err) {
861
858
 
862
859
  // we cannot recover gracefully if a Runnable has already passed
863
860
  // then fails asynchronously
864
- var alreadyPassed = runnable.isPassed();
865
- // this will change the state to "failed" regardless of the current value
866
- this.fail(runnable, err);
867
- if (!alreadyPassed) {
868
- // recover from test
869
- if (runnable.type === constants.EVENT_TEST_BEGIN) {
870
- this.emit(constants.EVENT_TEST_END, runnable);
871
- this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
872
- return;
873
- }
861
+ if (runnable.isPassed()) {
862
+ this.fail(runnable, err);
863
+ this.abort();
864
+ } else {
874
865
  debug(runnable);
875
-
876
- // recover from hooks
877
- var errSuite = this.suite;
878
-
879
- // XXX how about a less awful way to determine this?
880
- // if hook failure is in afterEach block
881
- if (runnable.fullTitle().indexOf('after each') > -1) {
882
- return this.hookErr(err, errSuite, true);
883
- }
884
- // if hook failure is in beforeEach block
885
- if (runnable.fullTitle().indexOf('before each') > -1) {
886
- return this.hookErr(err, errSuite, false);
887
- }
888
- // if hook failure is in after or before blocks
889
- return this.nextSuite(errSuite);
866
+ return runnable.callback(err);
890
867
  }
868
+ };
891
869
 
892
- // bail
893
- this.abort();
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;
894
879
  };
895
880
 
896
881
  /**
@@ -940,16 +925,12 @@ Runner.prototype.run = function(fn) {
940
925
  this.on(constants.EVENT_RUN_END, function() {
941
926
  debug(constants.EVENT_RUN_END);
942
927
  process.removeListener('uncaughtException', uncaught);
943
- process.on('uncaughtException', function(err) {
944
- if (err instanceof Pending) {
945
- return;
946
- }
947
- throw err;
948
- });
928
+ process.on('uncaughtException', self.uncaughtEnd);
949
929
  fn(self.failures);
950
930
  });
951
931
 
952
932
  // uncaught exception
933
+ process.removeListener('uncaughtException', self.uncaughtEnd);
953
934
  process.on('uncaughtException', uncaught);
954
935
 
955
936
  if (this._delay) {
@@ -958,7 +939,9 @@ Runner.prototype.run = function(fn) {
958
939
  this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
959
940
  rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
960
941
  } else {
961
- start();
942
+ Runner.immediately(function() {
943
+ start();
944
+ });
962
945
  }
963
946
 
964
947
  return this;
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
@@ -838,39 +838,18 @@ exports.defineConstants = function(obj) {
838
838
  * @description
839
839
  * Versions prior to 10 did not support ES Modules, and version 10 has an old incompatibile version of ESM.
840
840
  * This function returns whether Node.JS has ES Module supports that is compatible with Mocha's needs,
841
- * which is version 12 and older
841
+ * which is version >=12.11.
842
842
  *
843
- * @param {Boolean} unflagged whether the support is unflagged (`true`) or only using the `--experimental-modules` flag (`false`)
844
- * @returns {Boolean} whether the current version of Node.JS supports ES Modules in a way that is compatbile with Mocha
843
+ * @returns {Boolean} whether the current version of Node.JS supports ES Modules in a way that is compatible with Mocha
845
844
  */
846
- exports.supportsEsModules = function(unflagged) {
847
- if (typeof document !== 'undefined') {
848
- return false;
849
- }
850
- if (
851
- typeof process !== 'object' ||
852
- !process.versions ||
853
- !process.versions.node
854
- ) {
855
- return false;
856
- }
857
- var versionFields = process.versions.node.split('.');
858
- var major = +versionFields[0];
859
- var minor = +versionFields[1];
860
-
861
- if (major >= 13) {
862
- if (unflagged) {
863
- return minor >= 2;
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;
864
853
  }
865
- return true;
866
854
  }
867
- if (unflagged) {
868
- return false;
869
- }
870
- if (major < 12) {
871
- return false;
872
- }
873
- // major === 12
874
-
875
- return minor >= 11;
876
855
  };