Skip to content

Commit

Permalink
fix(jest-runner): allow prerelease jest versions (#5015) (#5016)
Browse files Browse the repository at this point in the history
Support jests prerelease versions, like "30.0.0-alpha.6".

---------

Co-authored-by: Nico Jansen <jansennico@gmail.com>
  • Loading branch information
rriski and nicojs authored Sep 29, 2024
1 parent 5d792d8 commit 0c9cdd1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const jestEnvironmentGenericFileName = fileURLToPath(new URL('./jest-environment
*/
function getJestDefaults(jestWrapper: JestWrapper) {
// New defaults since 27: https://jestjs.io/blog/2021/05/25/jest-27
if (semver.satisfies(jestWrapper.getVersion(), '>=27')) {
if (semver.satisfies(semver.coerce(jestWrapper.getVersion())!, '>=27')) {
return {
testRunner: 'jest-circus/runner',
testEnvironment: 'node',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
import { Logger } from '@stryker-mutator/api/logging';
import { StrykerOptions } from '@stryker-mutator/api/core';
import { commonTokens, Injector, tokens } from '@stryker-mutator/api/plugin';
import semver from 'semver';
import semver, { SemVer } from 'semver';

import { JestPluginContext, pluginTokens } from '../plugin-di.js';
import { JestWrapper } from '../utils/jest-wrapper.js';

import { JestLessThan25TestAdapter } from './jest-less-than-25-adapter.js';
import { JestGreaterThan25TestAdapter } from './jest-greater-than-25-adapter.js';
interface CoercedVersion {
version: SemVer;
raw: string;
}

function coerceVersion(version: string): CoercedVersion {
return { version: semver.coerce(version)!, raw: version };
}

export function jestTestAdapterFactory(
log: Logger,
jestWrapper: JestWrapper,
options: StrykerOptions,
injector: Injector<JestPluginContext>,
): JestGreaterThan25TestAdapter | JestLessThan25TestAdapter {
const version = jestWrapper.getVersion();
log.debug('Detected Jest version %s', version);
guardJestVersion(version, options, log);
const coercedVersion = coerceVersion(jestWrapper.getVersion());
log.debug('Detected Jest version %s', coercedVersion.raw);
guardJestVersion(coercedVersion, options, log);

if (semver.satisfies(version, '<25.0.0')) {
if (semver.satisfies(coercedVersion.version, '<25.0.0')) {
return injector.injectClass(JestLessThan25TestAdapter);
} else {
return injector.injectClass(JestGreaterThan25TestAdapter);
}
}
jestTestAdapterFactory.inject = tokens(commonTokens.logger, pluginTokens.jestWrapper, commonTokens.options, commonTokens.injector);

function guardJestVersion(jest: string, options: StrykerOptions, log: Logger) {
if (semver.satisfies(jest, '<22.0.0')) {
throw new Error(`You need Jest version >= 22.0.0 to use the @stryker-mutator/jest-runner plugin, found ${jest}`);
} else if (semver.satisfies(jest, '<24')) {
function guardJestVersion({ version, raw }: CoercedVersion, options: StrykerOptions, log: Logger) {
if (semver.satisfies(version, '<22.0.0')) {
throw new Error(`You need Jest version >= 22.0.0 to use the @stryker-mutator/jest-runner plugin, found ${raw}`);
} else if (semver.satisfies(version, '<24')) {
if (options.coverageAnalysis !== 'off') {
throw new Error(
`You need Jest version >= 24.0.0 to use the @stryker-mutator/jest-runner with "coverageAnalysis": "${options.coverageAnalysis}", you're currently using version 23.0.0. Please upgrade your jest version, or set "coverageAnalysis": "off".`,
);
}
log.warn(
'[DEPRECATED] Support for Jest version < 24 is deprecated and will be removed in the next major version of Stryker, please upgrade your jest version (your current version is %s).',
jest,
raw,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,45 @@ describe(jestTestAdapterFactory.name, () => {
expect(testInjector.logger.debug).calledWith('Detected Jest version %s', '25.0.0');
});

it('should return a JestGreaterThan25Adapter when the Jest version is higher or equal to 25.0.0', () => {
it('should return a JestGreaterThan25Adapter when the Jest version is greater or equal to 25.0.0', () => {
jestWrapperMock.getVersion.returns('25.0.0');
const testAdapter = act();

expect(testAdapter).instanceOf(JestGreaterThan25TestAdapter);
});
it('should return a JestLessThan25Adapter when the Jest version is higher or equal to 22.0.0, but less then 25 and coverage analysis is disabled', () => {
it('should return a JestGreaterThan25Adapter when the Jest version is an alpha version greater than 25.0.0', () => {
jestWrapperMock.getVersion.returns('30.0.0-alpha.6');
const testAdapter = act();

expect(testAdapter).instanceOf(JestGreaterThan25TestAdapter);
});
it('should return a JestLessThan25Adapter when the Jest version is greater or equal to 22.0.0, but less then 25 and coverage analysis is disabled', () => {
testInjector.options.coverageAnalysis = 'off';
jestWrapperMock.getVersion.returns('22.0.0');
const testAdapter = act();

expect(testAdapter).instanceOf(JestLessThan25TestAdapter);
});
it('should return a JestLessThan25Adapter when the Jest version is an alpha version greater than 22.0.0, lower than 25', () => {
testInjector.options.coverageAnalysis = 'off';
jestWrapperMock.getVersion.returns('23.0.0-alpha.6');
const testAdapter = act();

expect(testAdapter).instanceOf(JestLessThan25TestAdapter);
});

it('should throw an error when the Jest version is lower than 22.0.0', () => {
jestWrapperMock.getVersion.returns('21.0.0');

expect(act).to.throw(Error, 'You need Jest version >= 22.0.0 to use the @stryker-mutator/jest-runner plugin, found 21.0.0');
});

it('should throw an error when the Jest version is an alpha version lower than 22.0.0', () => {
jestWrapperMock.getVersion.returns('21.0.0-alpha.6');

expect(act).to.throw(Error, 'You need Jest version >= 22.0.0 to use the @stryker-mutator/jest-runner plugin, found 21.0.0-alpha.6');
});

it('should throw an error when the Jest version is between 22 and 24, but coverage analysis is enabled', () => {
jestWrapperMock.getVersion.returns('23.0.0');
testInjector.options.coverageAnalysis = 'all';
Expand Down
12 changes: 11 additions & 1 deletion packages/jest-runner/test/unit/jest-test-runner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ describe(JestTestRunner.name, () => {
});
});

it('should not add a set setupFile if testRunner is not specified and jest version >= 27 (circus test runner)', async () => {
it('should not add a setupFile if testRunner is not specified and jest version >= 27 (circus test runner)', async () => {
jestWrapperMock.getVersion.returns('27.0.0');
options.jest.config = { testRunner: undefined };
const sut = await arrangeInitializedSut();
Expand All @@ -386,6 +386,16 @@ describe(JestTestRunner.name, () => {
});
});

it('should not add a setupFile if testRunner is not specified and jest is an alpha version >= 27 (circus test runner)', async () => {
jestWrapperMock.getVersion.returns('30.0.0-alpha.6');
options.jest.config = { testRunner: undefined };
const sut = await arrangeInitializedSut();
await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' }));
expect(jestTestAdapterMock.run).calledWithMatch({
jestConfig: sinon.match({ setupFilesAfterEnv: undefined }),
});
});

it('should not allow the circus test runner for coverage analysis "perTest"', async () => {
options.jest.config = { testRunner: 'jest-circus/runner' };
const sut = await arrangeInitializedSut();
Expand Down

0 comments on commit 0c9cdd1

Please sign in to comment.