From 0ae4289d465a03a42ecc686b0a42b9e9ef9b4d10 Mon Sep 17 00:00:00 2001 From: Yukihiro Hasegawa <49516827+y-hsgw@users.noreply.github.com> Date: Sun, 12 Jan 2025 18:32:03 +0900 Subject: [PATCH] fix(consistent-test-it): Remove duplicate imports inside the import statement (#638) * refactor: execute lint:js * fix: remove duplicate imports inside the import statement --- src/index.ts | 7 ++-- src/rules/consistent-test-it.ts | 19 ++++++++--- src/utils/index.ts | 2 +- tests/consistent-test-it.test.ts | 56 ++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index b13c01a..9caa8cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import type { Linter } from '@typescript-eslint/utils/ts-eslint' -import type { ESLint } from "eslint" +import type { ESLint } from 'eslint' import { version } from '../package.json' import lowerCaseTitle, { RULE_NAME as lowerCaseTitleName } from './rules/prefer-lowercase-title' import maxNestedDescribe, { RULE_NAME as maxNestedDescribeName } from './rules/max-nested-describe' @@ -71,8 +71,8 @@ const createConfig = (rules: R) => ( [`vitest/${ruleName}`]: rules[ruleName] } }, {})) as { - [K in keyof R as `vitest/${Extract}`]: R[K] - } + [K in keyof R as `vitest/${Extract}`]: R[K] +} const createConfigLegacy = (rules: Record) => ({ plugins: ['@vitest'], @@ -160,7 +160,6 @@ const recommended = { [noImportNodeTestName]: 'error' } as const - const plugin = { meta: { name: 'vitest', diff --git a/src/rules/consistent-test-it.ts b/src/rules/consistent-test-it.ts index 617543f..5c5625b 100644 --- a/src/rules/consistent-test-it.ts +++ b/src/rules/consistent-test-it.ts @@ -110,10 +110,21 @@ export default createEslintRule< node: specifier, data: { testFnKeyWork, oppositeTestKeyword }, messageId: 'consistentMethod', - fix: fixer => fixer.replaceText( - specifier.local, - testFnDisabled - ) + fix: (fixer) => { + const remainingSpecifiers = node.specifiers.filter(spec => spec.local.name !== oppositeTestKeyword) + if (remainingSpecifiers.length > 0) { + const importText = remainingSpecifiers.map(spec => spec.local.name).join(', ') + const lastSpecifierRange = node.specifiers.at(-1)?.range + if (!lastSpecifierRange) return null + + return fixer.replaceTextRange( + [node.specifiers[0].range[0], lastSpecifierRange[1]], + importText + ) + } + + return fixer.replaceText(specifier.local, testFnDisabled) + } }) } } diff --git a/src/utils/index.ts b/src/utils/index.ts index 54bc756..2c986db 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -10,7 +10,7 @@ import { KnownMemberExpression, ParsedExpectVitestFnCall } from './parse-vitest-fn-call' -import { Rule } from "eslint" +import { Rule } from 'eslint' export interface PluginDocs { recommended?: boolean diff --git a/tests/consistent-test-it.test.ts b/tests/consistent-test-it.test.ts index 2eec85c..659690f 100644 --- a/tests/consistent-test-it.test.ts +++ b/tests/consistent-test-it.test.ts @@ -84,6 +84,33 @@ ruleTester.run(RULE_NAME, rule, { options: [{ fn: TestCaseName.it }], output: 'import { it } from "vitest"\nit("shows error", () => {});', errors: [{ messageId: 'consistentMethod' }, { messageId: 'consistentMethod' }] + }, + { + code: 'import { expect, test, it } from "vitest"\ntest("shows error", () => {});', + options: [{ fn: TestCaseName.it }], + output: 'import { expect, it } from "vitest"\nit("shows error", () => {});', + errors: [ + { + messageId: 'consistentMethod', + data: { + testFnKeyWork: TestCaseName.it, + oppositeTestKeyword: TestCaseName.test + }, + line: 1, + column: 18, + endColumn: 22 + }, + { + messageId: 'consistentMethod', + data: { + testFnKeyWork: TestCaseName.it, + oppositeTestKeyword: TestCaseName.test + }, + line: 2, + column: 1, + endColumn: 5 + } + ] } ] }) @@ -303,6 +330,35 @@ ruleTester.run(RULE_NAME, rule, { } ] }, + { + code: 'import { expect, it, test } from "vitest"\nit("foo")', + output: 'import { expect, test } from "vitest"\ntest("foo")', + options: [ + { withinDescribe: TestCaseName.test } + ], + errors: [ + { + messageId: 'consistentMethod', + data: { + testFnKeyWork: TestCaseName.test, + oppositeTestKeyword: TestCaseName.it + }, + line: 1, + column: 18, + endColumn: 20 + }, + { + messageId: 'consistentMethod', + data: { + testFnKeyWork: TestCaseName.test, + oppositeTestKeyword: TestCaseName.it + }, + line: 2, + column: 1, + endColumn: 3 + } + ] + }, { code: 'describe("suite", () => { it("foo") })', output: 'describe("suite", () => { test("foo") })',