1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const commander = require("commander");
|
4 | const log4js_1 = require("log4js");
|
5 | const core_1 = require("@stryker-mutator/api/core");
|
6 | const initializer_1 = require("./initializer");
|
7 | const LogConfigurator_1 = require("./logging/LogConfigurator");
|
8 | const Stryker_1 = require("./Stryker");
|
9 | const OptionsValidator_1 = require("./config/OptionsValidator");
|
10 | const errors_1 = require("./errors");
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | function deepOption(object, key) {
|
17 | return (value) => {
|
18 | object[key] = value;
|
19 | return undefined;
|
20 | };
|
21 | }
|
22 | function list(val) {
|
23 | return val.split(',');
|
24 | }
|
25 | function parseBoolean(val) {
|
26 | const v = val.toLocaleLowerCase();
|
27 | return v !== 'false' && v !== '0';
|
28 | }
|
29 | class StrykerCli {
|
30 | constructor(argv, program = new commander.Command(), runMutationTest = async (options) => new Stryker_1.default(options).runMutationTest(), log = log4js_1.getLogger(StrykerCli.name)) {
|
31 | this.argv = argv;
|
32 | this.program = program;
|
33 | this.runMutationTest = runMutationTest;
|
34 | this.log = log;
|
35 | this.command = '';
|
36 | this.strykerConfig = null;
|
37 | }
|
38 | run() {
|
39 | const dashboard = {};
|
40 | const defaultValues = OptionsValidator_1.defaultOptions();
|
41 | this.program
|
42 | .version(require('../package.json').version)
|
43 | .usage('<command> [options] [configFile]')
|
44 | .description(`Possible commands:
|
45 | run: Run mutation testing
|
46 | init: Initialize Stryker for your project
|
47 |
|
48 | 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.`)
|
49 | .arguments('<command> [configFile]')
|
50 | .action((cmd, config) => {
|
51 | this.command = cmd;
|
52 | this.strykerConfig = config;
|
53 | })
|
54 | .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.
|
55 | Example: node_modules/a-lib/**/*.js,src/**/*.js,!src/index.js,a.js,test/**/*.js`, list)
|
56 | .option('-m, --mutate <filesToMutate>', `A comma separated list of globbing expression used for selecting the files that should be mutated.
|
57 | Example: src/**/*.js,a.js`, list)
|
58 | .option('--coverageAnalysis <perTest|all|off>', `The coverage analysis strategy you want to use. Default value: "${defaultValues.coverageAnalysis}"`)
|
59 | .option('--testFramework <name>', 'The name of the test framework you want to use.')
|
60 | .option('--testRunner <name>', 'The name of the test runner you want to use')
|
61 | .option('--mutator <name>', 'The name of the mutant generator you want to use')
|
62 | .option('--transpilers <listOfTranspilers>', 'A comma separated list of transpilers to use.', list)
|
63 | .option('--reporters <name>', 'A comma separated list of the names of the reporter(s) you want to use', list)
|
64 | .option('--plugins <listOfPlugins>', 'A list of plugins you want stryker to load (`require`).', list)
|
65 | .option('--timeoutMS <number>', 'Tweak the absolute timeout used to wait for a test runner to complete', parseInt)
|
66 | .option('--timeoutFactor <number>', 'Tweak the standard deviation relative to the normal test run of a mutated test', parseFloat)
|
67 | .option('--maxConcurrentTestRunners <n>', 'Set the number of max concurrent test runner to spawn (default: cpuCount)', parseInt)
|
68 | .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}"`)
|
69 | .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}"`)
|
70 | .option('--allowConsoleColors <true/false>', 'Indicates whether or not Stryker should use colors in console.', parseBoolean)
|
71 | .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'))
|
72 | .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'))
|
73 | .option('--dashboard.module <name>', 'Indicates which module name to use if the "dashboard" reporter is enabled.', deepOption(dashboard, 'module'))
|
74 | .option('--dashboard.baseUrl <url>', `Indicates which baseUrl to use when reporting to the stryker dashboard. Default: "${defaultValues.dashboard.baseUrl}"`, deepOption(dashboard, 'baseUrl'))
|
75 | .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'))
|
76 | .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')
|
77 | .parse(this.argv);
|
78 |
|
79 | const options = this.program.opts();
|
80 | LogConfigurator_1.default.configureMainProcess(options.logLevel);
|
81 |
|
82 | delete options.version;
|
83 | Object.keys(options)
|
84 | .filter((key) => key.startsWith('dashboard.'))
|
85 | .forEach((key) => delete options[key]);
|
86 | if (this.strykerConfig) {
|
87 | options.configFile = this.strykerConfig;
|
88 | }
|
89 | if (Object.keys(dashboard).length > 0) {
|
90 | options.dashboard = dashboard;
|
91 | }
|
92 | const commands = {
|
93 | init: () => initializer_1.initializerFactory().initialize(),
|
94 | run: () => this.runMutationTest(options),
|
95 | };
|
96 | if (Object.keys(commands).includes(this.command)) {
|
97 | commands[this.command]().catch((err) => {
|
98 | const error = errors_1.retrieveCause(err);
|
99 | if (error instanceof errors_1.ConfigError) {
|
100 | this.log.error(error.message);
|
101 | }
|
102 | else {
|
103 | this.log.error('an error occurred', err);
|
104 | if (!this.log.isTraceEnabled()) {
|
105 | this.log.info('Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.');
|
106 | }
|
107 | }
|
108 | process.exitCode = 1;
|
109 | });
|
110 | }
|
111 | else {
|
112 | this.log.error('Unknown command: "%s", supported commands: [%s], or use `stryker --help`.', this.command, Object.keys(commands));
|
113 | }
|
114 | }
|
115 | }
|
116 | exports.default = StrykerCli;
|
117 |
|
\ | No newline at end of file |