mocha 8.1.2 → 8.3.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 +99 -1
- package/LICENSE +1 -1
- package/README.md +13 -2
- package/bin/mocha +0 -3
- package/lib/browser/growl.js +1 -1
- package/lib/cli/cli.js +19 -8
- package/lib/cli/collect-files.js +25 -25
- package/lib/cli/config.js +1 -2
- package/lib/cli/index.js +0 -6
- package/lib/cli/lookup-files.js +37 -31
- package/lib/cli/options.js +7 -5
- package/lib/cli/run-helpers.js +21 -56
- package/lib/cli/run.js +5 -9
- package/lib/cli/watch-run.js +55 -30
- package/lib/errors.js +231 -24
- package/lib/esm-utils.js +23 -1
- package/lib/hook.js +14 -9
- package/lib/mocha.js +264 -64
- package/lib/nodejs/buffered-worker-pool.js +1 -3
- package/lib/nodejs/file-unloader.js +15 -0
- package/lib/nodejs/parallel-buffered-runner.js +156 -18
- package/lib/nodejs/reporters/parallel-buffered.js +61 -29
- package/lib/nodejs/serializer.js +14 -6
- package/lib/nodejs/worker.js +9 -12
- package/lib/plugin-loader.js +286 -0
- package/lib/reporters/json-stream.js +2 -1
- package/lib/reporters/json.js +1 -0
- package/lib/runnable.js +13 -8
- package/lib/runner.js +238 -109
- package/lib/suite.js +34 -15
- package/lib/test.js +6 -2
- package/lib/utils.js +151 -63
- package/mocha.js +7866 -3746
- package/mocha.js.map +1 -1
- package/package.json +33 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,107 @@
|
|
|
1
|
+
# 8.3.0 / 2021-02-11
|
|
2
|
+
|
|
3
|
+
## :tada: Enhancements
|
|
4
|
+
|
|
5
|
+
- [#4506](https://github.com/mochajs/mocha/issues/4506): Add error code for test timeout errors ([**@boneskull**](https://github.com/boneskull))
|
|
6
|
+
- [#4112](https://github.com/mochajs/mocha/issues/4112): Add BigInt support to stringify util function ([**@JosejeSinohui**](https://github.com/JosejeSinohui))
|
|
7
|
+
|
|
8
|
+
## :bug: Fixes
|
|
9
|
+
|
|
10
|
+
- [#4557](https://github.com/mochajs/mocha/issues/4557): Add file location when SyntaxError happens in ESM ([**@giltayar**](https://github.com/giltayar))
|
|
11
|
+
- [#4521](https://github.com/mochajs/mocha/issues/4521): Fix `require` error when bundling Mocha with Webpack ([**@devhazem**](https://github.com/devhazem))
|
|
12
|
+
|
|
13
|
+
## :book: Documentation
|
|
14
|
+
|
|
15
|
+
- [#4507](https://github.com/mochajs/mocha/issues/4507): Add support for typescript-style docstrings ([**@boneskull**](https://github.com/boneskull))
|
|
16
|
+
- [#4503](https://github.com/mochajs/mocha/issues/4503): Add GH Actions workflow status badge ([**@outsideris**](https://github.com/outsideris))
|
|
17
|
+
- [#4494](https://github.com/mochajs/mocha/issues/4494): Add example of generating tests dynamically with a closure ([**@maxwellgerber**](https://github.com/maxwellgerber))
|
|
18
|
+
|
|
19
|
+
## :nut_and_bolt: Other
|
|
20
|
+
|
|
21
|
+
- [#4556](https://github.com/mochajs/mocha/issues/4556): Upgrade all dependencies to latest stable ([**@AviVahl**](https://github.com/AviVahl))
|
|
22
|
+
- [#4543](https://github.com/mochajs/mocha/issues/4543): Update dependencies yargs and yargs-parser ([**@juergba**](https://github.com/juergba))
|
|
23
|
+
|
|
24
|
+
Also thanks to [**@outsideris**](https://github.com/outsideris) and [**@HyunSangHan**](https://github.com/HyunSangHan) for various fixes to our website and documentation.
|
|
25
|
+
|
|
26
|
+
# 8.2.1 / 2020-11-02
|
|
27
|
+
|
|
28
|
+
Fixed stuff.
|
|
29
|
+
|
|
30
|
+
## :bug: Fixes
|
|
31
|
+
|
|
32
|
+
- [#4489](https://github.com/mochajs/mocha/issues/4489): Fix problematic handling of otherwise-unhandled `Promise` rejections and erroneous "`done()` called twice" errors ([**@boneskull**](https://github.com/boneskull))
|
|
33
|
+
- [#4496](https://github.com/mochajs/mocha/issues/4496): Avoid `MaxListenersExceededWarning` in watch mode ([**@boneskull**](https://github.com/boneskull))
|
|
34
|
+
|
|
35
|
+
Also thanks to [**@akeating**](https://github.com/akeating) for a documentation fix!
|
|
36
|
+
|
|
37
|
+
# 8.2.0 / 2020-10-16
|
|
38
|
+
|
|
39
|
+
The major feature added in v8.2.0 is addition of support for [_global fixtures_](https://mochajs.org/#global-fixtures).
|
|
40
|
+
|
|
41
|
+
While Mocha has always had the ability to run setup and teardown via a hook (e.g., a `before()` at the top level of a test file) when running tests in serial, Mocha v8.0.0 added support for parallel runs. Parallel runs are _incompatible_ with this strategy; e.g., a top-level `before()` would only run for the file in which it was defined.
|
|
42
|
+
|
|
43
|
+
With [global fixtures](https://mochajs.org/#global-fixtures), Mocha can now perform user-defined setup and teardown _regardless_ of mode, and these fixtures are guaranteed to run _once and only once_. This holds for parallel mode, serial mode, and even "watch" mode (the teardown will run once you hit Ctrl-C, just before Mocha finally exits). Tasks such as starting and stopping servers are well-suited to global fixtures, but not sharing resources--global fixtures do _not_ share context with your test files (but they do share context with each other).
|
|
44
|
+
|
|
45
|
+
Here's a short example of usage:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
// fixtures.js
|
|
49
|
+
|
|
50
|
+
// can be async or not
|
|
51
|
+
exports.mochaGlobalSetup = async function() {
|
|
52
|
+
this.server = await startSomeServer({port: process.env.TEST_PORT});
|
|
53
|
+
console.log(`server running on port ${this.server.port}`);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
exports.mochaGlobalTeardown = async function() {
|
|
57
|
+
// the context (`this`) is shared, but not with the test files
|
|
58
|
+
await this.server.stop();
|
|
59
|
+
console.log(`server on port ${this.server.port} stopped`);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// this file can contain root hook plugins as well!
|
|
63
|
+
// exports.mochaHooks = { ... }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Fixtures are loaded with `--require`, e.g., `mocha --require fixtures.js`.
|
|
67
|
+
|
|
68
|
+
For detailed information, please see the [documentation](https://mochajs.org/#global-fixtures) and this handy-dandy [flowchart](https://mochajs.org/#test-fixture-decision-tree-wizard-thing) to help understand the differences between hooks, root hook plugins, and global fixtures (and when you should use each).
|
|
69
|
+
|
|
70
|
+
## :tada: Enhancements
|
|
71
|
+
|
|
72
|
+
- [#4308](https://github.com/mochajs/mocha/issues/4308): Support run-once [global setup & teardown fixtures](https://mochajs.org/#global-fixtures) ([**@boneskull**](https://github.com/boneskull))
|
|
73
|
+
- [#4442](https://github.com/mochajs/mocha/issues/4442): Multi-part extensions (e.g., `test.js`) now usable with `--extension` option ([**@jordanstephens**](https://github.com/jordanstephens))
|
|
74
|
+
- [#4472](https://github.com/mochajs/mocha/issues/4472): Leading dots (e.g., `.js`, `.test.js`) now usable with `--extension` option ([**@boneskull**](https://github.com/boneskull))
|
|
75
|
+
- [#4434](https://github.com/mochajs/mocha/issues/4434): Output of `json` reporter now contains `speed` ("fast"/"medium"/"slow") property ([**@wwhurin**](https://github.com/wwhurin))
|
|
76
|
+
- [#4464](https://github.com/mochajs/mocha/issues/4464): Errors thrown by serializer in parallel mode now have error codes ([**@evaline-ju**](https://github.com/evaline-ju))
|
|
77
|
+
|
|
78
|
+
_For implementors of custom reporters:_
|
|
79
|
+
|
|
80
|
+
- [#4409](https://github.com/mochajs/mocha/issues/4409): Parallel mode and custom reporter improvements ([**@boneskull**](https://github.com/boneskull)):
|
|
81
|
+
- Support custom worker-process-only reporters (`Runner.prototype.workerReporter()`); reporters should subclass `ParallelBufferedReporter` in `mocha/lib/nodejs/reporters/parallel-buffered`
|
|
82
|
+
- Allow opt-in of object reference matching for "sufficiently advanced" custom reporters (`Runner.prototype.linkPartialObjects()`); use if strict object equality is needed when consuming `Runner` event data
|
|
83
|
+
- Enable detection of parallel mode (`Runner.prototype.isParallelMode()`)
|
|
84
|
+
|
|
85
|
+
## :bug: Fixes
|
|
86
|
+
|
|
87
|
+
- [#4476](https://github.com/mochajs/mocha/issues/4476): Workaround for profoundly bizarre issue affecting `npm` v6.x causing some of Mocha's deps to be installed when `mocha` is present in a package's `devDependencies` and `npm install --production` is run the package's working copy ([**@boneskull**](https://github.com/boneskull))
|
|
88
|
+
- [#4465](https://github.com/mochajs/mocha/issues/4465): Worker processes guaranteed (as opposed to "very likely") to exit before Mocha does; fixes a problem when using `nyc` with Mocha in parallel mode ([**@boneskull**](https://github.com/boneskull))
|
|
89
|
+
- [#4419](https://github.com/mochajs/mocha/issues/4419): Restore `lookupFiles()` in `mocha/lib/utils`, which was broken/missing in Mocha v8.1.0; it now prints a deprecation warning (use `const {lookupFiles} = require('mocha/lib/cli')` instead) ([**@boneskull**](https://github.com/boneskull))
|
|
90
|
+
|
|
91
|
+
Thanks to [**@AviVahl**](https://github.com/AviVahl), [**@donghoon-song**](https://github.com/donghoon-song), [**@ValeriaVG**](https://github.com/ValeriaVG), [**@znarf**](https://github.com/znarf), [**@sujin-park**](https://github.com/sujin-park), and [**@majecty**](https://github.com/majecty) for other helpful contributions!
|
|
92
|
+
|
|
93
|
+
# 8.1.3 / 2020-08-28
|
|
94
|
+
|
|
95
|
+
## :bug: Fixes
|
|
96
|
+
|
|
97
|
+
- [#4425](https://github.com/mochajs/mocha/issues/4425): Restore `Mocha.utils.lookupFiles()` and Webpack compatibility (both broken since v8.1.0); `Mocha.utils.lookupFiles()` is now **deprecated** and will be removed in the next major revision of Mocha; use `require('mocha/lib/cli').lookupFiles` instead ([**@boneskull**](https://github.com/boneskull))
|
|
98
|
+
|
|
1
99
|
# 8.1.2 / 2020-08-25
|
|
2
100
|
|
|
3
101
|
## :bug: Fixes
|
|
4
102
|
|
|
5
103
|
- [#4418](https://github.com/mochajs/mocha/issues/4418): Fix command-line flag incompatibility in forthcoming Node.js v14.9.0 ([**@boneskull**](https://github.com/boneskull))
|
|
6
|
-
- [#4401](https://github.com/mochajs/mocha/issues/4401): Fix missing global variable in browser ([**@
|
|
104
|
+
- [#4401](https://github.com/mochajs/mocha/issues/4401): Fix missing global variable in browser ([**@irrationnelle**](https://github.com/irrationnelle))
|
|
7
105
|
|
|
8
106
|
## :lock: Security Fixes
|
|
9
107
|
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(The MIT License)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2011-
|
|
3
|
+
Copyright (c) 2011-2021 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
|
@@ -4,7 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
<p align="center">☕️ Simple, flexible, fun JavaScript test framework for Node.js & The Browser ☕️</p>
|
|
6
6
|
|
|
7
|
-
<p align="center"
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://github.com/mochajs/mocha/actions?query=workflow%3ATests+branch%3Amaster"><img src="https://github.com/mochajs/mocha/workflows/Tests/badge.svg?branch=master" alt="GitHub Actions Build Status"></a>
|
|
9
|
+
<a href="https://coveralls.io/github/mochajs/mocha"><img src="https://coveralls.io/repos/github/mochajs/mocha/badge.svg" alt="Coverage Status"></a>
|
|
10
|
+
<a href="https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_shield"><img src="https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha.svg?type=shield" alt="FOSSA Status"></a>
|
|
11
|
+
<a href="https://gitter.im/mochajs/mocha?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter"></a>
|
|
12
|
+
<a href="https://github.com/mochajs/mocha#backers"><img src="https://opencollective.com/mochajs/backers/badge.svg" alt="OpenCollective"></a>
|
|
13
|
+
<a href="https://github.com/mochajs/mocha#sponsors"><img src="https://opencollective.com/mochajs/sponsors/badge.svg" alt="OpenCollective"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://www.npmjs.com/package/mocha"><img src="https://img.shields.io/npm/v/mocha.svg" alt="NPM Version"></a>
|
|
18
|
+
<a href="https://github.com/mochajs/mocha"><img src="https://img.shields.io/node/v/mocha.svg" alt="Node Version"></a>
|
|
8
19
|
</p>
|
|
9
20
|
|
|
10
21
|
<p align="center"><br><img alt="Mocha Browser Support h/t SauceLabs" src="https://saucelabs.com/browser-matrix/mochajs.svg" width="354"></p>
|
|
@@ -100,6 +111,6 @@ Finally, come [chat with the maintainers](https://gitter.im/mochajs/contributors
|
|
|
100
111
|
|
|
101
112
|
## License
|
|
102
113
|
|
|
103
|
-
Copyright 2011-
|
|
114
|
+
Copyright 2011-2021 OpenJS Foundation and contributors. Licensed [MIT](https://github.com/mochajs/mocha/blob/master/LICENSE).
|
|
104
115
|
|
|
105
116
|
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_large)
|
package/bin/mocha
CHANGED
|
@@ -36,8 +36,6 @@ const disableTimeouts = value => {
|
|
|
36
36
|
if (impliesNoTimeouts(value)) {
|
|
37
37
|
debug('option %s disabled timeouts', value);
|
|
38
38
|
mochaArgs.timeout = 0;
|
|
39
|
-
delete mochaArgs.timeouts;
|
|
40
|
-
delete mochaArgs.t;
|
|
41
39
|
}
|
|
42
40
|
};
|
|
43
41
|
|
|
@@ -93,7 +91,6 @@ if (mochaArgs.require && mochaArgs.require.includes('esm')) {
|
|
|
93
91
|
if (!mochaArgs.require.length) {
|
|
94
92
|
delete mochaArgs.require;
|
|
95
93
|
}
|
|
96
|
-
delete mochaArgs.r;
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
if (Object.keys(nodeArgs).length) {
|
package/lib/browser/growl.js
CHANGED
package/lib/cli/cli.js
CHANGED
|
@@ -3,19 +3,24 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* Option parsing is handled by {@link https://npm.im/yargs yargs}.
|
|
8
|
-
* If executed via `node`, this module will run {@linkcode module:lib/cli
|
|
9
|
-
*
|
|
10
|
-
* @
|
|
11
|
-
* @module
|
|
6
|
+
* Contains CLI entry point and public API for programmatic usage in Node.js.
|
|
7
|
+
* - Option parsing is handled by {@link https://npm.im/yargs yargs}.
|
|
8
|
+
* - If executed via `node`, this module will run {@linkcode module:lib/cli.main main()}.
|
|
9
|
+
* @public
|
|
10
|
+
* @module lib/cli
|
|
12
11
|
*/
|
|
13
12
|
|
|
14
13
|
const debug = require('debug')('mocha:cli:cli');
|
|
15
14
|
const symbols = require('log-symbols');
|
|
16
15
|
const yargs = require('yargs/yargs');
|
|
17
16
|
const path = require('path');
|
|
18
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
loadRc,
|
|
19
|
+
loadPkgRc,
|
|
20
|
+
loadOptions,
|
|
21
|
+
YARGS_PARSER_CONFIG
|
|
22
|
+
} = require('./options');
|
|
23
|
+
const lookupFiles = require('./lookup-files');
|
|
19
24
|
const commands = require('./commands');
|
|
20
25
|
const ansi = require('ansi-colors');
|
|
21
26
|
const {repository, homepage, version, gitter} = require('../../package.json');
|
|
@@ -25,7 +30,8 @@ const {cwd} = require('../utils');
|
|
|
25
30
|
* - Accepts an `Array` of arguments
|
|
26
31
|
* - Modifies {@link https://nodejs.org/api/modules.html#modules_module_paths Node.js' search path} for easy loading of consumer modules
|
|
27
32
|
* - Sets {@linkcode https://nodejs.org/api/errors.html#errors_error_stacktracelimit Error.stackTraceLimit} to `Infinity`
|
|
28
|
-
* @
|
|
33
|
+
* @public
|
|
34
|
+
* @summary Mocha's main command-line entry-point.
|
|
29
35
|
* @param {string[]} argv - Array of arguments to parse, or by default the lovely `process.argv.slice(2)`
|
|
30
36
|
*/
|
|
31
37
|
exports.main = (argv = process.argv.slice(2)) => {
|
|
@@ -71,6 +77,11 @@ exports.main = (argv = process.argv.slice(2)) => {
|
|
|
71
77
|
.parse(args._);
|
|
72
78
|
};
|
|
73
79
|
|
|
80
|
+
exports.lookupFiles = lookupFiles;
|
|
81
|
+
exports.loadOptions = loadOptions;
|
|
82
|
+
exports.loadPkgRc = loadPkgRc;
|
|
83
|
+
exports.loadRc = loadRc;
|
|
84
|
+
|
|
74
85
|
// allow direct execution
|
|
75
86
|
if (require.main === module) {
|
|
76
87
|
exports.main();
|
package/lib/cli/collect-files.js
CHANGED
|
@@ -6,6 +6,7 @@ const debug = require('debug')('mocha:cli:run:helpers');
|
|
|
6
6
|
const minimatch = require('minimatch');
|
|
7
7
|
const {NO_FILES_MATCH_PATTERN} = require('../errors').constants;
|
|
8
8
|
const lookupFiles = require('./lookup-files');
|
|
9
|
+
const {castArray} = require('../utils');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Exports a function that collects test files from CLI parameters.
|
|
@@ -21,45 +22,44 @@ const lookupFiles = require('./lookup-files');
|
|
|
21
22
|
* @returns {string[]} List of files to test
|
|
22
23
|
* @private
|
|
23
24
|
*/
|
|
24
|
-
module.exports = ({
|
|
25
|
-
|
|
25
|
+
module.exports = ({
|
|
26
|
+
ignore,
|
|
27
|
+
extension,
|
|
28
|
+
file: fileArgs,
|
|
29
|
+
recursive,
|
|
30
|
+
sort,
|
|
31
|
+
spec
|
|
32
|
+
} = {}) => {
|
|
26
33
|
const unmatched = [];
|
|
27
|
-
spec.
|
|
28
|
-
let newFiles;
|
|
34
|
+
const specFiles = spec.reduce((specFiles, arg) => {
|
|
29
35
|
try {
|
|
30
|
-
|
|
36
|
+
const moreSpecFiles = castArray(lookupFiles(arg, extension, recursive))
|
|
37
|
+
.filter(filename =>
|
|
38
|
+
ignore.every(pattern => !minimatch(filename, pattern))
|
|
39
|
+
)
|
|
40
|
+
.map(filename => path.resolve(filename));
|
|
41
|
+
return [...specFiles, ...moreSpecFiles];
|
|
31
42
|
} catch (err) {
|
|
32
43
|
if (err.code === NO_FILES_MATCH_PATTERN) {
|
|
33
44
|
unmatched.push({message: err.message, pattern: err.pattern});
|
|
34
|
-
return;
|
|
45
|
+
return specFiles;
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
throw err;
|
|
38
49
|
}
|
|
39
|
-
|
|
40
|
-
if (typeof newFiles !== 'undefined') {
|
|
41
|
-
if (typeof newFiles === 'string') {
|
|
42
|
-
newFiles = [newFiles];
|
|
43
|
-
}
|
|
44
|
-
newFiles = newFiles.filter(fileName =>
|
|
45
|
-
ignore.every(pattern => !minimatch(fileName, pattern))
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
files = files.concat(newFiles);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const fileArgs = file.map(filepath => path.resolve(filepath));
|
|
53
|
-
files = files.map(filepath => path.resolve(filepath));
|
|
50
|
+
}, []);
|
|
54
51
|
|
|
55
52
|
// ensure we don't sort the stuff from fileArgs; order is important!
|
|
56
53
|
if (sort) {
|
|
57
|
-
|
|
54
|
+
specFiles.sort();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
// add files given through --file to be ran first
|
|
61
|
-
files =
|
|
62
|
-
|
|
58
|
+
const files = [
|
|
59
|
+
...fileArgs.map(filepath => path.resolve(filepath)),
|
|
60
|
+
...specFiles
|
|
61
|
+
];
|
|
62
|
+
debug('test files (in order): ', files);
|
|
63
63
|
|
|
64
64
|
if (!files.length) {
|
|
65
65
|
// give full message details when only 1 file is missing
|
|
@@ -70,7 +70,7 @@ module.exports = ({ignore, extension, file, recursive, sort, spec} = {}) => {
|
|
|
70
70
|
console.error(ansi.red(noneFoundMsg));
|
|
71
71
|
process.exit(1);
|
|
72
72
|
} else {
|
|
73
|
-
// print messages as
|
|
73
|
+
// print messages as a warning
|
|
74
74
|
unmatched.forEach(warning => {
|
|
75
75
|
console.warn(ansi.yellow(`Warning: ${warning.message}`));
|
|
76
76
|
});
|
package/lib/cli/config.js
CHANGED
|
@@ -38,8 +38,7 @@ const isModuleNotFoundError = err =>
|
|
|
38
38
|
* returns an object (but could throw)
|
|
39
39
|
*/
|
|
40
40
|
const parsers = (exports.parsers = {
|
|
41
|
-
yaml: filepath =>
|
|
42
|
-
require('js-yaml').safeLoad(fs.readFileSync(filepath, 'utf8')),
|
|
41
|
+
yaml: filepath => require('js-yaml').load(fs.readFileSync(filepath, 'utf8')),
|
|
43
42
|
js: filepath => {
|
|
44
43
|
const cwdFilepath = path.resolve(filepath);
|
|
45
44
|
try {
|
package/lib/cli/index.js
CHANGED
package/lib/cli/lookup-files.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Contains `lookupFiles`, which takes some globs/dirs/options and returns a list of files.
|
|
4
|
+
* @module
|
|
5
|
+
* @private
|
|
6
|
+
*/
|
|
2
7
|
|
|
3
8
|
var fs = require('fs');
|
|
4
9
|
var path = require('path');
|
|
@@ -8,6 +13,7 @@ var errors = require('../errors');
|
|
|
8
13
|
var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
|
|
9
14
|
var createMissingArgumentError = errors.createMissingArgumentError;
|
|
10
15
|
var {sQuote, dQuote} = require('../utils');
|
|
16
|
+
const debug = require('debug')('mocha:cli:lookup-files');
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* Determines if pathname would be a "hidden" file (or directory) on UN*X.
|
|
@@ -24,26 +30,26 @@ var {sQuote, dQuote} = require('../utils');
|
|
|
24
30
|
* @example
|
|
25
31
|
* isHiddenOnUnix('.profile'); // => true
|
|
26
32
|
*/
|
|
27
|
-
|
|
28
|
-
return path.basename(pathname)[0] === '.';
|
|
29
|
-
}
|
|
33
|
+
const isHiddenOnUnix = pathname => path.basename(pathname).startsWith('.');
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Determines if pathname has a matching file extension.
|
|
33
37
|
*
|
|
38
|
+
* Supports multi-part extensions.
|
|
39
|
+
*
|
|
34
40
|
* @private
|
|
35
41
|
* @param {string} pathname - Pathname to check for match.
|
|
36
|
-
* @param {string[]} exts - List of file extensions
|
|
37
|
-
* @return {boolean}
|
|
42
|
+
* @param {string[]} exts - List of file extensions, w/-or-w/o leading period
|
|
43
|
+
* @return {boolean} `true` if file extension matches.
|
|
38
44
|
* @example
|
|
39
|
-
* hasMatchingExtname('foo.html', ['js', 'css']); //
|
|
45
|
+
* hasMatchingExtname('foo.html', ['js', 'css']); // false
|
|
46
|
+
* hasMatchingExtname('foo.js', ['.js']); // true
|
|
47
|
+
* hasMatchingExtname('foo.js', ['js']); // ture
|
|
40
48
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
-
}
|
|
49
|
+
const hasMatchingExtname = (pathname, exts = []) =>
|
|
50
|
+
exts
|
|
51
|
+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
|
|
52
|
+
.some(ext => pathname.endsWith(ext));
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* Lookup file names at the given `path`.
|
|
@@ -53,7 +59,7 @@ function hasMatchingExtname(pathname, exts) {
|
|
|
53
59
|
* **Make no assumption that the names will be sorted in any fashion.**
|
|
54
60
|
*
|
|
55
61
|
* @public
|
|
56
|
-
* @
|
|
62
|
+
* @alias module:lib/cli.lookupFiles
|
|
57
63
|
* @param {string} filepath - Base path to start searching from.
|
|
58
64
|
* @param {string[]} [extensions=[]] - File extensions to look for.
|
|
59
65
|
* @param {boolean} [recursive=false] - Whether to recurse into subdirectories.
|
|
@@ -61,27 +67,28 @@ function hasMatchingExtname(pathname, exts) {
|
|
|
61
67
|
* @throws {Error} if no files match pattern.
|
|
62
68
|
* @throws {TypeError} if `filepath` is directory and `extensions` not provided.
|
|
63
69
|
*/
|
|
64
|
-
module.exports = function lookupFiles(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
module.exports = function lookupFiles(
|
|
71
|
+
filepath,
|
|
72
|
+
extensions = [],
|
|
73
|
+
recursive = false
|
|
74
|
+
) {
|
|
75
|
+
const files = [];
|
|
76
|
+
let stat;
|
|
69
77
|
|
|
70
78
|
if (!fs.existsSync(filepath)) {
|
|
71
|
-
|
|
79
|
+
let pattern;
|
|
72
80
|
if (glob.hasMagic(filepath)) {
|
|
73
81
|
// Handle glob as is without extensions
|
|
74
82
|
pattern = filepath;
|
|
75
83
|
} else {
|
|
76
84
|
// glob pattern e.g. 'filepath+(.js|.ts)'
|
|
77
|
-
|
|
78
|
-
.map(
|
|
79
|
-
return '.' + v;
|
|
80
|
-
})
|
|
85
|
+
const strExtensions = extensions
|
|
86
|
+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
|
|
81
87
|
.join('|');
|
|
82
|
-
pattern = filepath
|
|
88
|
+
pattern = `${filepath}+(${strExtensions})`;
|
|
89
|
+
debug('looking for files using glob pattern: %s', pattern);
|
|
83
90
|
}
|
|
84
|
-
files
|
|
91
|
+
files.push(...glob.sync(pattern, {nodir: true}));
|
|
85
92
|
if (!files.length) {
|
|
86
93
|
throw createNoFilesMatchPatternError(
|
|
87
94
|
'Cannot find any files matching pattern ' + dQuote(filepath),
|
|
@@ -103,20 +110,19 @@ module.exports = function lookupFiles(filepath, extensions, recursive) {
|
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
// Handle directory
|
|
106
|
-
fs.readdirSync(filepath).forEach(
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
fs.readdirSync(filepath).forEach(dirent => {
|
|
114
|
+
const pathname = path.join(filepath, dirent);
|
|
115
|
+
let stat;
|
|
109
116
|
|
|
110
117
|
try {
|
|
111
118
|
stat = fs.statSync(pathname);
|
|
112
119
|
if (stat.isDirectory()) {
|
|
113
120
|
if (recursive) {
|
|
114
|
-
files
|
|
121
|
+
files.push(...lookupFiles(pathname, extensions, recursive));
|
|
115
122
|
}
|
|
116
123
|
return;
|
|
117
124
|
}
|
|
118
|
-
} catch (
|
|
119
|
-
// ignore error
|
|
125
|
+
} catch (ignored) {
|
|
120
126
|
return;
|
|
121
127
|
}
|
|
122
128
|
if (!extensions.length) {
|
package/lib/cli/options.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Main entry point for handling filesystem-based configuration,
|
|
5
5
|
* whether that's a config file or `package.json` or whatever.
|
|
6
|
-
* @module
|
|
6
|
+
* @module lib/cli/options
|
|
7
|
+
* @private
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
const fs = require('fs');
|
|
@@ -37,7 +38,8 @@ const {isNodeFlag} = require('./node-flags');
|
|
|
37
38
|
const YARGS_PARSER_CONFIG = {
|
|
38
39
|
'combine-arrays': true,
|
|
39
40
|
'short-option-groups': false,
|
|
40
|
-
'dot-notation': false
|
|
41
|
+
'dot-notation': false,
|
|
42
|
+
'strip-aliased': true
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
/**
|
|
@@ -150,7 +152,7 @@ const parse = (args = [], defaultValues = {}, ...configObjects) => {
|
|
|
150
152
|
* @param {Object} [args] - Arguments object
|
|
151
153
|
* @param {string|boolean} [args.config] - Path to config file or `false` to skip
|
|
152
154
|
* @public
|
|
153
|
-
* @
|
|
155
|
+
* @alias module:lib/cli.loadRc
|
|
154
156
|
* @returns {external:yargsParser.Arguments|void} Parsed config, or nothing if `args.config` is `false`
|
|
155
157
|
*/
|
|
156
158
|
const loadRc = (args = {}) => {
|
|
@@ -167,7 +169,7 @@ module.exports.loadRc = loadRc;
|
|
|
167
169
|
* @param {Object} [args] - Arguments object
|
|
168
170
|
* @param {string|boolean} [args.config] - Path to `package.json` or `false` to skip
|
|
169
171
|
* @public
|
|
170
|
-
* @
|
|
172
|
+
* @alias module:lib/cli.loadPkgRc
|
|
171
173
|
* @returns {external:yargsParser.Arguments|void} Parsed config, or nothing if `args.package` is `false`
|
|
172
174
|
*/
|
|
173
175
|
const loadPkgRc = (args = {}) => {
|
|
@@ -210,7 +212,7 @@ module.exports.loadPkgRc = loadPkgRc;
|
|
|
210
212
|
* @summary Parses options read from `.mocharc.*` and `package.json`.
|
|
211
213
|
* @param {string|string[]} [argv] - Arguments to parse
|
|
212
214
|
* @public
|
|
213
|
-
* @
|
|
215
|
+
* @alias module:lib/cli.loadOptions
|
|
214
216
|
* @returns {external:yargsParser.Arguments} Parsed args from everything
|
|
215
217
|
*/
|
|
216
218
|
const loadOptions = (argv = []) => {
|
package/lib/cli/run-helpers.js
CHANGED
|
@@ -12,10 +12,10 @@ const path = require('path');
|
|
|
12
12
|
const debug = require('debug')('mocha:cli:run:helpers');
|
|
13
13
|
const {watchRun, watchParallelRun} = require('./watch-run');
|
|
14
14
|
const collectFiles = require('./collect-files');
|
|
15
|
-
const {type} = require('../utils');
|
|
16
15
|
const {format} = require('util');
|
|
17
|
-
const {
|
|
16
|
+
const {createInvalidLegacyPluginError} = require('../errors');
|
|
18
17
|
const {requireOrImport} = require('../esm-utils');
|
|
18
|
+
const PluginLoader = require('../plugin-loader');
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Exits Mocha when tests + code under test has finished execution (default)
|
|
@@ -79,12 +79,12 @@ exports.list = str =>
|
|
|
79
79
|
*
|
|
80
80
|
* Returns array of `mochaHooks` exports, if any.
|
|
81
81
|
* @param {string[]} requires - Modules to require
|
|
82
|
-
* @returns {Promise<
|
|
82
|
+
* @returns {Promise<object>} Plugin implementations
|
|
83
83
|
* @private
|
|
84
84
|
*/
|
|
85
|
-
exports.handleRequires = async (requires = []) => {
|
|
86
|
-
const
|
|
87
|
-
for (const mod of requires) {
|
|
85
|
+
exports.handleRequires = async (requires = [], {ignoredPlugins = []} = {}) => {
|
|
86
|
+
const pluginLoader = PluginLoader.create({ignore: ignoredPlugins});
|
|
87
|
+
for await (const mod of requires) {
|
|
88
88
|
let modpath = mod;
|
|
89
89
|
// this is relative to cwd
|
|
90
90
|
if (fs.existsSync(mod) || fs.existsSync(`${mod}.js`)) {
|
|
@@ -92,49 +92,18 @@ exports.handleRequires = async (requires = []) => {
|
|
|
92
92
|
debug('resolved required file %s to %s', mod, modpath);
|
|
93
93
|
}
|
|
94
94
|
const requiredModule = await requireOrImport(modpath);
|
|
95
|
-
if (
|
|
96
|
-
requiredModule
|
|
97
|
-
|
|
98
|
-
requiredModule.mochaHooks
|
|
99
|
-
) {
|
|
100
|
-
const mochaHooksType = type(requiredModule.mochaHooks);
|
|
101
|
-
if (/function$/.test(mochaHooksType) || mochaHooksType === 'object') {
|
|
102
|
-
debug('found root hooks in required file %s', mod);
|
|
103
|
-
acc.push(requiredModule.mochaHooks);
|
|
104
|
-
} else {
|
|
105
|
-
throw createUnsupportedError(
|
|
106
|
-
'mochaHooks must be an object or a function returning (or fulfilling with) an object'
|
|
107
|
-
);
|
|
95
|
+
if (requiredModule && typeof requiredModule === 'object') {
|
|
96
|
+
if (pluginLoader.load(requiredModule)) {
|
|
97
|
+
debug('found one or more plugin implementations in %s', modpath);
|
|
108
98
|
}
|
|
109
99
|
}
|
|
110
100
|
debug('loaded required module "%s"', mod);
|
|
111
101
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* These can be sync/async functions returning objects, or just objects.
|
|
118
|
-
* Flattens to a single object.
|
|
119
|
-
* @param {Array<MochaRootHookObject|MochaRootHookFunction>} rootHooks - Array of root hooks
|
|
120
|
-
* @private
|
|
121
|
-
* @returns {MochaRootHookObject}
|
|
122
|
-
*/
|
|
123
|
-
exports.loadRootHooks = async rootHooks => {
|
|
124
|
-
const rootHookObjects = await Promise.all(
|
|
125
|
-
rootHooks.map(async hook => (/function$/.test(type(hook)) ? hook() : hook))
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
return rootHookObjects.reduce(
|
|
129
|
-
(acc, hook) => {
|
|
130
|
-
acc.beforeAll = acc.beforeAll.concat(hook.beforeAll || []);
|
|
131
|
-
acc.beforeEach = acc.beforeEach.concat(hook.beforeEach || []);
|
|
132
|
-
acc.afterAll = acc.afterAll.concat(hook.afterAll || []);
|
|
133
|
-
acc.afterEach = acc.afterEach.concat(hook.afterEach || []);
|
|
134
|
-
return acc;
|
|
135
|
-
},
|
|
136
|
-
{beforeAll: [], beforeEach: [], afterAll: [], afterEach: []}
|
|
137
|
-
);
|
|
102
|
+
const plugins = await pluginLoader.finalize();
|
|
103
|
+
if (Object.keys(plugins).length) {
|
|
104
|
+
debug('finalized plugin implementations: %O', plugins);
|
|
105
|
+
}
|
|
106
|
+
return plugins;
|
|
138
107
|
};
|
|
139
108
|
|
|
140
109
|
/**
|
|
@@ -172,11 +141,7 @@ const singleRun = async (mocha, {exit}, fileCollectParams) => {
|
|
|
172
141
|
*/
|
|
173
142
|
const parallelRun = async (mocha, options, fileCollectParams) => {
|
|
174
143
|
const files = collectFiles(fileCollectParams);
|
|
175
|
-
debug(
|
|
176
|
-
'executing %d test file(s) across %d concurrent jobs',
|
|
177
|
-
files.length,
|
|
178
|
-
options.jobs
|
|
179
|
-
);
|
|
144
|
+
debug('executing %d test file(s) in parallel mode', files.length);
|
|
180
145
|
mocha.files = files;
|
|
181
146
|
|
|
182
147
|
// note that we DO NOT load any files here; this is handled by the worker
|
|
@@ -236,7 +201,7 @@ exports.runMocha = async (mocha, options) => {
|
|
|
236
201
|
* name
|
|
237
202
|
* @private
|
|
238
203
|
*/
|
|
239
|
-
exports.
|
|
204
|
+
exports.validateLegacyPlugin = (opts, pluginType, map = {}) => {
|
|
240
205
|
/**
|
|
241
206
|
* This should be a unique identifier; either a string (present in `map`),
|
|
242
207
|
* or a resolvable (via `require.resolve`) module ID/path.
|
|
@@ -245,14 +210,14 @@ exports.validatePlugin = (opts, pluginType, map = {}) => {
|
|
|
245
210
|
const pluginId = opts[pluginType];
|
|
246
211
|
|
|
247
212
|
if (Array.isArray(pluginId)) {
|
|
248
|
-
throw
|
|
213
|
+
throw createInvalidLegacyPluginError(
|
|
249
214
|
`"--${pluginType}" can only be specified once`,
|
|
250
215
|
pluginType
|
|
251
216
|
);
|
|
252
217
|
}
|
|
253
218
|
|
|
254
|
-
const
|
|
255
|
-
|
|
219
|
+
const createUnknownError = err =>
|
|
220
|
+
createInvalidLegacyPluginError(
|
|
256
221
|
format('Could not load %s "%s":\n\n %O', pluginType, pluginId, err),
|
|
257
222
|
pluginType,
|
|
258
223
|
pluginId
|
|
@@ -268,10 +233,10 @@ exports.validatePlugin = (opts, pluginType, map = {}) => {
|
|
|
268
233
|
try {
|
|
269
234
|
opts[pluginType] = require(path.resolve(pluginId));
|
|
270
235
|
} catch (err) {
|
|
271
|
-
throw
|
|
236
|
+
throw createUnknownError(err);
|
|
272
237
|
}
|
|
273
238
|
} else {
|
|
274
|
-
throw
|
|
239
|
+
throw createUnknownError(err);
|
|
275
240
|
}
|
|
276
241
|
}
|
|
277
242
|
}
|