UNPKG

@stryker-mutator/core

Version:

The extendable JavaScript mutation testing framework

188 lines 6.68 kB
import os from 'os'; import { types } from 'util'; import fs from 'fs'; import { fileURLToPath } from 'url'; import path from 'path'; import { commonTokens, declareClassPlugin, PluginKind, tokens } from '@stryker-mutator/api/plugin'; import { DryRunStatus, toMutantRunResult, } from '@stryker-mutator/api/test-runner'; import { factory } from '@stryker-mutator/test-helpers'; class NotImplementedTestRunner { capabilities() { return Promise.resolve({ reloadEnvironment: true }); } dryRun(_options) { throw new Error('Method not implemented.'); } mutantRun(_options) { throw new Error('Method not implemented.'); } } class CoverageReportingTestRunner extends NotImplementedTestRunner { async dryRun() { global.__mutantCoverage__ = 'overridden'; return { status: DryRunStatus.Complete, tests: [], mutantCoverage: factory.mutantCoverage({ static: { 1: 42 } }) }; } } class TimeBombTestRunner extends NotImplementedTestRunner { constructor() { super(); // Setting a time bomb after 100 ms setTimeout(() => process.exit(), 500); } async dryRun() { return factory.completeDryRunResult(); } } class ProximityMineTestRunner extends NotImplementedTestRunner { async dryRun() { process.exit(42); } } export class CounterTestRunner extends NotImplementedTestRunner { constructor() { super(...arguments); this.count = 0; } async dryRun() { return factory.completeDryRunResult(); } async mutantRun() { this.count++; fs.writeFileSync(CounterTestRunner.COUNTER_FILE, `${this.count}`); return factory.survivedMutantRunResult(); } } CounterTestRunner.COUNTER_FILE = `${os.tmpdir()}/stryker-js-test-counter-file`; class DirectResolvedTestRunner extends NotImplementedTestRunner { async dryRun() { global.__mutantCoverage__ = 'coverageObject'; return factory.completeDryRunResult(); } } class DiscoverRegexTestRunner extends NotImplementedTestRunner { constructor(options) { super(); this.options = options; } async dryRun() { if (types.isRegExp(this.options.someRegex)) { return factory.completeDryRunResult(); } else { return factory.errorDryRunResult({ errorMessage: 'No regex found in runnerOptions.strykerOptions.someRegex' }); } } } DiscoverRegexTestRunner.inject = tokens(commonTokens.options); class ErroredTestRunner extends NotImplementedTestRunner { async dryRun() { let expectedError = null; try { throw new SyntaxError('This is invalid syntax!'); } catch (error) { expectedError = error; } return factory.errorDryRunResult({ errorMessage: expectedError }); } dispose() { throw new Error('Test runner exited with exit code 1'); } } class RejectInitRunner extends NotImplementedTestRunner { init() { return Promise.reject(new Error('Init was rejected')); } async dryRun() { throw new Error(); } } class NeverResolvedTestRunner extends NotImplementedTestRunner { dryRun() { // eslint-disable-next-line @typescript-eslint/no-empty-function return new Promise(() => { }); } } class SlowInitAndDisposeTestRunner extends NotImplementedTestRunner { constructor() { super(...arguments); this.inInit = false; } init() { return new Promise((resolve) => { this.inInit = true; setTimeout(() => { this.inInit = false; resolve(); }, 1000); }); } async dryRun() { if (this.inInit) { throw new Error('Test should fail! Not yet initialized!'); } return factory.completeDryRunResult(); } dispose() { return this.init(); } } class VerifyWorkingFolderTestRunner extends NotImplementedTestRunner { async dryRun() { const dirname = path.dirname(fileURLToPath(import.meta.url)); if (process.cwd().toLowerCase() === dirname.toLowerCase()) { return factory.completeDryRunResult(); } else { throw new Error(`Expected ${process.cwd()} to be ${dirname}`); } } } class AsynchronousPromiseRejectionHandlerTestRunner extends NotImplementedTestRunner { async init() { this.promise = Promise.reject('Reject for now, but will be caught asynchronously'); } async dryRun() { // eslint-disable-next-line @typescript-eslint/no-empty-function this.promise.catch(() => { }); return factory.completeDryRunResult(); } } class StaticMutantTestRunner extends NotImplementedTestRunner { constructor() { super(...arguments); this.count = 0; } async capabilities() { return { reloadEnvironment: false }; } async dryRun() { this.count++; if (this.count === 1) { return factory.completeDryRunResult({ tests: [factory.failedTestResult()] }); } else { return factory.completeDryRunResult({ tests: [factory.successTestResult()] }); } } async mutantRun() { return toMutantRunResult(await this.dryRun()); } } export const strykerPlugins = [ declareClassPlugin(PluginKind.TestRunner, 'verify-working-folder', VerifyWorkingFolderTestRunner), declareClassPlugin(PluginKind.TestRunner, 'slow-init-dispose', SlowInitAndDisposeTestRunner), declareClassPlugin(PluginKind.TestRunner, 'never-resolved', NeverResolvedTestRunner), declareClassPlugin(PluginKind.TestRunner, 'errored', ErroredTestRunner), declareClassPlugin(PluginKind.TestRunner, 'discover-regex', DiscoverRegexTestRunner), declareClassPlugin(PluginKind.TestRunner, 'direct-resolved', DirectResolvedTestRunner), declareClassPlugin(PluginKind.TestRunner, 'coverage-reporting', CoverageReportingTestRunner), declareClassPlugin(PluginKind.TestRunner, 'time-bomb', TimeBombTestRunner), declareClassPlugin(PluginKind.TestRunner, 'proximity-mine', ProximityMineTestRunner), declareClassPlugin(PluginKind.TestRunner, 'counter', CounterTestRunner), declareClassPlugin(PluginKind.TestRunner, 'async-promise-rejection-handler', AsynchronousPromiseRejectionHandlerTestRunner), declareClassPlugin(PluginKind.TestRunner, 'reject-init', RejectInitRunner), declareClassPlugin(PluginKind.TestRunner, 'static', StaticMutantTestRunner), ]; export const additionalTestRunnersFileUrl = import.meta.url; //# sourceMappingURL=additional-test-runners.js.map