mocha-compat 3.6.4 → 10.8.2
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 +1 -1
- package/README.md +61 -110
- package/bin/_mocha +10 -0
- package/bin/mocha.js +142 -0
- package/browser-entry.js +61 -22
- package/lib/browser/highlight-tags.js +39 -0
- package/lib/browser/parse-query.js +24 -0
- package/lib/{template.html → browser/template.html} +7 -5
- package/lib/cli/cli.js +89 -0
- package/lib/cli/collect-files.js +137 -0
- package/lib/cli/commands.js +14 -0
- package/lib/cli/config.js +100 -0
- package/lib/cli/index.js +3 -0
- package/lib/cli/init.js +36 -0
- package/lib/cli/lookup-files.js +150 -0
- package/lib/cli/node-flags.js +85 -0
- package/lib/cli/one-and-dones.js +69 -0
- package/lib/cli/options.js +284 -0
- package/lib/cli/run-helpers.js +304 -0
- package/lib/cli/run-option-metadata.js +116 -0
- package/lib/cli/run.js +380 -0
- package/lib/cli/watch-run.js +377 -0
- package/lib/context.js +16 -42
- package/lib/errors.js +563 -0
- package/lib/hook.js +50 -9
- package/lib/interfaces/bdd.js +28 -29
- package/lib/interfaces/common.js +56 -21
- package/lib/interfaces/exports.js +4 -7
- package/lib/interfaces/qunit.js +10 -11
- package/lib/interfaces/tdd.js +15 -15
- package/lib/mocha.js +1073 -292
- package/lib/mocharc.json +10 -0
- package/lib/nodejs/buffered-worker-pool.js +188 -0
- package/lib/nodejs/esm-utils.js +106 -0
- package/lib/nodejs/file-unloader.js +15 -0
- package/lib/nodejs/parallel-buffered-runner.js +433 -0
- package/lib/nodejs/reporters/parallel-buffered.js +165 -0
- package/lib/nodejs/serializer.js +414 -0
- package/lib/nodejs/worker.js +151 -0
- package/lib/pending.js +3 -3
- package/lib/plugin-loader.js +286 -0
- package/lib/reporters/base.js +305 -205
- package/lib/reporters/doc.js +52 -21
- package/lib/reporters/dot.js +31 -18
- package/lib/reporters/html.js +153 -81
- package/lib/reporters/json-stream.js +53 -24
- package/lib/reporters/json.js +88 -18
- package/lib/reporters/landing.js +38 -16
- package/lib/reporters/list.js +34 -19
- package/lib/reporters/markdown.js +28 -15
- package/lib/reporters/min.js +22 -8
- package/lib/reporters/nyan.js +62 -58
- package/lib/reporters/progress.js +32 -19
- package/lib/reporters/spec.js +41 -23
- package/lib/reporters/tap.js +255 -32
- package/lib/reporters/xunit.js +89 -39
- package/lib/runnable.js +233 -148
- package/lib/runner.js +679 -380
- package/lib/stats-collector.js +83 -0
- package/lib/suite.js +376 -112
- package/lib/test.js +82 -21
- package/lib/utils.js +364 -477
- package/mocha.css +183 -54
- package/mocha.js +19840 -15846
- package/mocha.js.map +1 -0
- package/package.json +163 -336
- package/{lib/to-iso-string → vendor/serialize-javascript}/LICENSE +8 -6
- package/vendor/serialize-javascript/README.md +10 -0
- package/vendor/serialize-javascript/index.js +349 -0
- package/bin/_mocha-compat +0 -572
- package/bin/mocha-compat +0 -87
- package/bin/options.js +0 -41
- package/bower.json +0 -38
- package/images/error.png +0 -0
- package/images/ok.png +0 -0
- package/lib/browser/.eslintrc.yaml +0 -4
- package/lib/browser/debug.js +0 -7
- package/lib/browser/events.js +0 -195
- package/lib/browser/progress.js +0 -119
- package/lib/browser/tty.js +0 -13
- package/lib/ms.js +0 -130
- package/lib/to-iso-string/index.js +0 -37
- package/vendor/glob/LICENSE +0 -15
- package/vendor/glob/README.md +0 -399
- package/vendor/glob/common.js +0 -244
- package/vendor/glob/glob.js +0 -788
- package/vendor/glob/package.json +0 -55
- package/vendor/glob/sync.js +0 -486
- package/vendor/inflight/LICENSE +0 -15
- package/vendor/inflight/README.md +0 -37
- package/vendor/inflight/inflight.js +0 -54
- package/vendor/inflight/package.json +0 -29
package/lib/cli/cli.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
/**
|
|
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
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const debug = require('debug')('mocha:cli:cli');
|
|
14
|
+
const symbols = require('log-symbols');
|
|
15
|
+
const yargs = require('yargs/yargs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const {
|
|
18
|
+
loadRc,
|
|
19
|
+
loadPkgRc,
|
|
20
|
+
loadOptions,
|
|
21
|
+
YARGS_PARSER_CONFIG
|
|
22
|
+
} = require('./options');
|
|
23
|
+
const lookupFiles = require('./lookup-files');
|
|
24
|
+
const commands = require('./commands');
|
|
25
|
+
const ansi = require('ansi-colors');
|
|
26
|
+
const {repository, homepage, version, discord} = require('../../package.json');
|
|
27
|
+
const {cwd} = require('../utils');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* - Accepts an `Array` of arguments
|
|
31
|
+
* - Modifies {@link https://nodejs.org/api/modules.html#modules_module_paths Node.js' search path} for easy loading of consumer modules
|
|
32
|
+
* - Sets {@linkcode https://nodejs.org/api/errors.html#errors_error_stacktracelimit Error.stackTraceLimit} to `Infinity`
|
|
33
|
+
* @public
|
|
34
|
+
* @summary Mocha's main command-line entry-point.
|
|
35
|
+
* @param {string[]} argv - Array of arguments to parse, or by default the lovely `process.argv.slice(2)`
|
|
36
|
+
* @param {object} [mochaArgs] - Object of already parsed Mocha arguments (by bin/mocha)
|
|
37
|
+
*/
|
|
38
|
+
exports.main = (argv = process.argv.slice(2), mochaArgs) => {
|
|
39
|
+
debug('entered main with raw args', argv);
|
|
40
|
+
// ensure we can require() from current working directory
|
|
41
|
+
if (typeof module.paths !== 'undefined') {
|
|
42
|
+
module.paths.push(cwd(), path.resolve('node_modules'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Error.stackTraceLimit = Infinity; // configurable via --stack-trace-limit?
|
|
46
|
+
|
|
47
|
+
var args = mochaArgs || loadOptions(argv);
|
|
48
|
+
|
|
49
|
+
yargs()
|
|
50
|
+
.scriptName('mocha-compat-10')
|
|
51
|
+
.command(commands.run)
|
|
52
|
+
.command(commands.init)
|
|
53
|
+
.updateStrings({
|
|
54
|
+
'Positionals:': 'Positional Arguments',
|
|
55
|
+
'Options:': 'Other Options',
|
|
56
|
+
'Commands:': 'Commands'
|
|
57
|
+
})
|
|
58
|
+
.fail((msg, err, yargs) => {
|
|
59
|
+
debug('caught error sometime before command handler: %O', err);
|
|
60
|
+
yargs.showHelp();
|
|
61
|
+
console.error(`\n${symbols.error} ${ansi.red('ERROR:')} ${msg}`);
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
})
|
|
64
|
+
.help('help', 'Show usage information & exit')
|
|
65
|
+
.alias('help', 'h')
|
|
66
|
+
.version('version', 'Show version number & exit', version)
|
|
67
|
+
.alias('version', 'V')
|
|
68
|
+
.wrap(process.stdout.columns ? Math.min(process.stdout.columns, 80) : 80)
|
|
69
|
+
.epilog(
|
|
70
|
+
`Mocha Resources
|
|
71
|
+
Chat: ${ansi.magenta(discord)}
|
|
72
|
+
GitHub: ${ansi.blue(repository.url)}
|
|
73
|
+
Docs: ${ansi.yellow(homepage)}
|
|
74
|
+
`
|
|
75
|
+
)
|
|
76
|
+
.parserConfiguration(YARGS_PARSER_CONFIG)
|
|
77
|
+
.config(args)
|
|
78
|
+
.parse(args._);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
exports.lookupFiles = lookupFiles;
|
|
82
|
+
exports.loadOptions = loadOptions;
|
|
83
|
+
exports.loadPkgRc = loadPkgRc;
|
|
84
|
+
exports.loadRc = loadRc;
|
|
85
|
+
|
|
86
|
+
// allow direct execution
|
|
87
|
+
if (require.main === module) {
|
|
88
|
+
exports.main();
|
|
89
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const ansi = require('ansi-colors');
|
|
6
|
+
const debug = require('debug')('mocha:cli:run:helpers');
|
|
7
|
+
const minimatch = require('minimatch');
|
|
8
|
+
const {NO_FILES_MATCH_PATTERN} = require('../errors').constants;
|
|
9
|
+
const lookupFiles = require('./lookup-files');
|
|
10
|
+
const {castArray} = require('../utils');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Exports a function that collects test files from CLI parameters.
|
|
14
|
+
* @see module:lib/cli/run-helpers
|
|
15
|
+
* @see module:lib/cli/watch-run
|
|
16
|
+
* @module
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Smash together an array of test files in the correct order
|
|
22
|
+
* @param {FileCollectionOptions} [opts] - Options
|
|
23
|
+
* @returns {FileCollectionResponse} An object containing a list of files to test and unmatched files.
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
module.exports = ({
|
|
27
|
+
ignore,
|
|
28
|
+
extension,
|
|
29
|
+
file: fileArgs,
|
|
30
|
+
recursive,
|
|
31
|
+
sort,
|
|
32
|
+
spec
|
|
33
|
+
} = {}) => {
|
|
34
|
+
const unmatchedSpecFiles = [];
|
|
35
|
+
const specFiles = spec.reduce((specFiles, arg) => {
|
|
36
|
+
try {
|
|
37
|
+
const moreSpecFiles = castArray(lookupFiles(arg, extension, recursive))
|
|
38
|
+
.filter(filename =>
|
|
39
|
+
ignore.every(
|
|
40
|
+
pattern =>
|
|
41
|
+
!minimatch(filename, pattern, {windowsPathsNoEscape: true})
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
.map(filename => path.resolve(filename));
|
|
45
|
+
return [...specFiles, ...moreSpecFiles];
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (err.code === NO_FILES_MATCH_PATTERN) {
|
|
48
|
+
unmatchedSpecFiles.push({message: err.message, pattern: err.pattern});
|
|
49
|
+
return specFiles;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
// check that each file passed in to --file exists
|
|
57
|
+
|
|
58
|
+
const unmatchedFiles = [];
|
|
59
|
+
fileArgs.forEach(file => {
|
|
60
|
+
const fileAbsolutePath = path.resolve(file);
|
|
61
|
+
try {
|
|
62
|
+
// Used instead of fs.existsSync to ensure that file-ending less files are still resolved correctly
|
|
63
|
+
require.resolve(fileAbsolutePath);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
66
|
+
unmatchedFiles.push({
|
|
67
|
+
pattern: file,
|
|
68
|
+
absolutePath: fileAbsolutePath
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// ensure we don't sort the stuff from fileArgs; order is important!
|
|
78
|
+
if (sort) {
|
|
79
|
+
specFiles.sort();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// add files given through --file to be ran first
|
|
83
|
+
const files = [
|
|
84
|
+
...fileArgs.map(filepath => path.resolve(filepath)),
|
|
85
|
+
...specFiles
|
|
86
|
+
];
|
|
87
|
+
debug('test files (in order): ', files);
|
|
88
|
+
|
|
89
|
+
if (!files.length) {
|
|
90
|
+
// give full message details when only 1 file is missing
|
|
91
|
+
const noneFoundMsg =
|
|
92
|
+
unmatchedSpecFiles.length === 1
|
|
93
|
+
? `Error: No test files found: ${JSON.stringify(
|
|
94
|
+
unmatchedSpecFiles[0].pattern
|
|
95
|
+
)}` // stringify to print escaped characters raw
|
|
96
|
+
: 'Error: No test files found';
|
|
97
|
+
console.error(ansi.red(noneFoundMsg));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
} else {
|
|
100
|
+
// print messages as a warning
|
|
101
|
+
unmatchedSpecFiles.forEach(warning => {
|
|
102
|
+
console.warn(ansi.yellow(`Warning: ${warning.message}`));
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
files,
|
|
108
|
+
unmatchedFiles
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* An object to configure how Mocha gathers test files
|
|
114
|
+
* @private
|
|
115
|
+
* @typedef {Object} FileCollectionOptions
|
|
116
|
+
* @property {string[]} extension - File extensions to use
|
|
117
|
+
* @property {string[]} spec - Files, dirs, globs to run
|
|
118
|
+
* @property {string[]} ignore - Files, dirs, globs to ignore
|
|
119
|
+
* @property {string[]} file - List of additional files to include
|
|
120
|
+
* @property {boolean} recursive - Find files recursively
|
|
121
|
+
* @property {boolean} sort - Sort test files
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Diagnostic object containing unmatched files
|
|
126
|
+
* @typedef {Object} UnmatchedFile -
|
|
127
|
+
* @property {string} absolutePath - A list of unmatched files derived from the file arguments passed in.
|
|
128
|
+
* @property {string} pattern - A list of unmatched files derived from the file arguments passed in.
|
|
129
|
+
*
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Response object containing a list of files to test and unmatched files.
|
|
134
|
+
* @typedef {Object} FileCollectionResponse
|
|
135
|
+
* @property {string[]} files - A list of files to test
|
|
136
|
+
* @property {UnmatchedFile[]} unmatchedFiles - A list of unmatched files derived from the file arguments passed in.
|
|
137
|
+
*/
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Responsible for loading / finding Mocha's "rc" files.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const debug = require('debug')('mocha:cli:config');
|
|
13
|
+
const findUp = require('find-up');
|
|
14
|
+
const {createUnparsableFileError} = require('../errors');
|
|
15
|
+
const utils = require('../utils');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* These are the valid config files, in order of precedence;
|
|
19
|
+
* e.g., if `.mocharc.js` is present, then `.mocharc.yaml` and the rest
|
|
20
|
+
* will be ignored.
|
|
21
|
+
* The user should still be able to explicitly specify a file.
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
exports.CONFIG_FILES = [
|
|
25
|
+
'.mocharc.cjs',
|
|
26
|
+
'.mocharc.js',
|
|
27
|
+
'.mocharc.yaml',
|
|
28
|
+
'.mocharc.yml',
|
|
29
|
+
'.mocharc.jsonc',
|
|
30
|
+
'.mocharc.json'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Parsers for various config filetypes. Each accepts a filepath and
|
|
35
|
+
* returns an object (but could throw)
|
|
36
|
+
*/
|
|
37
|
+
const parsers = (exports.parsers = {
|
|
38
|
+
yaml: filepath => require('js-yaml').load(fs.readFileSync(filepath, 'utf8')),
|
|
39
|
+
js: filepath => {
|
|
40
|
+
let cwdFilepath;
|
|
41
|
+
try {
|
|
42
|
+
debug('parsers: load cwd-relative path: "%s"', path.resolve(filepath));
|
|
43
|
+
cwdFilepath = require.resolve(path.resolve(filepath)); // evtl. throws
|
|
44
|
+
return require(cwdFilepath);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (cwdFilepath) throw err;
|
|
47
|
+
|
|
48
|
+
debug('parsers: retry load as module-relative path: "%s"', filepath);
|
|
49
|
+
return require(filepath);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
json: filepath =>
|
|
53
|
+
JSON.parse(
|
|
54
|
+
require('strip-json-comments')(fs.readFileSync(filepath, 'utf8'))
|
|
55
|
+
)
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Loads and parses, based on file extension, a config file.
|
|
60
|
+
* "JSON" files may have comments.
|
|
61
|
+
*
|
|
62
|
+
* @private
|
|
63
|
+
* @param {string} filepath - Config file path to load
|
|
64
|
+
* @returns {Object} Parsed config object
|
|
65
|
+
*/
|
|
66
|
+
exports.loadConfig = filepath => {
|
|
67
|
+
let config = {};
|
|
68
|
+
debug('loadConfig: trying to parse config at %s', filepath);
|
|
69
|
+
|
|
70
|
+
const ext = path.extname(filepath);
|
|
71
|
+
try {
|
|
72
|
+
if (ext === '.yml' || ext === '.yaml') {
|
|
73
|
+
config = parsers.yaml(filepath);
|
|
74
|
+
} else if (ext === '.js' || ext === '.cjs') {
|
|
75
|
+
config = parsers.js(filepath);
|
|
76
|
+
} else {
|
|
77
|
+
config = parsers.json(filepath);
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
throw createUnparsableFileError(
|
|
81
|
+
`Unable to read/parse ${filepath}: ${err}`,
|
|
82
|
+
filepath
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return config;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Find ("find up") config file starting at `cwd`
|
|
90
|
+
*
|
|
91
|
+
* @param {string} [cwd] - Current working directory
|
|
92
|
+
* @returns {string|null} Filepath to config, if found
|
|
93
|
+
*/
|
|
94
|
+
exports.findConfig = (cwd = utils.cwd()) => {
|
|
95
|
+
const filepath = findUp.sync(exports.CONFIG_FILES, {cwd});
|
|
96
|
+
if (filepath) {
|
|
97
|
+
debug('findConfig: found config file %s', filepath);
|
|
98
|
+
}
|
|
99
|
+
return filepath;
|
|
100
|
+
};
|
package/lib/cli/index.js
ADDED
package/lib/cli/init.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Command module for "init" command
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
exports.command = 'init <path>';
|
|
14
|
+
|
|
15
|
+
exports.description = 'create a client-side Mocha setup at <path>';
|
|
16
|
+
|
|
17
|
+
exports.builder = yargs =>
|
|
18
|
+
yargs.positional('path', {
|
|
19
|
+
type: 'string',
|
|
20
|
+
normalize: true
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
exports.handler = argv => {
|
|
24
|
+
const destdir = argv.path;
|
|
25
|
+
const srcdir = path.join(__dirname, '..', '..');
|
|
26
|
+
fs.mkdirSync(destdir, {recursive: true});
|
|
27
|
+
const css = fs.readFileSync(path.join(srcdir, 'mocha.css'));
|
|
28
|
+
const js = fs.readFileSync(path.join(srcdir, 'mocha.js'));
|
|
29
|
+
const tmpl = fs.readFileSync(
|
|
30
|
+
path.join(srcdir, 'lib', 'browser', 'template.html')
|
|
31
|
+
);
|
|
32
|
+
fs.writeFileSync(path.join(destdir, 'mocha.css'), css);
|
|
33
|
+
fs.writeFileSync(path.join(destdir, 'mocha.js'), js);
|
|
34
|
+
fs.writeFileSync(path.join(destdir, 'tests.spec.js'), '');
|
|
35
|
+
fs.writeFileSync(path.join(destdir, 'index.html'), tmpl);
|
|
36
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Contains `lookupFiles`, which takes some globs/dirs/options and returns a list of files.
|
|
4
|
+
* @module
|
|
5
|
+
* @private
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var fs = require('fs');
|
|
9
|
+
var path = require('path');
|
|
10
|
+
var glob = require('glob');
|
|
11
|
+
var errors = require('../errors');
|
|
12
|
+
var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
|
|
13
|
+
var createMissingArgumentError = errors.createMissingArgumentError;
|
|
14
|
+
const debug = require('debug')('mocha:cli:lookup-files');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Determines if pathname would be a "hidden" file (or directory) on UN*X.
|
|
18
|
+
*
|
|
19
|
+
* @description
|
|
20
|
+
* On UN*X, pathnames beginning with a full stop (aka dot) are hidden during
|
|
21
|
+
* typical usage. Dotfiles, plain-text configuration files, are prime examples.
|
|
22
|
+
*
|
|
23
|
+
* @see {@link http://xahlee.info/UnixResource_dir/writ/unix_origin_of_dot_filename.html|Origin of Dot File Names}
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
* @param {string} pathname - Pathname to check for match.
|
|
27
|
+
* @return {boolean} whether pathname would be considered a hidden file.
|
|
28
|
+
* @example
|
|
29
|
+
* isHiddenOnUnix('.profile'); // => true
|
|
30
|
+
*/
|
|
31
|
+
const isHiddenOnUnix = pathname => path.basename(pathname).startsWith('.');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Determines if pathname has a matching file extension.
|
|
35
|
+
*
|
|
36
|
+
* Supports multi-part extensions.
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
* @param {string} pathname - Pathname to check for match.
|
|
40
|
+
* @param {string[]} exts - List of file extensions, w/-or-w/o leading period
|
|
41
|
+
* @return {boolean} `true` if file extension matches.
|
|
42
|
+
* @example
|
|
43
|
+
* hasMatchingExtname('foo.html', ['js', 'css']); // false
|
|
44
|
+
* hasMatchingExtname('foo.js', ['.js']); // true
|
|
45
|
+
* hasMatchingExtname('foo.js', ['js']); // ture
|
|
46
|
+
*/
|
|
47
|
+
const hasMatchingExtname = (pathname, exts = []) =>
|
|
48
|
+
exts
|
|
49
|
+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
|
|
50
|
+
.some(ext => pathname.endsWith(ext));
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Lookup file names at the given `path`.
|
|
54
|
+
*
|
|
55
|
+
* @description
|
|
56
|
+
* Filenames are returned in _traversal_ order by the OS/filesystem.
|
|
57
|
+
* **Make no assumption that the names will be sorted in any fashion.**
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
* @alias module:lib/cli.lookupFiles
|
|
61
|
+
* @param {string} filepath - Base path to start searching from.
|
|
62
|
+
* @param {string[]} [extensions=[]] - File extensions to look for.
|
|
63
|
+
* @param {boolean} [recursive=false] - Whether to recurse into subdirectories.
|
|
64
|
+
* @return {string[]} An array of paths.
|
|
65
|
+
* @throws {Error} if no files match pattern.
|
|
66
|
+
* @throws {TypeError} if `filepath` is directory and `extensions` not provided.
|
|
67
|
+
*/
|
|
68
|
+
module.exports = function lookupFiles(
|
|
69
|
+
filepath,
|
|
70
|
+
extensions = [],
|
|
71
|
+
recursive = false
|
|
72
|
+
) {
|
|
73
|
+
const files = [];
|
|
74
|
+
let stat;
|
|
75
|
+
|
|
76
|
+
if (!fs.existsSync(filepath)) {
|
|
77
|
+
let pattern;
|
|
78
|
+
if (glob.hasMagic(filepath, {windowsPathsNoEscape: true})) {
|
|
79
|
+
// Handle glob as is without extensions
|
|
80
|
+
pattern = filepath;
|
|
81
|
+
} else {
|
|
82
|
+
// glob pattern e.g. 'filepath+(.js|.ts)'
|
|
83
|
+
const strExtensions = extensions
|
|
84
|
+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
|
|
85
|
+
.join('|');
|
|
86
|
+
pattern = `${filepath}+(${strExtensions})`;
|
|
87
|
+
debug('looking for files using glob pattern: %s', pattern);
|
|
88
|
+
}
|
|
89
|
+
files.push(
|
|
90
|
+
...glob.sync(pattern, {
|
|
91
|
+
nodir: true,
|
|
92
|
+
windowsPathsNoEscape: true
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
if (!files.length) {
|
|
96
|
+
throw createNoFilesMatchPatternError(
|
|
97
|
+
`Cannot find any files matching pattern "${filepath}"`,
|
|
98
|
+
filepath
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return files;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Handle file
|
|
105
|
+
try {
|
|
106
|
+
stat = fs.statSync(filepath);
|
|
107
|
+
if (stat.isFile()) {
|
|
108
|
+
return filepath;
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
// ignore error
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Handle directory
|
|
116
|
+
fs.readdirSync(filepath).forEach(dirent => {
|
|
117
|
+
const pathname = path.join(filepath, dirent);
|
|
118
|
+
let stat;
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
stat = fs.statSync(pathname);
|
|
122
|
+
if (stat.isDirectory()) {
|
|
123
|
+
if (recursive) {
|
|
124
|
+
files.push(...lookupFiles(pathname, extensions, recursive));
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
} catch (ignored) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!extensions.length) {
|
|
132
|
+
throw createMissingArgumentError(
|
|
133
|
+
`Argument '${extensions}' required when argument '${filepath}' is a directory`,
|
|
134
|
+
'extensions',
|
|
135
|
+
'array'
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
!stat.isFile() ||
|
|
141
|
+
!hasMatchingExtname(pathname, extensions) ||
|
|
142
|
+
isHiddenOnUnix(pathname)
|
|
143
|
+
) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
files.push(pathname);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return files;
|
|
150
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Some settings and code related to Mocha's handling of Node.js/V8 flags.
|
|
5
|
+
* @private
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const nodeFlags = process.allowedNodeEnvironmentFlags;
|
|
10
|
+
const {isMochaFlag} = require('./run-option-metadata');
|
|
11
|
+
const unparse = require('yargs-unparser');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* These flags are considered "debug" flags.
|
|
15
|
+
* @see {@link impliesNoTimeouts}
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
const debugFlags = new Set(['inspect', 'inspect-brk']);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Mocha has historical support for various `node` and V8 flags which might not
|
|
22
|
+
* appear in `process.allowedNodeEnvironmentFlags`.
|
|
23
|
+
* These include:
|
|
24
|
+
* - `--preserve-symlinks`
|
|
25
|
+
* - `--harmony-*`
|
|
26
|
+
* - `--gc-global`
|
|
27
|
+
* - `--trace-*`
|
|
28
|
+
* - `--es-staging`
|
|
29
|
+
* - `--use-strict`
|
|
30
|
+
* - `--v8-*` (but *not* `--v8-options`)
|
|
31
|
+
* @summary Whether or not to pass a flag along to the `node` executable.
|
|
32
|
+
* @param {string} flag - Flag to test
|
|
33
|
+
* @param {boolean} [bareword=true] - If `false`, we expect `flag` to have one or two leading dashes.
|
|
34
|
+
* @returns {boolean} If the flag is considered a "Node" flag.
|
|
35
|
+
* @private
|
|
36
|
+
*/
|
|
37
|
+
exports.isNodeFlag = (flag, bareword = true) => {
|
|
38
|
+
if (!bareword) {
|
|
39
|
+
// check if the flag begins with dashes; if not, not a node flag.
|
|
40
|
+
if (!/^--?/.test(flag)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
// strip the leading dashes to match against subsequent checks
|
|
44
|
+
flag = flag.replace(/^--?/, '');
|
|
45
|
+
}
|
|
46
|
+
return (
|
|
47
|
+
// check actual node flags from `process.allowedNodeEnvironmentFlags`,
|
|
48
|
+
// then historical support for various V8 and non-`NODE_OPTIONS` flags
|
|
49
|
+
// and also any V8 flags with `--v8-` prefix
|
|
50
|
+
(!isMochaFlag(flag) && nodeFlags && nodeFlags.has(flag)) ||
|
|
51
|
+
debugFlags.has(flag) ||
|
|
52
|
+
/(?:preserve-symlinks(?:-main)?|harmony(?:[_-]|$)|(?:trace[_-].+$)|gc[_-]global$|es[_-]staging$|use[_-]strict$|v8[_-](?!options).+?$)/.test(
|
|
53
|
+
flag
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Returns `true` if the flag is a "debug-like" flag. These require timeouts
|
|
60
|
+
* to be suppressed, or pausing the debugger on breakpoints will cause test failures.
|
|
61
|
+
* @param {string} flag - Flag to test
|
|
62
|
+
* @returns {boolean}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
exports.impliesNoTimeouts = flag => debugFlags.has(flag);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* All non-strictly-boolean arguments to node--those with values--must specify those values using `=`, e.g., `--inspect=0.0.0.0`.
|
|
69
|
+
* Unparse these arguments using `yargs-unparser` (which would result in `--inspect 0.0.0.0`), then supply `=` where we have values.
|
|
70
|
+
* There's probably an easier or more robust way to do this; fixes welcome
|
|
71
|
+
* @param {Object} opts - Arguments object
|
|
72
|
+
* @returns {string[]} Unparsed arguments using `=` to specify values
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
exports.unparseNodeFlags = opts => {
|
|
76
|
+
var args = unparse(opts);
|
|
77
|
+
return args.length
|
|
78
|
+
? args
|
|
79
|
+
.join(' ')
|
|
80
|
+
.split(/\b/)
|
|
81
|
+
.map(arg => (arg === ' ' ? '=' : arg))
|
|
82
|
+
.join('')
|
|
83
|
+
.split(' ')
|
|
84
|
+
: [];
|
|
85
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contains "command" code for "one-and-dones"--options passed
|
|
5
|
+
* to Mocha which cause it to just dump some info and exit.
|
|
6
|
+
* See {@link module:lib/cli/one-and-dones.ONE_AND_DONE_ARGS ONE_AND_DONE_ARGS} for more info.
|
|
7
|
+
* @module
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const Mocha = require('../mocha');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Dumps a sorted list of the enumerable, lower-case keys of some object
|
|
15
|
+
* to `STDOUT`.
|
|
16
|
+
* @param {Object} obj - Object, ostensibly having some enumerable keys
|
|
17
|
+
* @ignore
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
const showKeys = obj => {
|
|
21
|
+
console.log();
|
|
22
|
+
const keys = Object.keys(obj);
|
|
23
|
+
const maxKeyLength = keys.reduce((max, key) => Math.max(max, key.length), 0);
|
|
24
|
+
keys
|
|
25
|
+
.filter(
|
|
26
|
+
key => /^[a-z]/.test(key) && !obj[key].browserOnly && !obj[key].abstract
|
|
27
|
+
)
|
|
28
|
+
.sort()
|
|
29
|
+
.forEach(key => {
|
|
30
|
+
const description = obj[key].description;
|
|
31
|
+
console.log(
|
|
32
|
+
` ${key.padEnd(maxKeyLength + 1)}${
|
|
33
|
+
description ? `- ${description}` : ''
|
|
34
|
+
}`
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
console.log();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Handlers for one-and-done options
|
|
42
|
+
* @namespace
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
exports.ONE_AND_DONES = {
|
|
46
|
+
/**
|
|
47
|
+
* Dump list of built-in interfaces
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
'list-interfaces': () => {
|
|
51
|
+
showKeys(Mocha.interfaces);
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Dump list of built-in reporters
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
'list-reporters': () => {
|
|
58
|
+
showKeys(Mocha.reporters);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A Set of all one-and-done options
|
|
64
|
+
* @type Set<string>
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
exports.ONE_AND_DONE_ARGS = new Set(
|
|
68
|
+
['help', 'h', 'version', 'V'].concat(Object.keys(exports.ONE_AND_DONES))
|
|
69
|
+
);
|