@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
104 lines • 5.3 kB
JavaScript
import { URL } from 'url';
import { expect } from 'chai';
import sinon from 'sinon';
import { Task } from '@stryker-mutator/util';
import { factory, testInjector } from '@stryker-mutator/test-helpers';
import { ChildProcessCrashedError } from '../../../src/child-proxy/child-process-crashed-error.js';
import { ChildProcessProxy } from '../../../src/child-proxy/child-process-proxy.js';
import { ChildProcessTestRunnerProxy } from '../../../src/test-runner/child-process-test-runner-proxy.js';
import { ChildProcessTestRunnerWorker } from '../../../src/test-runner/child-process-test-runner-worker.js';
import { IdGenerator } from '../../../src/child-proxy/id-generator.js';
describe(ChildProcessTestRunnerProxy.name, () => {
let options;
let childProcessProxyMock;
let proxyMock;
let childProcessProxyCreateStub;
let loggingContext;
let clock;
let fileDescriptions;
const idGenerator = new IdGenerator();
beforeEach(() => {
clock = sinon.useFakeTimers();
fileDescriptions = { 'foo.js': { mutate: true } };
childProcessProxyMock = sinon.createStubInstance(ChildProcessProxy);
proxyMock = childProcessProxyMock.proxy =
factory.testRunner();
childProcessProxyCreateStub = sinon.stub(ChildProcessProxy, 'create');
childProcessProxyCreateStub.returns(childProcessProxyMock);
options = factory.strykerOptions({
plugins: ['foo-plugin', 'bar-plugin'],
});
loggingContext = { port: 4200, level: "fatal" /* LogLevel.Fatal */ };
idGenerator.next();
});
function createSut() {
return new ChildProcessTestRunnerProxy(options, fileDescriptions, 'a working directory', loggingContext, ['plugin', 'paths'], testInjector.logger, idGenerator);
}
it('should create the child process proxy', () => {
options.testRunnerNodeArgs = ['--inspect', '--no-warnings'];
createSut();
sinon.assert.calledWithExactly(childProcessProxyCreateStub, new URL('../../../src/test-runner/child-process-test-runner-worker.js', import.meta.url).toString(), loggingContext, options, fileDescriptions, ['plugin', 'paths'], 'a working directory', ChildProcessTestRunnerWorker, ['--inspect', '--no-warnings'], idGenerator);
});
it('should forward `init` calls', async () => {
const sut = createSut();
proxyMock.init.resolves();
await sut.init();
expect(proxyMock.init).called;
});
it('should forward `dryRun` calls', async () => {
const sut = createSut();
const expectedResult = factory.completeDryRunResult({ mutantCoverage: factory.mutantCoverage() });
proxyMock.dryRun.resolves(expectedResult);
const runOptions = factory.dryRunOptions({
timeout: 234,
});
const actualResult = await sut.dryRun(runOptions);
expect(actualResult).eq(expectedResult);
expect(proxyMock.dryRun).calledWith(runOptions);
});
it('should forward `mutantRun` calls', async () => {
const sut = createSut();
const expectedResult = factory.survivedMutantRunResult();
proxyMock.mutantRun.resolves(expectedResult);
const runOptions = factory.mutantRunOptions({
timeout: 234,
});
const actualResult = await sut.mutantRun(runOptions);
expect(actualResult).eq(expectedResult);
expect(proxyMock.mutantRun).calledWith(runOptions);
});
describe('dispose', () => {
it('should dispose the test runner before disposing the child process itself on `dispose`', async () => {
const sut = createSut();
proxyMock.dispose.resolves();
await sut.dispose();
expect(proxyMock.dispose).calledBefore(childProcessProxyMock.dispose);
});
it('should not reject when the child process is down', async () => {
const sut = createSut();
proxyMock.dispose.rejects(new ChildProcessCrashedError(1, '1'));
await sut.dispose();
expect(childProcessProxyMock.dispose).called;
expect(testInjector.logger.warn).not.called;
});
it('should log, but not reject, when the child process rejects', async () => {
const sut = createSut();
const expectedError = new Error('Could not divide by zero 🤷♀️');
proxyMock.dispose.rejects(expectedError);
await sut.dispose();
expect(childProcessProxyMock.dispose).called;
expect(testInjector.logger.warn).calledWithExactly('An unexpected error occurred during test runner disposal. This might be worth looking into. Stryker will ignore this error.', expectedError);
});
it('should only wait 2 seconds for the test runner to be disposed', async () => {
const sut = createSut();
const testRunnerDisposeTask = new Task();
proxyMock.dispose.returns(testRunnerDisposeTask.promise);
const disposePromise = sut.dispose();
clock.tick(2001);
await disposePromise;
expect(childProcessProxyMock.dispose).called;
testRunnerDisposeTask.resolve(undefined);
});
});
});
//# sourceMappingURL=child-process-test-runner-proxy.spec.js.map