mocha 9.2.2 → 10.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.
File without changes
@@ -86,6 +86,20 @@ Progress.prototype.update = function (n) {
86
86
  */
87
87
  Progress.prototype.draw = function (ctx) {
88
88
  try {
89
+ var darkMatcher = window.matchMedia('(prefers-color-scheme: dark)');
90
+ var isDarkMode = !!darkMatcher.matches;
91
+ var lightColors = {
92
+ outerCircle: '#9f9f9f',
93
+ innerCircle: '#eee',
94
+ text: '#000'
95
+ };
96
+ var darkColors = {
97
+ outerCircle: '#888',
98
+ innerCircle: '#444',
99
+ text: '#fff'
100
+ };
101
+ var colors = isDarkMode ? darkColors : lightColors;
102
+
89
103
  var percent = Math.min(this.percent, 100);
90
104
  var size = this._size;
91
105
  var half = size / 2;
@@ -100,13 +114,13 @@ Progress.prototype.draw = function (ctx) {
100
114
  ctx.clearRect(0, 0, size, size);
101
115
 
102
116
  // outer circle
103
- ctx.strokeStyle = '#9f9f9f';
117
+ ctx.strokeStyle = colors.outerCircle;
104
118
  ctx.beginPath();
105
119
  ctx.arc(x, y, rad, 0, angle, false);
106
120
  ctx.stroke();
107
121
 
108
122
  // inner circle
109
- ctx.strokeStyle = '#eee';
123
+ ctx.strokeStyle = colors.innerCircle;
110
124
  ctx.beginPath();
111
125
  ctx.arc(x, y, rad - 1, 0, angle, true);
112
126
  ctx.stroke();
@@ -115,6 +129,7 @@ Progress.prototype.draw = function (ctx) {
115
129
  var text = this._text || (percent | 0) + '%';
116
130
  var w = ctx.measureText(text).width;
117
131
 
132
+ ctx.fillStyle = colors.text;
118
133
  ctx.fillText(text, x - w / 2 + 1, y + fontSize / 2 - 1);
119
134
  } catch (ignore) {
120
135
  // don't fail if we can't render progress
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * Exports Yargs commands
5
- * @see https://git.io/fpJ0G
5
+ * @see https://github.com/yargs/yargs/blob/main/docs/advanced.md
6
6
  * @private
7
7
  * @module
8
8
  */
@@ -39,7 +39,6 @@ const TYPES = (exports.types = {
39
39
  'forbid-only',
40
40
  'forbid-pending',
41
41
  'full-trace',
42
- 'growl',
43
42
  'inline-diffs',
44
43
  'invert',
45
44
  'list-interfaces',
@@ -76,7 +75,6 @@ exports.aliases = {
76
75
  fgrep: ['f'],
77
76
  global: ['globals'],
78
77
  grep: ['g'],
79
- growl: ['G'],
80
78
  ignore: ['exclude'],
81
79
  invert: ['i'],
82
80
  jobs: ['j'],
package/lib/cli/run.js CHANGED
@@ -141,10 +141,6 @@ exports.builder = yargs =>
141
141
  group: GROUPS.FILTERS,
142
142
  requiresArg: true
143
143
  },
144
- growl: {
145
- description: 'Enable Growl notifications',
146
- group: GROUPS.OUTPUT
147
- },
148
144
  ignore: {
149
145
  defaultDescription: '(none)',
150
146
  description: 'Ignore file(s) or glob pattern(s)',
@@ -333,7 +329,7 @@ exports.builder = yargs =>
333
329
  if (argv.compilers) {
334
330
  throw createUnsupportedError(
335
331
  `--compilers is DEPRECATED and no longer supported.
336
- See https://git.io/vdcSr for migration information.`
332
+ See https://github.com/mochajs/mocha/wiki/compilers-deprecation for migration information.`
337
333
  );
338
334
  }
339
335
 
@@ -40,9 +40,9 @@ module.exports = function bddInterface(suite) {
40
40
 
41
41
  context.describe = context.context = function (title, fn) {
42
42
  return common.suite.create({
43
- title: title,
44
- file: file,
45
- fn: fn
43
+ title,
44
+ file,
45
+ fn
46
46
  });
47
47
  };
48
48
 
@@ -55,9 +55,9 @@ module.exports = function bddInterface(suite) {
55
55
  context.describe.skip =
56
56
  function (title, fn) {
57
57
  return common.suite.skip({
58
- title: title,
59
- file: file,
60
- fn: fn
58
+ title,
59
+ file,
60
+ fn
61
61
  });
62
62
  };
63
63
 
@@ -67,9 +67,9 @@ module.exports = function bddInterface(suite) {
67
67
 
68
68
  context.describe.only = function (title, fn) {
69
69
  return common.suite.only({
70
- title: title,
71
- file: file,
72
- fn: fn
70
+ title,
71
+ file,
72
+ fn
73
73
  });
74
74
  };
75
75
 
@@ -49,8 +49,8 @@ module.exports = function qUnitInterface(suite) {
49
49
  suites.shift();
50
50
  }
51
51
  return common.suite.create({
52
- title: title,
53
- file: file,
52
+ title,
53
+ file,
54
54
  fn: false
55
55
  });
56
56
  };
@@ -64,8 +64,8 @@ module.exports = function qUnitInterface(suite) {
64
64
  suites.shift();
65
65
  }
66
66
  return common.suite.only({
67
- title: title,
68
- file: file,
67
+ title,
68
+ file,
69
69
  fn: false
70
70
  });
71
71
  };
@@ -47,9 +47,9 @@ module.exports = function (suite) {
47
47
  */
48
48
  context.suite = function (title, fn) {
49
49
  return common.suite.create({
50
- title: title,
51
- file: file,
52
- fn: fn
50
+ title,
51
+ file,
52
+ fn
53
53
  });
54
54
  };
55
55
 
@@ -58,9 +58,9 @@ module.exports = function (suite) {
58
58
  */
59
59
  context.suite.skip = function (title, fn) {
60
60
  return common.suite.skip({
61
- title: title,
62
- file: file,
63
- fn: fn
61
+ title,
62
+ file,
63
+ fn
64
64
  });
65
65
  };
66
66
 
@@ -69,9 +69,9 @@ module.exports = function (suite) {
69
69
  */
70
70
  context.suite.only = function (title, fn) {
71
71
  return common.suite.only({
72
- title: title,
73
- file: file,
74
- fn: fn
72
+ title,
73
+ file,
74
+ fn
75
75
  });
76
76
  };
77
77
 
package/lib/mocha.js CHANGED
@@ -9,7 +9,6 @@
9
9
  var escapeRe = require('escape-string-regexp');
10
10
  var path = require('path');
11
11
  var builtinReporters = require('./reporters');
12
- var growl = require('./nodejs/growl');
13
12
  var utils = require('./utils');
14
13
  var mocharc = require('./mocharc.json');
15
14
  var Suite = require('./suite');
@@ -165,7 +164,6 @@ exports.run = function (...args) {
165
164
  * @param {boolean} [options.fullTrace] - Full stacktrace upon failure?
166
165
  * @param {string[]} [options.global] - Variables expected in global scope.
167
166
  * @param {RegExp|string} [options.grep] - Test filter given regular expression.
168
- * @param {boolean} [options.growl] - Enable desktop notifications?
169
167
  * @param {boolean} [options.inlineDiffs] - Display inline diffs?
170
168
  * @param {boolean} [options.invert] - Invert test filter matches?
171
169
  * @param {boolean} [options.noHighlighting] - Disable syntax highlighting?
@@ -195,7 +193,7 @@ function Mocha(options = {}) {
195
193
  .ui(options.ui)
196
194
  .reporter(
197
195
  options.reporter,
198
- options.reporterOption || options.reporterOptions // for backwards compability
196
+ options.reporterOption || options.reporterOptions // for backwards compatibility
199
197
  )
200
198
  .slow(options.slow)
201
199
  .global(options.global);
@@ -222,7 +220,6 @@ function Mocha(options = {}) {
222
220
  'forbidOnly',
223
221
  'forbidPending',
224
222
  'fullTrace',
225
- 'growl',
226
223
  'inlineDiffs',
227
224
  'invert'
228
225
  ].forEach(function (opt) {
@@ -468,7 +465,7 @@ Mocha.prototype.loadFilesAsync = function () {
468
465
  Mocha.unloadFile = function (file) {
469
466
  if (utils.isBrowser()) {
470
467
  throw createUnsupportedError(
471
- 'unloadFile() is only suported in a Node.js environment'
468
+ 'unloadFile() is only supported in a Node.js environment'
472
469
  );
473
470
  }
474
471
  return require('./nodejs/file-unloader').unloadFile(file);
@@ -647,49 +644,6 @@ Mocha.prototype.fullTrace = function (fullTrace) {
647
644
  return this;
648
645
  };
649
646
 
650
- /**
651
- * Enables desktop notification support if prerequisite software installed.
652
- *
653
- * @public
654
- * @see [CLI option](../#-growl-g)
655
- * @return {Mocha} this
656
- * @chainable
657
- */
658
- Mocha.prototype.growl = function () {
659
- this.options.growl = this.isGrowlCapable();
660
- if (!this.options.growl) {
661
- var detail = utils.isBrowser()
662
- ? 'notification support not available in this browser...'
663
- : 'notification support prerequisites not installed...';
664
- console.error(detail + ' cannot enable!');
665
- }
666
- return this;
667
- };
668
-
669
- /**
670
- * @summary
671
- * Determines if Growl support seems likely.
672
- *
673
- * @description
674
- * <strong>Not available when run in browser.</strong>
675
- *
676
- * @private
677
- * @see {@link Growl#isCapable}
678
- * @see {@link Mocha#growl}
679
- * @return {boolean} whether Growl support can be expected
680
- */
681
- Mocha.prototype.isGrowlCapable = growl.isCapable;
682
-
683
- /**
684
- * Implements desktop notifications using a pseudo-reporter.
685
- *
686
- * @private
687
- * @see {@link Mocha#growl}
688
- * @see {@link Growl#notify}
689
- * @param {Runner} runner - Runner instance.
690
- */
691
- Mocha.prototype._growl = growl.notify;
692
-
693
647
  /**
694
648
  * Specifies whitelist of variable names to be expected in global scope.
695
649
  *
@@ -713,7 +667,7 @@ Mocha.prototype.global = function (global) {
713
667
  });
714
668
  return this;
715
669
  };
716
- // for backwards compability, 'globals' is an alias of 'global'
670
+ // for backwards compatibility, 'globals' is an alias of 'global'
717
671
  Mocha.prototype.globals = Mocha.prototype.global;
718
672
 
719
673
  /**
@@ -1037,9 +991,6 @@ Mocha.prototype.run = function (fn) {
1037
991
  if (options.global) {
1038
992
  runner.globals(options.global);
1039
993
  }
1040
- if (options.growl) {
1041
- this._growl(runner);
1042
- }
1043
994
  if (options.color !== undefined) {
1044
995
  exports.reporters.Base.useColors = options.color;
1045
996
  }
@@ -10,7 +10,7 @@ const formattedImport = async file => {
10
10
  // the location of the syntax error in the error thrown.
11
11
  // This is problematic because the user can't see what file has the problem,
12
12
  // so we add the file location to the error.
13
- // This `if` should be removed once Node.js fixes the problem.
13
+ // TODO: remove once Node.js fixes the problem.
14
14
  if (
15
15
  err instanceof SyntaxError &&
16
16
  err.message &&
@@ -30,64 +30,52 @@ const formattedImport = async file => {
30
30
  return import(file);
31
31
  };
32
32
 
33
- const hasStableEsmImplementation = (() => {
34
- const [major, minor] = process.version.split('.');
35
- // ESM is stable from v12.22.0 onward
36
- // https://nodejs.org/api/esm.html#esm_modules_ecmascript_modules
37
- const majorNumber = parseInt(major.slice(1), 10);
38
- const minorNumber = parseInt(minor, 10);
39
- return majorNumber > 12 || (majorNumber === 12 && minorNumber >= 22);
40
- })();
41
-
42
- exports.requireOrImport = hasStableEsmImplementation
43
- ? async file => {
44
- if (path.extname(file) === '.mjs') {
45
- return formattedImport(file);
46
- }
33
+ exports.requireOrImport = async file => {
34
+ if (path.extname(file) === '.mjs') {
35
+ return formattedImport(file);
36
+ }
37
+ try {
38
+ return dealWithExports(await formattedImport(file));
39
+ } catch (err) {
40
+ if (
41
+ err.code === 'ERR_MODULE_NOT_FOUND' ||
42
+ err.code === 'ERR_UNKNOWN_FILE_EXTENSION' ||
43
+ err.code === 'ERR_UNSUPPORTED_DIR_IMPORT'
44
+ ) {
47
45
  try {
48
- return dealWithExports(await formattedImport(file));
49
- } catch (err) {
46
+ // Importing a file usually works, but the resolution of `import` is the ESM
47
+ // resolution algorithm, and not the CJS resolution algorithm. We may have
48
+ // failed because we tried the ESM resolution, so we try to `require` it.
49
+ return require(file);
50
+ } catch (requireErr) {
50
51
  if (
51
- err.code === 'ERR_MODULE_NOT_FOUND' ||
52
- err.code === 'ERR_UNKNOWN_FILE_EXTENSION' ||
53
- err.code === 'ERR_UNSUPPORTED_DIR_IMPORT'
52
+ requireErr.code === 'ERR_REQUIRE_ESM' ||
53
+ (requireErr instanceof SyntaxError &&
54
+ requireErr
55
+ .toString()
56
+ .includes('Cannot use import statement outside a module'))
54
57
  ) {
55
- try {
56
- // Importing a file usually works, but the resolution of `import` is the ESM
57
- // resolution algorithm, and not the CJS resolution algorithm. So in this case
58
- // if we fail, we may have failed because we tried the ESM resolution and failed
59
- // So we try to `require` it
60
- return require(file);
61
- } catch (requireErr) {
62
- if (
63
- requireErr.code === 'ERR_REQUIRE_ESM' ||
64
- (requireErr instanceof SyntaxError &&
65
- requireErr
66
- .toString()
67
- .includes('Cannot use import statement outside a module'))
68
- ) {
69
- // ERR_REQUIRE_ESM happens when the test file is a JS file, but via type:module is actually ESM,
70
- // AND has an import to a file that doesn't exist.
71
- // This throws an `ERR_MODULE_NOT_FOUND` error above,
72
- // and when we try to `require` it here, it throws an `ERR_REQUIRE_ESM`.
73
- // What we want to do is throw the original error (the `ERR_MODULE_NOT_FOUND`),
74
- // and not the `ERR_REQUIRE_ESM` error, which is a red herring.
75
- //
76
- // SyntaxError happens when in an edge case: when we're using an ESM loader that loads
77
- // a `test.ts` file (i.e. unrecognized extension), and that file includes an unknown
78
- // import (which thows an ERR_MODULE_NOT_FOUND). require-ing it will throw the
79
- // syntax error, because we cannot require a file that has import-s.
80
- throw err;
81
- } else {
82
- throw requireErr;
83
- }
84
- }
85
- } else {
58
+ // ERR_REQUIRE_ESM happens when the test file is a JS file, but via type:module is actually ESM,
59
+ // AND has an import to a file that doesn't exist.
60
+ // This throws an `ERR_MODULE_NOT_FOUND` error above,
61
+ // and when we try to `require` it here, it throws an `ERR_REQUIRE_ESM`.
62
+ // What we want to do is throw the original error (the `ERR_MODULE_NOT_FOUND`),
63
+ // and not the `ERR_REQUIRE_ESM` error, which is a red herring.
64
+ //
65
+ // SyntaxError happens when in an edge case: when we're using an ESM loader that loads
66
+ // a `test.ts` file (i.e. unrecognized extension), and that file includes an unknown
67
+ // import (which throws an ERR_MODULE_NOT_FOUND). `require`-ing it will throw the
68
+ // syntax error, because we cannot require a file that has `import`-s.
86
69
  throw err;
70
+ } else {
71
+ throw requireErr;
87
72
  }
88
73
  }
74
+ } else {
75
+ throw err;
89
76
  }
90
- : implementationOfRequireOrImportForUnstableEsm;
77
+ }
78
+ };
91
79
 
92
80
  function dealWithExports(module) {
93
81
  if (module.default) {
@@ -104,21 +92,3 @@ exports.loadFilesAsync = async (files, preLoadFunc, postLoadFunc) => {
104
92
  postLoadFunc(file, result);
105
93
  }
106
94
  };
107
-
108
- /* istanbul ignore next */
109
- async function implementationOfRequireOrImportForUnstableEsm(file) {
110
- if (path.extname(file) === '.mjs') {
111
- return formattedImport(file);
112
- }
113
- // This is currently the only known way of figuring out whether a file is CJS or ESM in
114
- // Node.js that doesn't necessitate calling `import` first.
115
- try {
116
- return require(file);
117
- } catch (err) {
118
- if (err.code === 'ERR_REQUIRE_ESM') {
119
- return formattedImport(file);
120
- } else {
121
- throw err;
122
- }
123
- }
124
- }
@@ -6,7 +6,6 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- const allSettled = require('@ungap/promise-all-settled').bind(Promise);
10
9
  const Runner = require('../runner');
11
10
  const {EVENT_RUN_BEGIN, EVENT_RUN_END} = Runner.constants;
12
11
  const debug = require('debug')('mocha:parallel:parallel-buffered-runner');
@@ -271,8 +270,9 @@ class ParallelBufferedRunner extends Runner {
271
270
  *
272
271
  * @param {Function} callback - Called with an exit code corresponding to
273
272
  * number of test failures.
274
- * @param {{files: string[], options: Options}} opts - Files to run and
275
- * command-line options, respectively.
273
+ * @param {Object} [opts] - options
274
+ * @param {string[]} opts.files - Files to run
275
+ * @param {Options} opts.options - command-line options
276
276
  */
277
277
  run(callback, {files, options = {}} = {}) {
278
278
  /**
@@ -321,7 +321,7 @@ class ParallelBufferedRunner extends Runner {
321
321
  delete options[opt];
322
322
  });
323
323
 
324
- const results = await allSettled(
324
+ const results = await Promise.allSettled(
325
325
  files.map(this._createFileRunner(pool, options))
326
326
  );
327
327
 
@@ -181,7 +181,7 @@ function HTML(runner, options) {
181
181
  if (indexOfMessage === -1) {
182
182
  stackString = test.err.stack;
183
183
  } else {
184
- stackString = test.err.stack.substr(
184
+ stackString = test.err.stack.slice(
185
185
  test.err.message.length + indexOfMessage
186
186
  );
187
187
  }
@@ -36,7 +36,7 @@ function JSONStream(runner, options) {
36
36
  var total = runner.total;
37
37
 
38
38
  runner.once(EVENT_RUN_BEGIN, function () {
39
- writeEvent(['start', {total: total}]);
39
+ writeEvent(['start', {total}]);
40
40
  });
41
41
 
42
42
  runner.on(EVENT_TEST_PASS, function (test) {
@@ -50,7 +50,7 @@ function Markdown(runner, options) {
50
50
  var ret = obj;
51
51
  var key = SUITE_PREFIX + suite.title;
52
52
 
53
- obj = obj[key] = obj[key] || {suite: suite};
53
+ obj = obj[key] = obj[key] || {suite};
54
54
  suite.suites.forEach(function (suite) {
55
55
  mapTOC(suite, obj);
56
56
  });
package/lib/runner.js CHANGED
@@ -135,27 +135,15 @@ class Runner extends EventEmitter {
135
135
  * @public
136
136
  * @class
137
137
  * @param {Suite} suite - Root suite
138
- * @param {Object|boolean} [opts] - Options. If `boolean` (deprecated), whether to delay execution of root suite until ready.
138
+ * @param {Object} [opts] - Settings object
139
139
  * @param {boolean} [opts.cleanReferencesAfterRun] - Whether to clean references to test fns and hooks when a suite is done.
140
140
  * @param {boolean} [opts.delay] - Whether to delay execution of root suite until ready.
141
141
  * @param {boolean} [opts.dryRun] - Whether to report tests without running them.
142
142
  * @param {boolean} [opts.failZero] - Whether to fail test run if zero tests encountered.
143
143
  */
144
- constructor(suite, opts) {
144
+ constructor(suite, opts = {}) {
145
145
  super();
146
- if (opts === undefined) {
147
- opts = {};
148
- }
149
- if (typeof opts === 'boolean') {
150
- // TODO: remove this
151
- require('./errors').deprecate(
152
- '"Runner(suite: Suite, delay: boolean)" is deprecated. Use "Runner(suite: Suite, {delay: boolean})" instead.'
153
- );
154
- this._delay = opts;
155
- opts = {};
156
- } else {
157
- this._delay = opts.delay;
158
- }
146
+
159
147
  var self = this;
160
148
  this._globals = [];
161
149
  this._abort = false;
@@ -1031,7 +1019,9 @@ Runner.prototype._uncaught = function (err) {
1031
1019
  * @public
1032
1020
  * @memberof Runner
1033
1021
  * @param {Function} fn - Callback when finished
1034
- * @param {{files: string[], options: Options}} [opts] - For subclasses
1022
+ * @param {Object} [opts] - For subclasses
1023
+ * @param {string[]} opts.files - Files to run
1024
+ * @param {Options} opts.options - command-line options
1035
1025
  * @returns {Runner} Runner instance.
1036
1026
  */
1037
1027
  Runner.prototype.run = function (fn, opts = {}) {
@@ -1064,7 +1054,7 @@ Runner.prototype.run = function (fn, opts = {}) {
1064
1054
  debug('run(): filtered exclusive Runnables');
1065
1055
  }
1066
1056
  this.state = constants.STATE_RUNNING;
1067
- if (this._delay) {
1057
+ if (this._opts.delay) {
1068
1058
  this.emit(constants.EVENT_DELAY_END);
1069
1059
  debug('run(): "delay" ended');
1070
1060
  }
@@ -1091,7 +1081,7 @@ Runner.prototype.run = function (fn, opts = {}) {
1091
1081
  this._addEventListener(process, 'uncaughtException', this.uncaught);
1092
1082
  this._addEventListener(process, 'unhandledRejection', this.unhandled);
1093
1083
 
1094
- if (this._delay) {
1084
+ if (this._opts.delay) {
1095
1085
  // for reporters, I guess.
1096
1086
  // might be nice to debounce some dots while we wait.
1097
1087
  this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
package/lib/utils.js CHANGED
@@ -76,7 +76,7 @@ exports.clean = function (str) {
76
76
  .replace(/^\uFEFF/, '')
77
77
  // (traditional)-> space/name parameters body (lambda)-> parameters body multi-statement/single keep body content
78
78
  .replace(
79
- /^function(?:\s*|\s+[^(]*)\([^)]*\)\s*\{((?:.|\n)*?)\s*\}$|^\([^)]*\)\s*=>\s*(?:\{((?:.|\n)*?)\s*\}|((?:.|\n)*))$/,
79
+ /^function(?:\s*|\s[^(]*)\([^)]*\)\s*\{((?:.|\n)*?)\}$|^\([^)]*\)\s*=>\s*(?:\{((?:.|\n)*?)\}|((?:.|\n)*))$/,
80
80
  '$1$2$3'
81
81
  );
82
82