From e1a7b0852b6091fa9ed60c5a2a5d2434c7617013 Mon Sep 17 00:00:00 2001 From: Erin Zimmer Date: Fri, 30 Aug 2024 13:16:14 +1000 Subject: [PATCH 1/3] fix(prefer-importing-jest-globals): ensure imports aren't inserted in the middle of a statement --- .../prefer-importing-jest-globals.test.ts | 57 ++++++++++++++++++- src/rules/prefer-importing-jest-globals.ts | 22 ++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/rules/__tests__/prefer-importing-jest-globals.test.ts b/src/rules/__tests__/prefer-importing-jest-globals.test.ts index ea5125711..563738883 100644 --- a/src/rules/__tests__/prefer-importing-jest-globals.test.ts +++ b/src/rules/__tests__/prefer-importing-jest-globals.test.ts @@ -228,8 +228,8 @@ ruleTester.run('prefer-importing-jest-globals', rule, { }); `, output: dedent` - import { pending } from 'actions'; import { describe, test } from '@jest/globals'; + import { pending } from 'actions'; describe('foo', () => { test.each(['hello', 'world'])("%s", (a) => {}); }); @@ -546,6 +546,61 @@ ruleTester.run('prefer-importing-jest-globals', rule, { }, ], }, + { + code: dedent` + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, + output: dedent` + console.log('hello'); + const { describe, expect, jest, test } = require('@jest/globals'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, + errors: [ + { + endColumn: 21, + column: 17, + line: 2, + messageId: 'preferImportingJestGlobal', + }, + ], + }, + { + code: dedent` + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, + output: dedent` + import { describe, expect, jest, test } from '@jest/globals'; + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, + parserOptions: { sourceType: 'module' }, + errors: [ + { + endColumn: 21, + column: 17, + line: 2, + messageId: 'preferImportingJestGlobal', + }, + ], + }, ], }); diff --git a/src/rules/prefer-importing-jest-globals.ts b/src/rules/prefer-importing-jest-globals.ts index fcc3bc75f..f84c64e09 100644 --- a/src/rules/prefer-importing-jest-globals.ts +++ b/src/rules/prefer-importing-jest-globals.ts @@ -21,6 +21,22 @@ const createFixerImports = ( : `const { ${allImportsFormatted} } = require('@jest/globals');`; }; +const findInsertionPoint = (reportingNode: TSESTree.Node) => { + let currentNode = reportingNode; + + while ( + currentNode.parent && + currentNode.parent.type !== AST_NODE_TYPES.Program && + currentNode.parent.type !== AST_NODE_TYPES.VariableDeclaration + ) { + currentNode = currentNode.parent; + } + + return currentNode.parent?.type === AST_NODE_TYPES.VariableDeclaration + ? currentNode.parent + : reportingNode; +}; + const allJestFnTypes: JestFnType[] = [ 'hook', 'describe', @@ -151,8 +167,12 @@ export default createRule({ ); if (requireNode?.type !== AST_NODE_TYPES.VariableDeclaration) { + const insertBeforeNode = isModule + ? firstNode + : findInsertionPoint(reportingNode); + return fixer.insertTextBefore( - reportingNode, + insertBeforeNode, `${createFixerImports(isModule, functionsToImport)}\n`, ); } From 0f41ddc628fc37b57545288c62f0e8facbccba1f Mon Sep 17 00:00:00 2001 From: Erin Zimmer Date: Tue, 3 Sep 2024 08:15:12 +1000 Subject: [PATCH 2/3] fix(prefer-importing-jest-globals): fix indenting --- .../prefer-importing-jest-globals.test.ts | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/rules/__tests__/prefer-importing-jest-globals.test.ts b/src/rules/__tests__/prefer-importing-jest-globals.test.ts index 563738883..acd6a1b5c 100644 --- a/src/rules/__tests__/prefer-importing-jest-globals.test.ts +++ b/src/rules/__tests__/prefer-importing-jest-globals.test.ts @@ -548,22 +548,22 @@ ruleTester.run('prefer-importing-jest-globals', rule, { }, { code: dedent` - console.log('hello'); - const onClick = jest.fn(); - describe("suite", () => { - test("foo"); - expect(onClick).toHaveBeenCalled(); - }) - `, + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, output: dedent` - console.log('hello'); - const { describe, expect, jest, test } = require('@jest/globals'); - const onClick = jest.fn(); - describe("suite", () => { - test("foo"); - expect(onClick).toHaveBeenCalled(); - }) - `, + console.log('hello'); + const { describe, expect, jest, test } = require('@jest/globals'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) + `, errors: [ { endColumn: 21, @@ -575,21 +575,21 @@ ruleTester.run('prefer-importing-jest-globals', rule, { }, { code: dedent` - console.log('hello'); - const onClick = jest.fn(); - describe("suite", () => { - test("foo"); - expect(onClick).toHaveBeenCalled(); - }) + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) `, output: dedent` - import { describe, expect, jest, test } from '@jest/globals'; - console.log('hello'); - const onClick = jest.fn(); - describe("suite", () => { - test("foo"); - expect(onClick).toHaveBeenCalled(); - }) + import { describe, expect, jest, test } from '@jest/globals'; + console.log('hello'); + const onClick = jest.fn(); + describe("suite", () => { + test("foo"); + expect(onClick).toHaveBeenCalled(); + }) `, parserOptions: { sourceType: 'module' }, errors: [ From f33e4d92f17240d87008f939866a584f193f5c1d Mon Sep 17 00:00:00 2001 From: Erin Zimmer Date: Tue, 3 Sep 2024 08:44:55 +1000 Subject: [PATCH 3/3] fix(prefer-importing-jest-globals): give commonjs and esmodules the same import behaviour --- .../prefer-importing-jest-globals.test.ts | 10 ++++----- src/rules/prefer-importing-jest-globals.ts | 22 +------------------ 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/rules/__tests__/prefer-importing-jest-globals.test.ts b/src/rules/__tests__/prefer-importing-jest-globals.test.ts index acd6a1b5c..fde6afd48 100644 --- a/src/rules/__tests__/prefer-importing-jest-globals.test.ts +++ b/src/rules/__tests__/prefer-importing-jest-globals.test.ts @@ -304,11 +304,11 @@ ruleTester.run('prefer-importing-jest-globals', rule, { `, // todo: this shouldn't be indenting the "test" output: dedent` + const { expect, test } = require('@jest/globals'); const source = 'globals'; const {describe} = require(\`@jest/\${source}\`); describe("suite", () => { - const { expect, test } = require('@jest/globals'); - test("foo"); + test("foo"); expect(true).toBeDefined(); }) `, @@ -407,8 +407,8 @@ ruleTester.run('prefer-importing-jest-globals', rule, { }); `, output: dedent` - const { pending } = require('actions'); const { describe, test } = require('@jest/globals'); + const { pending } = require('actions'); describe('foo', () => { test.each(['hello', 'world'])("%s", (a) => {}); }); @@ -552,12 +552,12 @@ ruleTester.run('prefer-importing-jest-globals', rule, { const onClick = jest.fn(); describe("suite", () => { test("foo"); - expect(onClick).toHaveBeenCalled(); + expect(onClick).toHaveBeenCalled(); }) `, output: dedent` - console.log('hello'); const { describe, expect, jest, test } = require('@jest/globals'); + console.log('hello'); const onClick = jest.fn(); describe("suite", () => { test("foo"); diff --git a/src/rules/prefer-importing-jest-globals.ts b/src/rules/prefer-importing-jest-globals.ts index f84c64e09..66afbd3f0 100644 --- a/src/rules/prefer-importing-jest-globals.ts +++ b/src/rules/prefer-importing-jest-globals.ts @@ -21,22 +21,6 @@ const createFixerImports = ( : `const { ${allImportsFormatted} } = require('@jest/globals');`; }; -const findInsertionPoint = (reportingNode: TSESTree.Node) => { - let currentNode = reportingNode; - - while ( - currentNode.parent && - currentNode.parent.type !== AST_NODE_TYPES.Program && - currentNode.parent.type !== AST_NODE_TYPES.VariableDeclaration - ) { - currentNode = currentNode.parent; - } - - return currentNode.parent?.type === AST_NODE_TYPES.VariableDeclaration - ? currentNode.parent - : reportingNode; -}; - const allJestFnTypes: JestFnType[] = [ 'hook', 'describe', @@ -167,12 +151,8 @@ export default createRule({ ); if (requireNode?.type !== AST_NODE_TYPES.VariableDeclaration) { - const insertBeforeNode = isModule - ? firstNode - : findInsertionPoint(reportingNode); - return fixer.insertTextBefore( - insertBeforeNode, + firstNode, `${createFixerImports(isModule, functionsToImport)}\n`, ); }