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) {
import * as path from 'path';
import { MutationScoreThresholds } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
import { commonTokens, tokens } from '@stryker-mutator/api/plugin';
import { MutantResult, MutantStatus, ScoreResult } from '@stryker-mutator/api/report';
import flatMap = require('lodash.flatmap');
import groupBy = require('lodash.groupby');
import { freezeRecursively, setExitCode } from './utils/objectUtils';
const defaultScoreIfNoValidMutants = 100;
export default class ScoreResultCalculator {
public static inject = tokens(commonTokens.logger);
constructor(private readonly log: Logger) {}
public calculate(results: MutantResult[]): ScoreResult {
const scoreResult = this.calculateScoreResult(results, '');
return this.wrapIfSingleFileScoreResult(scoreResult);
}
public determineExitCode(score: ScoreResult, thresholds: MutationScoreThresholds | undefined) {
const breaking = thresholds && thresholds.break;
const formattedScore = score.mutationScore.toFixed(2);
if (typeof breaking === 'number') {
if (score.mutationScore < breaking) {
this.log.error(`Final mutation score ${formattedScore} under breaking threshold ${breaking}, setting exit code to 1 (failure).`);
this.log.info('(improve mutation score or set `thresholds.break = null` to prevent this error in the future)');
setExitCode(1);
} else {
/**
* Subset of defaults for mocha options
* @see https://github.com/mochajs/mocha/blob/master/lib/mocharc.json
*/
export const DEFAULT_MOCHA_OPTIONS = Object.freeze({
extension: ['js'],
file: [],
ignore: [],
opts: './test/mocha.opts',
spec: ['test'],
timeout: 2000,
ui: 'bdd'
});
export default class MochaOptionsLoader {
public static inject = tokens(commonTokens.logger);
constructor(private readonly log: Logger) {}
public load(strykerOptions: StrykerOptions): MochaOptions {
const mochaOptions = { ...strykerOptions[mochaOptionsKey] } as MochaOptions;
return { ...DEFAULT_MOCHA_OPTIONS, ...this.loadMochaOptions(mochaOptions), ...mochaOptions };
}
private loadMochaOptions(overrides: MochaOptions) {
if (LibWrapper.loadOptions) {
this.log.debug("Mocha >= 6 detected. Using mocha's `%s` to load mocha options", LibWrapper.loadOptions.name);
return this.loadMocha6Options(overrides);
} else {
this.log.warn('DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6.');
this.log.debug('Mocha < 6 detected. Using custom logic to parse mocha options');
return this.loadLegacyMochaOptsFile(overrides.opts);
}
import { coreTokens } from './di';
import LoggingClientContext from './logging/LoggingClientContext';
import { InitialTestRunResult } from './process/InitialTestExecutor';
import Sandbox from './Sandbox';
import TranspiledMutant from './TranspiledMutant';
import { TemporaryDirectory } from './utils/TemporaryDirectory';
const MAX_CONCURRENT_INITIALIZING_SANDBOXES = 2;
export class SandboxPool implements Disposable {
private readonly allSandboxes: Array> = [];
private readonly overheadTimeMS: number;
public static inject = tokens(
commonTokens.logger,
commonTokens.options,
coreTokens.testFramework,
coreTokens.initialRunResult,
coreTokens.transpiledFiles,
coreTokens.loggingContext,
coreTokens.temporaryDirectory
);
constructor(
private readonly log: Logger,
private readonly options: StrykerOptions,
private readonly testFramework: TestFramework | null,
initialRunResult: InitialTestRunResult,
private readonly initialFiles: readonly File[],
private readonly loggingContext: LoggingClientContext,
private readonly tempDir: TemporaryDirectory
) {
function toReportSourceFile(file: File): SourceFile {
return {
content: file.textContent,
path: file.name
};
}
const IGNORE_PATTERN_CHARACTER = '!';
export default class InputFileResolver {
private readonly mutatePatterns: readonly string[];
private readonly filePatterns: readonly string[] | undefined;
private readonly tempDirName: string;
public static inject = tokens(commonTokens.logger, commonTokens.options, coreTokens.reporter);
constructor(private readonly log: Logger, { mutate, files, tempDirName }: StrykerOptions, private readonly reporter: StrictReporter) {
this.tempDirName = tempDirName;
this.mutatePatterns = mutate || [];
if (files) {
this.filePatterns = files;
}
}
public async resolve(): Promise {
const [inputFileNames, mutateFiles] = await Promise.all([this.resolveInputFiles(), this.resolveMutateFiles()]);
const files: File[] = await this.readFiles(inputFileNames);
const inputFileCollection = new InputFileCollection(files, mutateFiles);
this.reportAllSourceFilesRead(files);
inputFileCollection.logFiles(this.log);
return inputFileCollection;
}