Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 54 additions & 56 deletions src/rules/__tests__/no-deprecated-functions.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { TSESLint } from '@typescript-eslint/utils';
import type { TSESLint } from '@typescript-eslint/utils';
import rule from '../no-deprecated-functions';
import {
type JestVersion,
detectJestVersion,
} from '../utils/detectJestVersion';
import {
FlatCompatRuleTester as RuleTester,
usingFlatConfig,
} from './test-utils';
import { type JestVersion, getJestVersion } from '../utils/detectJestVersion';
import { FlatCompatRuleTester as RuleTester } from './test-utils';

jest.mock('../utils/detectJestVersion');

const detectJestVersionMock = detectJestVersion as jest.MockedFunction<
typeof detectJestVersion
const getJestVersionMock = getJestVersion as jest.MockedFunction<
typeof getJestVersion
>;

const ruleTester = new RuleTester();
Expand Down Expand Up @@ -67,11 +61,6 @@ describe('the rule', () => {
valid: [
{ code: 'jest', settings: { jest: { version: 14 } } },
{ code: 'require("fs")', settings: { jest: { version: 14 } } },
...generateValidCases(14, 'jest.resetModuleRegistry'),
...generateValidCases(17, 'require.requireActual'),
...generateValidCases(25, 'jest.genMockFromModule'),
...generateValidCases('25.1.1', 'jest.genMockFromModule'),
...generateValidCases('17.2', 'require.requireActual'),
],
invalid: [
...generateInvalidCases(
Expand All @@ -90,14 +79,53 @@ describe('the rule', () => {
'jest.genMockFromModule',
'jest.createMockFromModule',
),
...generateInvalidCases(
14,
'jest.resetModuleRegistry',
'jest.resetModules',
),
...generateInvalidCases(
17,
'require.requireActual',
'jest.requireActual',
),
...generateInvalidCases(
25,
'jest.genMockFromModule',
'jest.createMockFromModule',
),
...generateInvalidCases(
'25.1.1',
'jest.genMockFromModule',
'jest.createMockFromModule',
),
...generateInvalidCases(
'17.2',
'require.requireActual',
'jest.requireActual',
),
],
});

describe.each<JestVersion>([
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
describe.each<ReturnType<typeof getJestVersion>>([
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
null,
])('when using jest version %i', jestVersion => {
beforeEach(async () => {
detectJestVersionMock.mockReturnValue(jestVersion);
getJestVersionMock.mockReturnValue(jestVersion);
});

const allowedFunctions: string[] = [];
Expand All @@ -111,7 +139,7 @@ describe('the rule', () => {
[26, 'jest.genMockFromModule', 'jest.createMockFromModule'],
] as const
).filter(deprecation => {
if (deprecation[0] > jestVersion) {
if (jestVersion && deprecation[0] > jestVersion) {
allowedFunctions.push(deprecation[1]);

return false;
Expand All @@ -125,11 +153,15 @@ describe('the rule', () => {
'jest',
'require("fs")',
...allowedFunctions.flatMap(func =>
generateValidCases(jestVersion, func),
generateValidCases(jestVersion ?? undefined, func),
),
],
invalid: deprecations.flatMap(([, deprecation, replacement]) =>
generateInvalidCases(jestVersion, deprecation, replacement),
generateInvalidCases(
jestVersion ?? undefined,
deprecation,
replacement,
),
),
});

Expand All @@ -146,38 +178,4 @@ describe('the rule', () => {
),
});
});

describe('when there is an error in detecting the jest version', () => {
beforeEach(() => {
detectJestVersionMock.mockImplementation(() => {
throw new Error('oh noes!');
});
});

it('bubbles the error up', () => {
expect(() => {
const linter = new TSESLint.Linter();

/* istanbul ignore if */
if (usingFlatConfig) {
linter.verify('jest.resetModuleRegistry()', [
{
plugins: {
jest: { rules: { 'no-deprecated-functions': rule } },
},
rules: { 'jest/no-deprecated-functions': 'error' },
},
]);

return;
}

linter.defineRule('no-deprecated-functions', rule);

linter.verify('jest.resetModuleRegistry()', {
rules: { 'no-deprecated-functions': 'error' },
});
}).toThrow('oh noes!');
});
});
});
29 changes: 5 additions & 24 deletions src/rules/no-deprecated-functions.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import { AST_NODE_TYPES, type TSESTree } from '@typescript-eslint/utils';
import {
type JestVersion,
type EslintPluginJestRuleContext,
createRule,
detectJestVersion,
getJestVersion,
getNodeName,
} from './utils';

interface ContextSettings {
jest?: EslintPluginJestSettings;
}

interface EslintPluginJestSettings {
version: JestVersion | string;
}

const parseJestVersion = (rawVersion: number | string): JestVersion => {
if (typeof rawVersion === 'number') {
return rawVersion;
}

const [majorVersion] = rawVersion.split('.');

return parseInt(majorVersion, 10);
};

export default createRule({
name: __filename,
meta: {
Expand All @@ -40,10 +22,9 @@ export default createRule({
},
defaultOptions: [],
create(context) {
const jestVersion = parseJestVersion(
(context.settings as ContextSettings)?.jest?.version ||
detectJestVersion(),
);
// If jest version is not detected, assume latest
const jestVersion =
getJestVersion(context as EslintPluginJestRuleContext) || Infinity;

const deprecations: Record<string, string> = {
...(jestVersion >= 15 && {
Expand Down
12 changes: 5 additions & 7 deletions src/rules/utils/__tests__/detectJestVersion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,10 @@ describe('detectJestVersion', () => {
});

describe('when the package.json is missing the version property', () => {
it('throws an error', () => {
it('returns null', () => {
packageJsonFactory.mockReturnValue({});

expect(() => detectJestVersion()).toThrow(
/Unable to detect Jest version/iu,
);
expect(detectJestVersion()).toBeNull();
});
});

Expand Down Expand Up @@ -184,7 +182,7 @@ describe('detectJestVersion', () => {
});

describe('when jest is not installed', () => {
it('throws an error', () => {
it('returns null', () => {
const projectDir = setupFakeProject({
'package.json': { name: 'no-jest' },
[`node_modules/${relativePathToFn}`]: compiledFn,
Expand All @@ -193,8 +191,8 @@ describe('detectJestVersion', () => {

const { stdout, stderr } = runDetectJestVersion(projectDir);

expect(stdout).toBe('undefined');
expect(stderr).toContain('Unable to detect Jest version');
expect(stdout).toBe('null');
expect(stderr).toContain('');
});
});

Expand Down
49 changes: 42 additions & 7 deletions src/rules/utils/detectJestVersion.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import type { JSONSchemaForNPMPackageJsonFiles } from '@schemastore/package';
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';

interface ContextSettings {
[key: string]: unknown;
jest?: EslintPluginJestSettings;
}

interface EslintPluginJestSettings {
version: JestVersion | string;
}

export interface EslintPluginJestRuleContext
extends Readonly<RuleContext<never, []>> {
settings: ContextSettings;
}

export type JestVersion =
| 14
Expand All @@ -22,7 +37,25 @@ export type JestVersion =

let cachedJestVersion: JestVersion | null = null;

export const detectJestVersion = (): JestVersion => {
const parseJestVersion = (rawVersion: number | string): JestVersion => {
if (typeof rawVersion === 'number') {
return rawVersion;
}

const [majorVersion] = rawVersion.split('.');

return parseInt(majorVersion, 10);
};

export const getContextJestVersion = (
context: EslintPluginJestRuleContext,
): JestVersion | null => {
return context.settings.jest?.version
? parseJestVersion(context.settings.jest.version)
: null;
};

export const detectJestVersion = (): JestVersion | null => {
if (cachedJestVersion) {
return cachedJestVersion;
}
Expand All @@ -35,13 +68,15 @@ export const detectJestVersion = (): JestVersion => {
require(jestPath) as JSONSchemaForNPMPackageJsonFiles;

if (jestPackageJson.version) {
const [majorVersion] = jestPackageJson.version.split('.');

return (cachedJestVersion = parseInt(majorVersion, 10));
return (cachedJestVersion = parseJestVersion(jestPackageJson.version));
}
} catch {}

throw new Error(
'Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly',
);
return null;
};

export const getJestVersion = (
context: EslintPluginJestRuleContext,
): JestVersion | null => {
return getContextJestVersion(context) || detectJestVersion();
};
Loading