mocha
Version:
Classic, reliable, trusted test framework for Node.js and the browser
149 lines (125 loc) • 3.89 kB
JavaScript
;
/**
* Definition for Mocha's default ("run tests") command
*
* @module
* @private
*/
const Mocha = require("../mocha.cjs");
const {
createUnsupportedError,
createInvalidArgumentValueError,
createMissingArgumentError,
} = require("../errors.js");
const {
list,
handleRequires,
validateLegacyPlugin,
runMocha,
} = require("./run-helpers.cjs");
const { ONE_AND_DONES } = require("./one-and-dones.js");
const debug = require("debug")("mocha:cli:run");
exports.command = ["$0 [spec..]", "inspect"];
exports.describe = "Run tests with Mocha";
const camelCase = (name) =>
name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
const coerceReporterOption = (opts) =>
list(opts).reduce((acc, opt) => {
const pair = opt.split("=");
if (pair.length > 2 || !pair.length) {
throw createInvalidArgumentValueError(
`invalid reporter option '${opt}'`,
"--reporter-option",
opt,
'expected "key=value" format',
);
}
acc[pair[0]] = pair.length === 2 ? pair[1] : true;
return acc;
}, {});
const normalizeRunOptions = (argv) => {
Object.keys(argv).forEach((name) => {
const reporterOptionMatch = name.match(/^reporter-options?\.(.+)$/);
if (reporterOptionMatch) {
argv["reporter-option"] = Object.assign({}, argv["reporter-option"], {
[reporterOptionMatch[1]]: argv[name],
});
}
if (name.includes("-")) {
const normalizedName = camelCase(name);
if (!(normalizedName in argv)) {
argv[normalizedName] = argv[name];
}
}
});
if (Array.isArray(argv["reporter-option"])) {
argv["reporter-option"] = coerceReporterOption(argv["reporter-option"]);
}
};
const validateRunOptions = (argv) => {
// "one-and-dones"; help and version are handled by the top-level CLI.
const oneAndDoneOptions = Object.keys(ONE_AND_DONES).filter((opt) =>
Boolean(argv[opt]),
);
if (oneAndDoneOptions.length > 1) {
throw createUnsupportedError(
`Arguments ${oneAndDoneOptions.join(" and ")} are mutually exclusive`,
);
}
Object.keys(ONE_AND_DONES).forEach((opt) => {
if (argv[opt]) {
ONE_AND_DONES[opt].call(null);
process.exit(0);
}
});
if (argv.invert && !("fgrep" in argv || "grep" in argv)) {
throw createMissingArgumentError(
'"--invert" requires one of "--fgrep <str>" or "--grep <regexp>"',
"--fgrep|--grep",
"string|regexp",
);
}
if (argv.fgrep && argv.grep) {
throw createUnsupportedError(
"Arguments fgrep and grep are mutually exclusive",
);
}
if (argv.parallel) {
if (argv.file) {
throw createUnsupportedError(
"--parallel runs test files in a non-deterministic order, and is mutually exclusive with --file",
);
}
if (argv.sort) {
throw createUnsupportedError(
"--parallel runs test files in a non-deterministic order, and is mutually exclusive with --sort",
);
}
if (["progress", "markdown", "json-stream"].includes(argv.reporter)) {
throw createUnsupportedError(
`--reporter=${argv.reporter} is mutually exclusive with --parallel`,
);
}
}
};
const prepareRunOptions = async (argv) => {
const plugins = await handleRequires(argv.require);
validateLegacyPlugin(argv, "reporter", Mocha.reporters);
validateLegacyPlugin(argv, "ui", Mocha.interfaces);
Object.assign(argv, plugins);
return argv;
};
exports.validateRunOptions = validateRunOptions;
exports.prepareRunOptions = prepareRunOptions;
exports.normalizeRunOptions = normalizeRunOptions;
exports.handler = async function (argv) {
normalizeRunOptions(argv);
debug("running with config", argv);
const mocha = new Mocha(argv);
try {
await runMocha(mocha, argv);
} catch (err) {
console.error("\n Exception during run:", err);
process.exit(1);
}
};