diff --git a/package.json b/package.json index 2cf26ac..df323ed 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@types/eslint": "9.6.1", "@typescript-eslint/parser": "^8.13.0", "@typescript-eslint/utils": "^8.13.0", + "@vitest/eslint-plugin": "^1.1.7", "astro-eslint-parser": "^1.0.3", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc5b0f3..e49a9c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: '@typescript-eslint/utils': specifier: ^8.13.0 version: 8.13.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@vitest/eslint-plugin': + specifier: ^1.1.7 + version: 1.1.7(@typescript-eslint/utils@8.13.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3))(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)(vitest@2.1.4(@types/node@22.9.0)) astro-eslint-parser: specifier: ^1.0.3 version: 1.0.3(typescript@5.6.3) @@ -1544,6 +1547,19 @@ packages: '@vitest/browser': optional: true + '@vitest/eslint-plugin@1.1.7': + resolution: {integrity: sha512-pTWGW3y6lH2ukCuuffpan6kFxG6nIuoesbhMiQxskyQMRcCN5t9SXsKrNHvEw3p8wcCsgJoRqFZVkOTn6TjclA==} + peerDependencies: + '@typescript-eslint/utils': '>= 8.0' + eslint: '>= 8.57.0' + typescript: '>= 5.0.0' + vitest: '*' + peerDependenciesMeta: + typescript: + optional: true + vitest: + optional: true + '@vitest/expect@2.1.4': resolution: {integrity: sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==} @@ -6326,6 +6342,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/eslint-plugin@1.1.7(@typescript-eslint/utils@8.13.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3))(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)(vitest@2.1.4(@types/node@22.9.0))': + dependencies: + '@typescript-eslint/utils': 8.13.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) + optionalDependencies: + typescript: 5.6.3 + vitest: 2.1.4(@types/node@22.9.0) + '@vitest/expect@2.1.4': dependencies: '@vitest/spy': 2.1.4 diff --git a/scripts/typegen.ts b/scripts/typegen.ts index 48483bb..9db7e52 100644 --- a/scripts/typegen.ts +++ b/scripts/typegen.ts @@ -15,7 +15,12 @@ const ruleDts = await flatConfigsToRulesDTS( }, }, // @ts-expect-error TODO: config types don't seem to match - ...config(), + ...config({ + testing: { + // TODO: remove when framework approach is removed + framework: "jest", + }, + }), ], { includeAugmentation: false, diff --git a/src/configs/testing.spec.ts b/src/configs/testing.spec.ts deleted file mode 100644 index 9ff8e70..0000000 --- a/src/configs/testing.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ALLOWED_VITEST_FUNCS } from "../constants"; -import testingConfig from "./testing"; - -describe("testingConfig", () => { - it("should create default config w/ vitest overrides", () => { - const [, vitest] = testingConfig({}, false); - - expect(vitest?.rules).toStrictEqual( - expect.objectContaining({ - "jest/no-deprecated-functions": "off", - "jest/require-hook": [ - "error", - { - allowedFunctionCalls: ALLOWED_VITEST_FUNCS, - }, - ], - }), - ); - }); - - it("should create default config w/o vitest overrides", () => { - const [, jest] = testingConfig({ framework: "jest" }, false); - - expect(jest?.rules).toStrictEqual( - expect.not.objectContaining({ - "jest/no-deprecated-functions": "off", - "jest/require-hook": [ - "error", - { - allowedFunctionCalls: ALLOWED_VITEST_FUNCS, - }, - ], - }), - ); - }); -}); diff --git a/src/configs/testing.ts b/src/configs/testing.ts index 916d661..fd08f29 100644 --- a/src/configs/testing.ts +++ b/src/configs/testing.ts @@ -1,10 +1,12 @@ +import vitest from "@vitest/eslint-plugin"; import jest from "eslint-plugin-jest"; import type { Rules, TestingOptions } from "../types"; -import { ALLOWED_VITEST_FUNCS, GLOB_E2E, GLOB_TESTS } from "../constants"; +import { GLOB_E2E, GLOB_TESTS } from "../constants"; import { hasJest, hasTestingLibrary, hasVitest } from "../has-dep"; import { jestRules } from "../rules/jest"; +import { vitestRules } from "../rules/vitest"; import testingLibraryConfig from "./testing-library"; const testingConfig = ( @@ -18,27 +20,13 @@ const testingConfig = ( (autoDetect && hasTestingLibrary()); return [ - { - files: GLOB_TESTS, - name: "jimmy.codes/testing", - ...jest.configs["flat/recommended"], - }, ...(isVitest ? [ { files: GLOB_TESTS, + ...vitest.configs.recommended, name: "jimmy.codes/testing/vitest", - ...jest.configs["flat/recommended"], - rules: { - ...jestRules, - "jest/no-deprecated-functions": "off", - "jest/require-hook": [ - "error", - { - allowedFunctionCalls: ALLOWED_VITEST_FUNCS, - }, - ], - } satisfies Rules, + rules: vitestRules, }, ] : []), @@ -46,8 +34,8 @@ const testingConfig = ( ? [ { files: GLOB_TESTS, - name: "jimmy.codes/testing/jest", ...jest.configs["flat/recommended"], + name: "jimmy.codes/testing/jest", rules: jestRules, }, ] @@ -59,6 +47,8 @@ const testingConfig = ( "jest/expect-expect": "off", "jest/no-deprecated-functions": "off", "jest/require-hook": "off", + "vitest/expect-expect": "off", + "vitest/require-hook": "off", } satisfies Rules, }, ...(includeTestingLibrary ? testingLibraryConfig() : []), diff --git a/src/factory.spec.ts b/src/factory.spec.ts index ec45789..a8baf41 100644 --- a/src/factory.spec.ts +++ b/src/factory.spec.ts @@ -62,7 +62,6 @@ describe("jimmyDotCodes", () => { jimmyDotCodes({ autoDetect: false, testing: { framework: "jest" } }), ).toStrictEqual( expect.arrayContaining([ - expect.objectContaining({ name: "jimmy.codes/testing" }), expect.objectContaining({ name: "jimmy.codes/testing/disabled" }), expect.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.not.objectContaining({ name: "jimmy.codes/testing/vitest" }), @@ -73,7 +72,6 @@ describe("jimmyDotCodes", () => { it("should create configuration w/ vitest", () => { expect(jimmyDotCodes({ autoDetect: false, testing: true })).toStrictEqual( expect.arrayContaining([ - expect.objectContaining({ name: "jimmy.codes/testing" }), expect.objectContaining({ name: "jimmy.codes/testing/disabled" }), expect.not.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.objectContaining({ name: "jimmy.codes/testing/vitest" }), @@ -90,7 +88,6 @@ describe("jimmyDotCodes", () => { }), ).toStrictEqual( expect.arrayContaining([ - expect.objectContaining({ name: "jimmy.codes/testing" }), expect.objectContaining({ name: "jimmy.codes/testing/disabled" }), expect.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.objectContaining({ name: "jimmy.codes/react" }), @@ -113,7 +110,6 @@ describe("jimmyDotCodes", () => { }), ).toStrictEqual( expect.arrayContaining([ - expect.objectContaining({ name: "jimmy.codes/testing" }), expect.objectContaining({ name: "jimmy.codes/testing/disabled" }), expect.objectContaining({ name: "jimmy.codes/testing/vitest" }), expect.objectContaining({ name: "jimmy.codes/react" }), @@ -186,7 +182,6 @@ describe("jimmyDotCodes", () => { it("should include react-query when auto detection is enabled", () => { vi.mocked(isPackageExists).mockImplementation((name) => { - // eslint-disable-next-line jest/no-conditional-in-test -- this condition is only for the mock. return name === "react" || name === "@tanstack/react-query"; }); @@ -213,7 +208,7 @@ describe("jimmyDotCodes", () => { expect(jimmyDotCodes({ autoDetect: true })).toStrictEqual( expect.arrayContaining([ expect.not.objectContaining({ name: "jimmy.codes/typescript" }), - expect.objectContaining({ name: "jimmy.codes/testing" }), + expect.objectContaining({ name: "jimmy.codes/testing/vitest" }), expect.not.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.not.objectContaining({ name: "jimmy.codes/react" }), @@ -233,7 +228,7 @@ describe("jimmyDotCodes", () => { expect(jimmyDotCodes({ autoDetect: true })).toStrictEqual( expect.arrayContaining([ expect.not.objectContaining({ name: "jimmy.codes/typescript" }), - expect.objectContaining({ name: "jimmy.codes/testing" }), + expect.not.objectContaining({ name: "jimmy.codes/testing/vitest" }), expect.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.not.objectContaining({ name: "jimmy.codes/react" }), @@ -247,14 +242,13 @@ describe("jimmyDotCodes", () => { it("should include test-library when auto detection is enabled", () => { vi.mocked(isPackageExists).mockImplementation((name) => { - // eslint-disable-next-line jest/no-conditional-in-test -- this condition is only for the mock. return name === "@testing-library/react" || name === "vitest"; }); expect(jimmyDotCodes({ autoDetect: true })).toStrictEqual( expect.arrayContaining([ expect.not.objectContaining({ name: "jimmy.codes/typescript" }), - expect.objectContaining({ name: "jimmy.codes/testing" }), + expect.objectContaining({ name: "jimmy.codes/testing/vitest" }), expect.not.objectContaining({ name: "jimmy.codes/testing/jest" }), expect.not.objectContaining({ name: "jimmy.codes/react" }), diff --git a/src/rules.gen.d.ts b/src/rules.gen.d.ts index 3ad607f..6d581c2 100644 --- a/src/rules.gen.d.ts +++ b/src/rules.gen.d.ts @@ -4977,6 +4977,314 @@ export interface RuleOptions { * @see https://eslint.org/docs/latest/rules/vars-on-top */ "vars-on-top"?: Linter.RuleEntry<[]>; + /** + * require .spec test file pattern + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/consistent-test-filename.md + */ + "vitest/consistent-test-filename"?: Linter.RuleEntry; + /** + * enforce using test or it but not both + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/consistent-test-it.md + */ + "vitest/consistent-test-it"?: Linter.RuleEntry; + /** + * enforce having expectation in test body + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/expect-expect.md + */ + "vitest/expect-expect"?: Linter.RuleEntry; + /** + * enforce a maximum number of expect per test + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/max-expects.md + */ + "vitest/max-expects"?: Linter.RuleEntry; + /** + * require describe block to be less than set max value or default value + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/max-nested-describe.md + */ + "vitest/max-nested-describe"?: Linter.RuleEntry; + /** + * disallow alias methods + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-alias-methods.md + */ + "vitest/no-alias-methods"?: Linter.RuleEntry<[]>; + /** + * disallow commented out tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-commented-out-tests.md + */ + "vitest/no-commented-out-tests"?: Linter.RuleEntry<[]>; + /** + * disallow conditional expects + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-expect.md + */ + "vitest/no-conditional-expect"?: Linter.RuleEntry<[]>; + /** + * disallow conditional tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-in-test.md + */ + "vitest/no-conditional-in-test"?: Linter.RuleEntry<[]>; + /** + * disallow conditional tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-tests.md + */ + "vitest/no-conditional-tests"?: Linter.RuleEntry<[]>; + /** + * disallow disabled tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md + */ + "vitest/no-disabled-tests"?: Linter.RuleEntry<[]>; + /** + * disallow using a callback in asynchronous tests and hooks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-done-callback.md + * @deprecated + */ + "vitest/no-done-callback"?: Linter.RuleEntry<[]>; + /** + * disallow duplicate hooks and teardown hooks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-duplicate-hooks.md + */ + "vitest/no-duplicate-hooks"?: Linter.RuleEntry<[]>; + /** + * disallow focused tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-focused-tests.md + */ + "vitest/no-focused-tests"?: Linter.RuleEntry; + /** + * disallow setup and teardown hooks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-hooks.md + */ + "vitest/no-hooks"?: Linter.RuleEntry; + /** + * disallow identical titles + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-identical-title.md + */ + "vitest/no-identical-title"?: Linter.RuleEntry<[]>; + /** + * disallow importing `node:test` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-import-node-test.md + */ + "vitest/no-import-node-test"?: Linter.RuleEntry<[]>; + /** + * disallow string interpolation in snapshots + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-interpolation-in-snapshots.md + */ + "vitest/no-interpolation-in-snapshots"?: Linter.RuleEntry<[]>; + /** + * disallow large snapshots + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-large-snapshots.md + */ + "vitest/no-large-snapshots"?: Linter.RuleEntry; + /** + * disallow importing from __mocks__ directory + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-mocks-import.md + */ + "vitest/no-mocks-import"?: Linter.RuleEntry<[]>; + /** + * disallow the use of certain matchers + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-restricted-matchers.md + */ + "vitest/no-restricted-matchers"?: Linter.RuleEntry; + /** + * disallow specific `vi.` methods + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-restricted-vi-methods.md + */ + "vitest/no-restricted-vi-methods"?: Linter.RuleEntry; + /** + * disallow using `expect` outside of `it` or `test` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-standalone-expect.md + */ + "vitest/no-standalone-expect"?: Linter.RuleEntry; + /** + * disallow using `test` as a prefix + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-test-prefixes.md + */ + "vitest/no-test-prefixes"?: Linter.RuleEntry<[]>; + /** + * disallow return statements in tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-test-return-statement.md + */ + "vitest/no-test-return-statement"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `afterAll` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-after-all-blocks.md + */ + "vitest/padding-around-after-all-blocks"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `afterEach` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-after-each-blocks.md + */ + "vitest/padding-around-after-each-blocks"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around vitest functions + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-all.md + */ + "vitest/padding-around-all"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `beforeAll` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-before-all-blocks.md + */ + "vitest/padding-around-before-all-blocks"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `beforeEach` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-before-each-blocks.md + */ + "vitest/padding-around-before-each-blocks"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `describe` blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-describe-blocks.md + */ + "vitest/padding-around-describe-blocks"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around `expect` groups + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-expect-groups.md + */ + "vitest/padding-around-expect-groups"?: Linter.RuleEntry<[]>; + /** + * Enforce padding around afterAll blocks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/padding-around-test-blocks.md + */ + "vitest/padding-around-test-blocks"?: Linter.RuleEntry<[]>; + /** + * enforce using `toBeCalledWith()` or `toHaveBeenCalledWith()` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-called-with.md + */ + "vitest/prefer-called-with"?: Linter.RuleEntry<[]>; + /** + * enforce using the built-in comparison matchers + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-comparison-matcher.md + */ + "vitest/prefer-comparison-matcher"?: Linter.RuleEntry<[]>; + /** + * enforce using `each` rather than manual loops + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-each.md + */ + "vitest/prefer-each"?: Linter.RuleEntry<[]>; + /** + * enforce using the built-in quality matchers + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-equality-matcher.md + */ + "vitest/prefer-equality-matcher"?: Linter.RuleEntry<[]>; + /** + * enforce using expect assertions instead of callbacks + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-expect-assertions.md + */ + "vitest/prefer-expect-assertions"?: Linter.RuleEntry; + /** + * enforce using `expect().resolves` over `expect(await ...)` syntax + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-expect-resolves.md + */ + "vitest/prefer-expect-resolves"?: Linter.RuleEntry<[]>; + /** + * enforce having hooks in consistent order + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-hooks-in-order.md + */ + "vitest/prefer-hooks-in-order"?: Linter.RuleEntry<[]>; + /** + * enforce having hooks before any test cases + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-hooks-on-top.md + */ + "vitest/prefer-hooks-on-top"?: Linter.RuleEntry<[]>; + /** + * enforce lowercase titles + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-lowercase-title.md + */ + "vitest/prefer-lowercase-title"?: Linter.RuleEntry; + /** + * enforce mock resolved/rejected shorthands for promises + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-mock-promise-shorthand.md + */ + "vitest/prefer-mock-promise-shorthand"?: Linter.RuleEntry<[]>; + /** + * enforce including a hint with external snapshots + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-snapshot-hint.md + */ + "vitest/prefer-snapshot-hint"?: Linter.RuleEntry; + /** + * enforce using `vi.spyOn` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-spy-on.md + */ + "vitest/prefer-spy-on"?: Linter.RuleEntry<[]>; + /** + * enforce strict equal over equal + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-strict-equal.md + */ + "vitest/prefer-strict-equal"?: Linter.RuleEntry<[]>; + /** + * enforce using toBe() + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be.md + */ + "vitest/prefer-to-be"?: Linter.RuleEntry<[]>; + /** + * enforce using toBeFalsy() + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-falsy.md + */ + "vitest/prefer-to-be-falsy"?: Linter.RuleEntry<[]>; + /** + * enforce using toBeObject() + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-object.md + */ + "vitest/prefer-to-be-object"?: Linter.RuleEntry<[]>; + /** + * enforce using `toBeTruthy` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-be-truthy.md + */ + "vitest/prefer-to-be-truthy"?: Linter.RuleEntry<[]>; + /** + * enforce using toContain() + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-contain.md + */ + "vitest/prefer-to-contain"?: Linter.RuleEntry<[]>; + /** + * enforce using toHaveLength() + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-have-length.md + */ + "vitest/prefer-to-have-length"?: Linter.RuleEntry<[]>; + /** + * enforce using `test.todo` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-todo.md + */ + "vitest/prefer-todo"?: Linter.RuleEntry<[]>; + /** + * Prefer `vi.mocked()` over `fn as Mock` + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-vi-mocked.md + */ + "vitest/prefer-vi-mocked"?: Linter.RuleEntry<[]>; + /** + * require setup and teardown to be within a hook + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/require-hook.md + */ + "vitest/require-hook"?: Linter.RuleEntry; + /** + * require local Test Context for concurrent snapshot tests + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/require-local-test-context-for-concurrent-snapshots.md + */ + "vitest/require-local-test-context-for-concurrent-snapshots"?: Linter.RuleEntry< + [] + >; + /** + * require toThrow() to be called with an error message + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/require-to-throw-message.md + */ + "vitest/require-to-throw-message"?: Linter.RuleEntry<[]>; + /** + * enforce that all tests are in a top-level describe + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/require-top-level-describe.md + */ + "vitest/require-top-level-describe"?: Linter.RuleEntry; + /** + * enforce valid describe callback + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/valid-describe-callback.md + */ + "vitest/valid-describe-callback"?: Linter.RuleEntry<[]>; + /** + * enforce valid `expect()` usage + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/valid-expect.md + */ + "vitest/valid-expect"?: Linter.RuleEntry; + /** + * enforce valid titles + * @see https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/valid-title.md + */ + "vitest/valid-title"?: Linter.RuleEntry; /** * Require parentheses around immediate `function` invocations * @see https://eslint.org/docs/latest/rules/wrap-iife @@ -17321,6 +17629,169 @@ type ValidTypeof = requireStringLiterals?: boolean; }, ]; +// ----- vitest/consistent-test-filename ----- +type VitestConsistentTestFilename = + | [] + | [ + { + pattern?: string; + allTestPattern?: string; + }, + ]; +// ----- vitest/consistent-test-it ----- +type VitestConsistentTestIt = + | [] + | [ + { + fn?: "test" | "it"; + withinDescribe?: "test" | "it"; + }, + ]; +// ----- vitest/expect-expect ----- +type VitestExpectExpect = + | [] + | [ + { + assertFunctionNames?: [] | [string]; + additionalTestBlockFunctions?: string[]; + }, + ]; +// ----- vitest/max-expects ----- +type VitestMaxExpects = + | [] + | [ + { + max?: number; + }, + ]; +// ----- vitest/max-nested-describe ----- +type VitestMaxNestedDescribe = + | [] + | [ + { + max?: number; + }, + ]; +// ----- vitest/no-focused-tests ----- +type VitestNoFocusedTests = + | [] + | [ + { + fixable?: boolean; + }, + ]; +// ----- vitest/no-hooks ----- +type VitestNoHooks = + | [] + | [ + { + allow?: unknown[]; + }, + ]; +// ----- vitest/no-large-snapshots ----- +type VitestNoLargeSnapshots = + | [] + | [ + { + maxSize?: number; + inlineMaxSize?: number; + allowedSnapshots?: { + [k: string]: unknown[] | undefined; + }; + }, + ]; +// ----- vitest/no-restricted-matchers ----- +type VitestNoRestrictedMatchers = + | [] + | [ + { + [k: string]: (string | null) | undefined; + }, + ]; +// ----- vitest/no-restricted-vi-methods ----- +type VitestNoRestrictedViMethods = + | [] + | [ + { + [k: string]: (string | null) | undefined; + }, + ]; +// ----- vitest/no-standalone-expect ----- +type VitestNoStandaloneExpect = + | [] + | [ + { + additionaltestblockfunctions?: string[]; + [k: string]: unknown | undefined; + }, + ]; +// ----- vitest/prefer-expect-assertions ----- +type VitestPreferExpectAssertions = + | [] + | [ + { + onlyFunctionsWithAsyncKeyword?: boolean; + onlyFunctionsWithExpectInLoop?: boolean; + onlyFunctionsWithExpectInCallback?: boolean; + }, + ]; +// ----- vitest/prefer-lowercase-title ----- +type VitestPreferLowercaseTitle = + | [] + | [ + { + ignore?: ("describe" | "test" | "it")[]; + allowedPrefixes?: string[]; + ignoreTopLevelDescribe?: boolean; + lowercaseFirstCharacterOnly?: boolean; + }, + ]; +// ----- vitest/prefer-snapshot-hint ----- +type VitestPreferSnapshotHint = [] | ["always" | "multi"]; +// ----- vitest/require-hook ----- +type VitestRequireHook = + | [] + | [ + { + allowedFunctionCalls?: string[]; + }, + ]; +// ----- vitest/require-top-level-describe ----- +type VitestRequireTopLevelDescribe = + | [] + | [ + { + maxNumberOfTopLevelDescribes?: number; + }, + ]; +// ----- vitest/valid-expect ----- +type VitestValidExpect = + | [] + | [ + { + alwaysAwait?: boolean; + asyncMatchers?: string[]; + minArgs?: number; + maxArgs?: number; + }, + ]; +// ----- vitest/valid-title ----- +type VitestValidTitle = + | [] + | [ + { + ignoreTypeOfDescribeName?: boolean; + allowArguments?: boolean; + disallowedWords?: string[]; + [k: string]: + | string + | [string] + | [string, string] + | { + [k: string]: (string | [string] | [string, string]) | undefined; + }; + }, + ]; // ----- wrap-iife ----- type WrapIife = | [] diff --git a/src/rules/vitest.ts b/src/rules/vitest.ts new file mode 100644 index 0000000..98d757c --- /dev/null +++ b/src/rules/vitest.ts @@ -0,0 +1,46 @@ +import vitest from "@vitest/eslint-plugin"; + +import type { Rules } from "../types"; + +export const vitestRules = { + ...vitest.configs.recommended.rules, + "vitest/consistent-test-it": [ + "error", + { + fn: "test", + withinDescribe: "it", + }, + ], + "vitest/no-alias-methods": "error", + "vitest/no-commented-out-tests": "error", + "vitest/no-conditional-in-test": "error", + // "vitest/no-confusing-set-timeout": "error", // missing + "vitest/no-duplicate-hooks": "error", + "vitest/no-hooks": "off", + "vitest/no-large-snapshots": "off", + "vitest/no-restricted-matchers": "off", + "vitest/no-restricted-vi-methods": "off", + "vitest/no-test-return-statement": "error", + // "vitest/no-untyped-mock-factory": "off", // requires typescript + "vitest/prefer-called-with": "error", + "vitest/prefer-comparison-matcher": "error", + "vitest/prefer-each": "error", + "vitest/prefer-equality-matcher": "error", + "vitest/prefer-expect-assertions": "off", + "vitest/prefer-expect-resolves": "error", + "vitest/prefer-hooks-in-order": "error", + "vitest/prefer-hooks-on-top": "error", + "vitest/prefer-lowercase-title": "off", + "vitest/prefer-mock-promise-shorthand": "error", + "vitest/prefer-snapshot-hint": "error", + "vitest/prefer-spy-on": "off", + "vitest/prefer-strict-equal": "error", + "vitest/prefer-to-be": "error", + "vitest/prefer-to-contain": "error", + "vitest/prefer-to-have-length": "error", + "vitest/prefer-todo": "warn", + "vitest/require-hook": "error", + "vitest/require-to-throw-message": "error", + "vitest/require-top-level-describe": "off", + // "vitest/unbound-method": "off", // requires typescript, no types https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/unbound-method.md +} satisfies Rules;