diff --git a/src/rules/__tests__/no-deprecated-functions.test.ts b/src/rules/__tests__/no-deprecated-functions.test.ts index eb2174e44..ea0588bb4 100644 --- a/src/rules/__tests__/no-deprecated-functions.test.ts +++ b/src/rules/__tests__/no-deprecated-functions.test.ts @@ -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(); @@ -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( @@ -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([ - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + describe.each>([ + 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[] = []; @@ -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; @@ -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, + ), ), }); @@ -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!'); - }); - }); }); diff --git a/src/rules/no-deprecated-functions.ts b/src/rules/no-deprecated-functions.ts index d83323d47..b50901b06 100644 --- a/src/rules/no-deprecated-functions.ts +++ b/src/rules/no-deprecated-functions.ts @@ -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: { @@ -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 = { ...(jestVersion >= 15 && { diff --git a/src/rules/utils/__tests__/detectJestVersion.test.ts b/src/rules/utils/__tests__/detectJestVersion.test.ts index 68fa16545..81a5d8b3a 100644 --- a/src/rules/utils/__tests__/detectJestVersion.test.ts +++ b/src/rules/utils/__tests__/detectJestVersion.test.ts @@ -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(); }); }); @@ -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, @@ -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(''); }); }); diff --git a/src/rules/utils/detectJestVersion.ts b/src/rules/utils/detectJestVersion.ts index 7935d9a6c..5e04b7cba 100644 --- a/src/rules/utils/detectJestVersion.ts +++ b/src/rules/utils/detectJestVersion.ts @@ -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> { + settings: ContextSettings; +} export type JestVersion = | 14 @@ -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; } @@ -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(); };