1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const commander = require("commander");
|
4 | const core_1 = require("@stryker-mutator/api/core");
|
5 | const initializer_1 = require("./initializer");
|
6 | const logging_1 = require("./logging");
|
7 | const Stryker_1 = require("./Stryker");
|
8 | const OptionsValidator_1 = require("./config/OptionsValidator");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | function deepOption(object, key) {
|
15 | return (value) => {
|
16 | object[key] = value;
|
17 | return undefined;
|
18 | };
|
19 | }
|
20 | function list(val) {
|
21 | return val.split(',');
|
22 | }
|
23 | function parseBoolean(val) {
|
24 | const v = val.toLocaleLowerCase();
|
25 | return v !== 'false' && v !== '0';
|
26 | }
|
27 | class 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 |
|
77 | const options = this.program.opts();
|
78 | logging_1.LogConfigurator.configureMainProcess(options.logLevel);
|
79 |
|
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 | }
|
105 | exports.default = StrykerCli;
|
106 |
|
\ | No newline at end of file |