Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
import * as path from 'path';
import { Config } from '@stryker-mutator/api/config';
import { StrykerOptions } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
import { commonTokens, tokens } from '@stryker-mutator/api/plugin';
import { StrykerError } from '@stryker-mutator/util';
import { coreTokens } from '../di';
export const CONFIG_SYNTAX_HELP = ' module.exports = function(config) {\n' + ' config.set({\n' + ' // your config\n' + ' });\n' + ' };';
const DEFAULT_CONFIG_FILE = 'stryker.conf.js';
export default class ConfigReader {
public static inject = tokens(coreTokens.cliOptions, commonTokens.logger);
constructor(private readonly cliOptions: Partial, private readonly log: Logger) {}
public readConfig() {
const configModule = this.loadConfigModule();
const config = new Config();
try {
configModule(config);
} catch (e) {
throw new StrykerError('Error in config file!', e);
}
// merge the config from config file and cliOptions (precedence)
config.set(this.cliOptions);
if (this.log.isDebugEnabled()) {
this.log.debug(`Loaded config: ${JSON.stringify(config, null, 2)}`);
}
import * as os from 'os';
import { Position, StrykerOptions } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
import { commonTokens } from '@stryker-mutator/api/plugin';
import { MutantResult, MutantStatus, mutationTestReportSchema, Reporter } from '@stryker-mutator/api/report';
import { calculateMetrics } from 'mutation-testing-metrics';
import { tokens } from 'typed-inject';
import chalk = require('chalk');
import ClearTextScoreTable from './ClearTextScoreTable';
export default class ClearTextReporter implements Reporter {
public static inject = tokens(commonTokens.logger, commonTokens.options);
constructor(private readonly log: Logger, private readonly options: StrykerOptions) {
this.configConsoleColor();
}
private readonly out: NodeJS.WritableStream = process.stdout;
private writeLine(output?: string) {
this.out.write(`${output || ''}${os.EOL}`);
}
private configConsoleColor() {
if (!this.options.allowConsoleColors) {
chalk.level = 0; // All colors disabled
}
}
.provideValue(PROCESS_ENV_TOKEN, process.env)
.provideValue(JEST_VERSION_TOKEN, require('jest/package.json').version as string)
.provideFactory(JEST_TEST_ADAPTER_TOKEN, jestTestAdapterFactory)
.injectClass(JestTestRunner);
}
jestTestRunnerFactory.inject = tokens(commonTokens.injector);
export const PROCESS_ENV_TOKEN = 'PROCESS_ENV_TOKEN';
export const JEST_TEST_ADAPTER_TOKEN = 'jestTestAdapter';
export default class JestTestRunner implements TestRunner {
private readonly jestConfig: jest.Configuration;
private readonly enableFindRelatedTests: boolean;
public static inject = tokens(commonTokens.logger, commonTokens.options, PROCESS_ENV_TOKEN, JEST_TEST_ADAPTER_TOKEN);
constructor(
private readonly log: Logger,
options: StrykerOptions,
private readonly processEnvRef: NodeJS.ProcessEnv,
private readonly jestTestAdapter: JestTestAdapter
) {
// Get jest configuration from stryker options and assign it to jestConfig
this.jestConfig = options.jest.config;
// Get enableFindRelatedTests from stryker jest options or default to true
this.enableFindRelatedTests = options.jest.enableFindRelatedTests;
if (this.enableFindRelatedTests === undefined) {
this.enableFindRelatedTests = true;
}
if (this.enableFindRelatedTests) {
injector: Injector
): Transpiler & Disposable {
if (options.transpilers.length) {
return injector.injectClass(ChildProcessTranspiler);
} else {
return {
transpile(files: readonly File[]) {
return Promise.resolve(files);
},
dispose() {
// noop
}
};
}
}
transpilerFactory.inject = tokens(commonTokens.options, commonTokens.injector);
import { File, StrykerOptions } from '@stryker-mutator/api/core';
import { commonTokens, tokens } from '@stryker-mutator/api/plugin';
import { Transpiler } from '@stryker-mutator/api/transpile';
import ConfigLoader from './compiler/ConfigLoader';
import WebpackCompiler from './compiler/WebpackCompiler';
import { pluginTokens } from './pluginTokens';
const DEFAULT_STRYKER_WEBPACK_CONFIG = Object.freeze({ configFile: undefined, silent: true, context: process.cwd() });
export default class WebpackTranspiler implements Transpiler {
private readonly config: StrykerWebpackConfig;
private webpackCompiler: WebpackCompiler;
public static inject = tokens(commonTokens.options, commonTokens.produceSourceMaps, pluginTokens.configLoader);
constructor(options: StrykerOptions, produceSourceMaps: boolean, private readonly configLoader: ConfigLoader) {
if (produceSourceMaps) {
throw new Error(
`Invalid \`coverageAnalysis\` "${options.coverageAnalysis}" is not supported by the stryker-webpack-transpiler (yet). It is not able to produce source maps yet. Please set it "coverageAnalysis" to "off".`
);
}
this.config = this.getStrykerWebpackConfig(options.webpack);
}
public async transpile(files: readonly File[]): Promise {
if (!this.webpackCompiler) {
// Initialize the webpack compiler with the current directory (process.cwd)
const config = await this.configLoader.load(this.config);
this.webpackCompiler = new WebpackCompiler(config);
}
private determineRunState() {
// Karma will report an Error if no tests had executed.
// This is not an "error" in Stryker terms
if (this.currentRunStatus === RunStatus.Error && !this.currentErrorMessages.length && !this.currentTestResults.length) {
return RunStatus.Complete;
} else if (this.currentErrorMessages.length) {
// Karma will return Complete when there are runtime errors
return RunStatus.Error;
} else {
return this.currentRunStatus;
}
}
}
public async run(options: RunOptions): Promise {
this.setNodeEnv();
const { results } = await this.jestTestAdapter.run(
this.jestConfig,
process.cwd(),
this.enableFindRelatedTests ? options.mutatedFileName : undefined
);
// Get the non-empty errorMessages from the jest RunResult, it's safe to cast to Array here because we filter the empty error messages
const errorMessages = results.testResults
.map((testSuite: jest.TestResult) => testSuite.failureMessage)
.filter(errorMessage => errorMessage) as string[];
return {
errorMessages,
status: results.numRuntimeErrorTestSuites > 0 ? RunStatus.Error : RunStatus.Complete,
tests: this.processTestResults(results.testResults)
};
}
public async run({ testHooks }: { testHooks?: string }): Promise {
this.testHooksMiddleware.currentTestHooks = testHooks || '';
if (this.currentRunStatus !== RunStatus.Error) {
// Only run when there was no compile error
// An compile error can happen in case of angular-cli
await this.runServer();
}
const runResult = this.collectRunResult();
this.cleanRun();
return runResult;
}
private transpileFile(file: File) {
const relativeOptions: babel.TransformOptions = {
cwd: this.projectRoot,
filename: file.name,
filenameRelative: path.relative(this.projectRoot, file.name)
};
const options: babel.TransformOptions = { ...this.babelConfig.options, ...relativeOptions };
const result: babel.BabelFileResult | null = babel.transformSync(file.textContent, options);
if (!result) {
// File is ignored by babel
return file;
} else if (result.code === undefined || result.code === null) {
throw new Error(`Could not transpile file "${file.name}". Babel transform function delivered \`undefined\`.`);
} else {
return new File(toJSFileName(file.name), result.code);
}
}
private determineRunState() {
// Karma will report an Error if no tests had executed.
// This is not an "error" in Stryker terms
if (this.currentRunStatus === RunStatus.Error && !this.currentErrorMessages.length && !this.currentTestResults.length) {
return RunStatus.Complete;
} else if (this.currentErrorMessages.length) {
// Karma will return Complete when there are runtime errors
return RunStatus.Error;
} else {
return this.currentRunStatus;
}
}
}