UNPKG

7.64 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const commander = require("commander");
4const core_1 = require("@stryker-mutator/api/core");
5const initializer_1 = require("./initializer");
6const logging_1 = require("./logging");
7const Stryker_1 = require("./Stryker");
8const OptionsValidator_1 = require("./config/OptionsValidator");
9/**
10 * Interpret a command line argument and add it to an object.
11 * @param object The object to assign the value to.
12 * @param key The property name under which the value needs to be stored.
13 */
14function deepOption(object, key) {
15 return (value) => {
16 object[key] = value;
17 return undefined;
18 };
19}
20function list(val) {
21 return val.split(',');
22}
23function parseBoolean(val) {
24 const v = val.toLocaleLowerCase();
25 return v !== 'false' && v !== '0';
26}
27class StrykerCli {
28 constructor(argv, program = new commander.Command(), runMutationTest = async (options) => new Stryker_1.default(options).runMutationTest()) {
29 this.argv = argv;
30 this.program = program;
31 this.runMutationTest = runMutationTest;
32 this.command = '';
33 this.strykerConfig = null;
34 }
35 run() {
36 const dashboard = {};
37 const defaultValues = OptionsValidator_1.defaultOptions();
38 this.program
39 .version(require('../package.json').version)
40 .usage('<command> [options] [configFile]')
41 .description(`Possible commands:
42 run: Run mutation testing
43 init: Initialize Stryker for your project
44
45 Optional location to a JSON or JavaScript config file as the last argument. If it's a JavaScript file, that file should export the config directly.`)
46 .arguments('<command> [configFile]')
47 .action((cmd, config) => {
48 this.command = cmd;
49 this.strykerConfig = config;
50 })
51 .option('-f, --files <allFiles>', 'A comma separated list of globbing expression used for selecting all files needed to run the tests. For a more detailed way of selecting input files, please use a configFile. Example: node_modules/a-lib/**/*.js,src/**/*.js,!src/index.js,a.js,test/**/*.js', list)
52 .option('-m, --mutate <filesToMutate>', 'A comma separated list of globbing expression used for selecting the files that should be mutated. Example: src/**/*.js,a.js', list)
53 .option('-b, --buildCommand <command>', 'Configure a build command to run after mutating the code, but before mutants are tested. This is generally used to transpile your code before testing.' +
54 " Only configure this if your test runner doesn't take care of this already and you're not using just-in-time transpiler like `babel/register` or `ts-node`.")
55 .option('--coverageAnalysis <perTest|all|off>', `The coverage analysis strategy you want to use. Default value: "${defaultValues.coverageAnalysis}"`)
56 .option('--testRunner <name>', 'The name of the test runner you want to use')
57 .option('--reporters <name>', 'A comma separated list of the names of the reporter(s) you want to use', list)
58 .option('--plugins <listOfPlugins>', 'A list of plugins you want stryker to load (`require`).', list)
59 .option('--appendPlugins <listOfPlugions>', 'A list of additional plugins you want Stryker to load (`require`) without overwriting the (default) `plugins`.', list)
60 .option('--timeoutMS <number>', 'Tweak the absolute timeout used to wait for a test runner to complete', parseInt)
61 .option('--timeoutFactor <number>', 'Tweak the standard deviation relative to the normal test run of a mutated test', parseFloat)
62 .option('--maxConcurrentTestRunners <n>', 'Set the number of max concurrent test runner to spawn (default: cpuCount)', parseInt)
63 .option('-c, --concurrency <n>', 'Set the concurrency of workers. Stryker will always run checkers and test runners in parallel by creating worker processes (default: cpuCount - 1)', parseInt)
64 .option('--maxTestRunnerReuse <n>', 'Restart each forked threads after <n> runs. Not recommended unless you are experiencing memory leaks that you are unable to resolve. (default: 0)', parseInt)
65 .option('--logLevel <level>', `Set the log level for the console. Possible values: fatal, error, warn, info, debug, trace, all and off. Default is "${defaultValues.logLevel}"`)
66 .option('--fileLogLevel <level>', `Set the log4js log level for the "stryker.log" file. Possible values: fatal, error, warn, info, debug, trace, all and off. Default is "${defaultValues.fileLogLevel}"`)
67 .option('--allowConsoleColors <true/false>', 'Indicates whether or not Stryker should use colors in console.', parseBoolean)
68 .option('--dashboard.project <name>', 'Indicates which project name to use if the "dashboard" reporter is enabled. Defaults to the git url configured in the environment of your CI server.', deepOption(dashboard, 'project'))
69 .option('--dashboard.version <version>', 'Indicates which version to use if the "dashboard" reporter is enabled. Defaults to the branch name or tag name configured in the environment of your CI server.', deepOption(dashboard, 'version'))
70 .option('--dashboard.module <name>', 'Indicates which module name to use if the "dashboard" reporter is enabled.', deepOption(dashboard, 'module'))
71 .option('--dashboard.baseUrl <url>', `Indicates which baseUrl to use when reporting to the stryker dashboard. Default: "${defaultValues.dashboard.baseUrl}"`, deepOption(dashboard, 'baseUrl'))
72 .option(`--dashboard.reportType <${core_1.ALL_REPORT_TYPES.join('|')}>`, `Send a full report (inc. source code and mutant results) or only the mutation score. Default: ${defaultValues.dashboard.reportType}`, deepOption(dashboard, 'reportType'))
73 .option('--tempDirName <name>', 'Set the name of the directory that is used by Stryker as a working directory. This directory will be cleaned after a successful run')
74 .option('--cleanTempDir <true/false>', 'Choose whether or not to clean the temp dir (which is ".stryker-tmp" inside the current working directory by default) after a successful run. The temp dir will never be removed when the run failed for some reason (for debugging purposes).', parseBoolean)
75 .parse(this.argv);
76 // Earliest opportunity to configure the log level based on the logLevel argument
77 const options = this.program.opts();
78 logging_1.LogConfigurator.configureMainProcess(options.logLevel);
79 // Cleanup commander state
80 delete options.version;
81 Object.keys(options)
82 .filter((key) => key.startsWith('dashboard.'))
83 .forEach((key) => delete options[key]);
84 if (this.strykerConfig) {
85 options.configFile = this.strykerConfig;
86 }
87 if (Object.keys(dashboard).length > 0) {
88 options.dashboard = dashboard;
89 }
90 const commands = {
91 init: () => initializer_1.initializerFactory().initialize(),
92 run: () => this.runMutationTest(options),
93 };
94 if (Object.keys(commands).includes(this.command)) {
95 const promise = commands[this.command]();
96 promise.catch((err) => {
97 process.exitCode = 1;
98 });
99 }
100 else {
101 console.error('Unknown command: "%s", supported commands: [%s], or use `stryker --help`.', this.command, Object.keys(commands));
102 }
103 }
104}
105exports.default = StrykerCli;
106//# sourceMappingURL=StrykerCli.js.map
\No newline at end of file