@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
188 lines • 6.68 kB
JavaScript
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