@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
94 lines • 5.11 kB
JavaScript
import sinon from 'sinon';
import { expect } from 'chai';
import { factory, testInjector } from '@stryker-mutator/test-helpers';
import { Instrumenter, createInstrumenter } from '@stryker-mutator/instrumenter';
import { MutantInstrumenterExecutor } from '../../../src/process/index.js';
import { Project } from '../../../src/fs/index.js';
import { coreTokens } from '../../../src/di/index.js';
import { createConcurrencyTokenProviderMock, createCheckerPoolMock } from '../../helpers/producers.js';
import { createCheckerFactory } from '../../../src/checker/index.js';
import { createPreprocessor, Sandbox } from '../../../src/sandbox/index.js';
import { FileSystemTestDouble } from '../../helpers/file-system-test-double.js';
describe(MutantInstrumenterExecutor.name, () => {
let sut;
let project;
let injectorMock;
let instrumenterMock;
let sandboxFilePreprocessorMock;
let instrumentResult;
let sandboxMock;
let checkerPoolMock;
let concurrencyTokenProviderMock;
beforeEach(() => {
const fsTestDouble = new FileSystemTestDouble({ 'foo.js': 'console.log("bar")', 'foo.spec.js': '' });
const fileDescriptions = { 'foo.js': { mutate: true }, 'foo.spec.js': { mutate: false } };
project = new Project(fsTestDouble, fileDescriptions);
concurrencyTokenProviderMock = createConcurrencyTokenProviderMock();
checkerPoolMock = createCheckerPoolMock();
instrumentResult = {
files: [{ name: 'foo.js', content: 'console.log(global.activeMutant === 1? "": "bar")', mutate: true }],
mutants: [factory.mutant({ id: '1', replacement: 'bar' })],
};
sandboxMock = sinon.createStubInstance(Sandbox);
instrumenterMock = sinon.createStubInstance(Instrumenter);
sandboxFilePreprocessorMock = {
preprocess: sinon.stub(),
};
sandboxFilePreprocessorMock.preprocess.resolves();
injectorMock = factory.injector();
sut = new MutantInstrumenterExecutor(injectorMock, project, testInjector.options);
injectorMock.injectFunction.withArgs(createInstrumenter).returns(instrumenterMock);
injectorMock.injectFunction.withArgs(createPreprocessor).returns(sandboxFilePreprocessorMock);
injectorMock.resolve.withArgs(coreTokens.sandbox).returns(sandboxMock);
injectorMock.resolve
.withArgs(coreTokens.concurrencyTokenProvider)
.returns(concurrencyTokenProviderMock)
.withArgs(coreTokens.checkerPool)
.returns(checkerPoolMock);
instrumenterMock.instrument.resolves(instrumentResult);
});
it('should instrument the given files', async () => {
testInjector.options.mutator.plugins = ['functionSent'];
testInjector.options.mutator.excludedMutations = ['fooMutator'];
await sut.execute();
const expectedInstrumenterOptions = { ...testInjector.options.mutator };
sinon.assert.calledOnceWithExactly(instrumenterMock.instrument, [{ name: 'foo.js', content: 'console.log("bar")', mutate: true }], expectedInstrumenterOptions);
});
it('result in the new injector', async () => {
const result = await sut.execute();
expect(result).eq(injectorMock);
});
it('should preprocess files before initializing the sandbox', async () => {
await sut.execute();
expect(sandboxFilePreprocessorMock.preprocess).calledWithExactly(project);
expect(sandboxFilePreprocessorMock.preprocess).calledBefore(sandboxMock.init);
});
it('should provide checkerToken$ to the checker pool', async () => {
concurrencyTokenProviderMock.checkerToken$.next(0);
concurrencyTokenProviderMock.checkerToken$.next(1);
await sut.execute();
expect(injectorMock.provideValue).calledWith(coreTokens.checkerConcurrencyTokens, concurrencyTokenProviderMock.checkerToken$);
});
it('should provide the checker factory to the checker pool', async () => {
await sut.execute();
expect(injectorMock.provideFactory).calledWith(coreTokens.checkerFactory, createCheckerFactory);
});
it('should initialize the CheckerPool before creating the sandbox', async () => {
// This is important for in-place mutation. We need to initialize the typescript checker(s) before we write mutated files to disk.
await sut.execute();
expect(checkerPoolMock.init).calledBefore(injectorMock.provideClass.withArgs(coreTokens.sandbox, Sandbox));
});
it('should provide mutants in the result', async () => {
await sut.execute();
expect(injectorMock.provideValue).calledWithExactly(coreTokens.mutants, instrumentResult.mutants);
});
it('should provide the sandbox in the result', async () => {
await sut.execute();
expect(injectorMock.provideClass).calledWithExactly(coreTokens.sandbox, Sandbox);
});
it('should initialize the sandbox', async () => {
await sut.execute();
expect(sandboxMock.init).calledOnce;
});
});
//# sourceMappingURL=2-mutant-instrumenter-executor.spec.js.map