Skip to content

Commit

Permalink
test: migrate test to eslint-vitest-rule-tester
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaStevens committed Aug 3, 2024
1 parent ecb384d commit e87cfe1
Show file tree
Hide file tree
Showing 133 changed files with 10,791 additions and 10,745 deletions.
23 changes: 5 additions & 18 deletions .github/workflows/test-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,29 @@ jobs:
- "20"
- "latest"
ts_version:
- "next"
# - "next"
- "latest"
- "4.7.4"
# - "4.7.4"
# - "JS"
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.ts_version == 'next' }}
env:
REPORT_COVERAGE: ${{ fromJSON('["false", "true"]')[matrix.node_version == 'latest' && matrix.os == 'ubuntu-latest'] }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/prepare

- name: Build
run: pnpm run build:node

- name: Compile Tests
run: pnpm run build-tests

- name: Setup NodeJs ${{ matrix.node_version }} for testing
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node_version }}

- name: Remove Dev TypeScript
run: pnpm remove typescript

- name: Add TypeScript "${{ matrix.ts_version }}"
if: matrix.ts_version != 'JS'
run: pnpm add -D typescript@"${{ matrix.ts_version }}"
# - name: Add TypeScript "${{ matrix.ts_version }}" for testing
# run: pnpm add -D typescript@"${{ matrix.ts_version }}"

- name: Run Tests
run: pnpm test-compiled
run: pnpm test:js-run

- name: Report coverage
uses: codecov/[email protected]
if: env.REPORT_COVERAGE == 'true'
with:
file: coverage/lcov.info
flags: ${{ matrix.ts_version }}
1 change: 0 additions & 1 deletion knip.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"ignore": ["tests/fixture/file.ts"],
"ignoreDependencies": [
// Unknown reason for issue.
"@vitest/coverage-istanbul",
"@vitest/coverage-v8",

// Lint staged
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"files": ["lib/", "package.json", "LICENSE", "README.md"],
"scripts": {
"build": "pnpm run build:node && pnpm run build:docs",
"build-tests": "rimraf tests-compiled && tsc -p tsconfig.tests-compiled.json && tsc-alias -p tsconfig.tests-compiled.json",
"build:docs": "eslint-doc-generator",
"build:node": "rimraf lib && rollup -c rollup.config.ts --configPlugin rollup-plugin-ts",
"lint": "eslint && pnpm run lint:md && pnpm lint:eslint-docs && pnpm run lint:spelling && pnpm run lint:knip && pnpm run lint:packages",
Expand All @@ -63,11 +62,11 @@
"prepare": "husky",
"release": "semantic-release",
"test": "pnpm run test:js",
"test-compiled": "USE_COMPILED_TESTS=1 vitest run --coverage",
"test-work": "vitest",
"test:js": "vitest --coverage",
"test:js-run": "vitest run --coverage",
"typecheck": "tsc -p tsconfig.build.json --noEmit",
"verify": "pnpm run lint && pnpm run typecheck && pnpm run build-tests && pnpm run test-compiled"
"verify": "pnpm run lint && pnpm run typecheck && pnpm run test:js-run"
},
"overrides": {
"eslint-plugin-functional": "link:."
Expand All @@ -91,12 +90,9 @@
"@semantic-release/release-notes-generator": "14.0.1",
"@stylistic/eslint-plugin": "2.6.1",
"@types/dedent": "0.7.2",
"@types/espree": "10.1.0",
"@types/node": "18.18.0",
"@typescript-eslint/eslint-plugin": "8.0.0",
"@typescript-eslint/parser": "8.0.0",
"@typescript-eslint/rule-tester": "8.0.0",
"@vitest/coverage-istanbul": "2.0.5",
"@vitest/coverage-v8": "2.0.5",
"cspell": "8.13.1",
"deassert": "1.0.2",
Expand Down Expand Up @@ -124,7 +120,7 @@
"eslint-plugin-unicorn": "55.0.0",
"eslint-plugin-vitest": "0.5.4",
"eslint-plugin-yml": "1.14.0",
"espree": "10.1.0",
"eslint-vitest-rule-tester": "0.3.3",
"fast-glob": "3.3.2",
"husky": "9.1.4",
"jsonc-eslint-parser": "2.4.0",
Expand All @@ -138,7 +134,6 @@
"rollup-plugin-ts": "3.4.5",
"semantic-release": "24.0.0",
"semantic-release-replace-plugin": "1.2.7",
"tsc-alias": "1.8.10",
"tsc-files": "1.1.4",
"tsx": "4.16.5",
"typescript": "5.5.4",
Expand All @@ -158,5 +153,10 @@
"packageManager": "[email protected]",
"engines": {
"node": ">=v18.18.0"
},
"pnpm": {
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
}
}
}
209 changes: 209 additions & 0 deletions patches/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
diff --git a/dist/index.d.mts b/dist/index.d.mts
index f982c4d7c06d00d8f1e9f7515951582be0cc1f59..7245940c64de19f60428239bcccca0658bb64a7b 100644
--- a/dist/index.d.mts
+++ b/dist/index.d.mts
@@ -93,6 +93,12 @@ interface RuleTesterBehaviorOptions {
*/
verifyFixChanges?: boolean;
}
+interface DefaultFilenames {
+ js: string;
+ jsx: string;
+ ts: string;
+ tsx: string;
+}
interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorOptions {
/**
* The rule to test
@@ -106,6 +112,11 @@ interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorO
* Additional flat configs to be merged with the rule config
*/
configs?: Linter.FlatConfig | Linter.FlatConfig[];
+ /**
+ * The default filenames to use for type-aware tests.
+ * @default { js: 'file.js', jsx: 'react.jsx', ts: 'file.ts', tsx: 'react.tsx' }
+ */
+ defaultFilenames?: Partial<DefaultFilenames>;
}
interface TestCasesOptions {
valid?: (ValidTestCase | string)[];
@@ -116,8 +127,10 @@ interface TestCasesOptions {
onResult?: (_case: NormalizedTestCase, result: Linter.FixReport) => void | Promise<void>;
}

-declare function normalizeTestCase(c: TestCase, type?: 'valid' | 'invalid'): NormalizedTestCase;
+declare function normalizeTestCase(c: TestCase, languageOptions: Linter.FlatConfig['languageOptions'], defaultFilenames: DefaultFilenames, type?: 'valid' | 'invalid'): NormalizedTestCase;
declare function normalizeCaseError(error: TestCaseError | string, rule?: RuleModule): Partial<Linter.LintMessage>;
+declare function isUsingTypeScriptParser(languageOptions: Linter.FlatConfig['languageOptions']): boolean;
+declare function isUsingTypeScriptTypings(languageOptions: Linter.FlatConfig['languageOptions']): any;

declare function createRuleTester(options: RuleTesterInitOptions): RuleTester;

@@ -132,4 +145,4 @@ declare function runClassic(ruleName: string, rule: RuleModule, cases: TestCases

declare function pickFlatConfigFromOptions(options: CompatConfigOptions): Linter.FlatConfig | undefined;

-export { type CompatConfigOptions, type InvalidTestCase, type InvalidTestCaseBase, type NormalizedTestCase, type RuleModule, type RuleTester, type RuleTesterBehaviorOptions, type RuleTesterInitOptions, type TestCase, type TestCaseError, type TestCasesOptions, type TestExecutionResult, type ValidTestCase, type ValidTestCaseBase, createRuleTester, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
+export { type CompatConfigOptions, type DefaultFilenames, type InvalidTestCase, type InvalidTestCaseBase, type NormalizedTestCase, type RuleModule, type RuleTester, type RuleTesterBehaviorOptions, type RuleTesterInitOptions, type TestCase, type TestCaseError, type TestCasesOptions, type TestExecutionResult, type ValidTestCase, type ValidTestCaseBase, createRuleTester, isUsingTypeScriptParser, isUsingTypeScriptTypings, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
diff --git a/dist/index.d.ts b/dist/index.d.ts
index f982c4d7c06d00d8f1e9f7515951582be0cc1f59..7245940c64de19f60428239bcccca0658bb64a7b 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -93,6 +93,12 @@ interface RuleTesterBehaviorOptions {
*/
verifyFixChanges?: boolean;
}
+interface DefaultFilenames {
+ js: string;
+ jsx: string;
+ ts: string;
+ tsx: string;
+}
interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorOptions {
/**
* The rule to test
@@ -106,6 +112,11 @@ interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorO
* Additional flat configs to be merged with the rule config
*/
configs?: Linter.FlatConfig | Linter.FlatConfig[];
+ /**
+ * The default filenames to use for type-aware tests.
+ * @default { js: 'file.js', jsx: 'react.jsx', ts: 'file.ts', tsx: 'react.tsx' }
+ */
+ defaultFilenames?: Partial<DefaultFilenames>;
}
interface TestCasesOptions {
valid?: (ValidTestCase | string)[];
@@ -116,8 +127,10 @@ interface TestCasesOptions {
onResult?: (_case: NormalizedTestCase, result: Linter.FixReport) => void | Promise<void>;
}

-declare function normalizeTestCase(c: TestCase, type?: 'valid' | 'invalid'): NormalizedTestCase;
+declare function normalizeTestCase(c: TestCase, languageOptions: Linter.FlatConfig['languageOptions'], defaultFilenames: DefaultFilenames, type?: 'valid' | 'invalid'): NormalizedTestCase;
declare function normalizeCaseError(error: TestCaseError | string, rule?: RuleModule): Partial<Linter.LintMessage>;
+declare function isUsingTypeScriptParser(languageOptions: Linter.FlatConfig['languageOptions']): boolean;
+declare function isUsingTypeScriptTypings(languageOptions: Linter.FlatConfig['languageOptions']): any;

declare function createRuleTester(options: RuleTesterInitOptions): RuleTester;

@@ -132,4 +145,4 @@ declare function runClassic(ruleName: string, rule: RuleModule, cases: TestCases

declare function pickFlatConfigFromOptions(options: CompatConfigOptions): Linter.FlatConfig | undefined;

-export { type CompatConfigOptions, type InvalidTestCase, type InvalidTestCaseBase, type NormalizedTestCase, type RuleModule, type RuleTester, type RuleTesterBehaviorOptions, type RuleTesterInitOptions, type TestCase, type TestCaseError, type TestCasesOptions, type TestExecutionResult, type ValidTestCase, type ValidTestCaseBase, createRuleTester, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
+export { type CompatConfigOptions, type DefaultFilenames, type InvalidTestCase, type InvalidTestCaseBase, type NormalizedTestCase, type RuleModule, type RuleTester, type RuleTesterBehaviorOptions, type RuleTesterInitOptions, type TestCase, type TestCaseError, type TestCasesOptions, type TestExecutionResult, type ValidTestCase, type ValidTestCaseBase, createRuleTester, isUsingTypeScriptParser, isUsingTypeScriptTypings, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
diff --git a/dist/index.mjs b/dist/index.mjs
index b10c991352ad54b17a05f8e41fe6d4b5e1f77ea1..b426a2540622b4bfd31d70598f971a280fe53ec5 100644
--- a/dist/index.mjs
+++ b/dist/index.mjs
@@ -1,4 +1,6 @@
-import { objectPick, toArray } from '@antfu/utils';
+import path from 'node:path';
+import process from 'node:process';
+import { objectPick, deepMerge, toArray } from '@antfu/utils';
export { unindent as $, unindent } from '@antfu/utils';
import { Linter } from 'eslint';
import { expect, describe, it } from 'vitest';
@@ -17,10 +19,21 @@ function interpolate(text, data) {
);
}

-function normalizeTestCase(c, type) {
+function normalizeTestCase(c, languageOptions, defaultFilenames, type) {
const obj = typeof c === "string" ? { code: c } : { ...c };
const normalized = obj;
normalized.type || (normalized.type = type || ("errors" in obj || "output" in obj ? "invalid" : "valid"));
+ if (isUsingTypeScriptParser(languageOptions)) {
+ normalized.filename || (normalized.filename = getDefaultTypeScriptFilename(languageOptions, defaultFilenames));
+ normalized.parserOptions = {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ disallowAutomaticSingleRunInference: true,
+ ...normalized.parserOptions
+ };
+ } else {
+ normalized.filename || (normalized.filename = getDefaultJavaScriptFilename(languageOptions, defaultFilenames));
+ }
return normalized;
}
function normalizeCaseError(error, rule) {
@@ -46,6 +59,20 @@ function normalizeCaseError(error, rule) {
}
return clone;
}
+function getDefaultJavaScriptFilename(languageOptions, defaultFilenames) {
+ return languageOptions?.parserOptions?.ecmaFeatures?.jsx ? defaultFilenames.jsx : defaultFilenames.js;
+}
+function getDefaultTypeScriptFilename(languageOptions, defaultFilenames) {
+ const rootPath = (isUsingTypeScriptTypings(languageOptions) ? languageOptions?.parserOptions?.tsconfigRootDir : void 0) ?? process.cwd();
+ const filename = languageOptions?.parserOptions?.ecmaFeatures?.jsx ? defaultFilenames.tsx : defaultFilenames.ts;
+ return path.join(rootPath, filename);
+}
+function isUsingTypeScriptParser(languageOptions) {
+ return languageOptions?.parser?.meta?.name === "typescript-eslint/parser";
+}
+function isUsingTypeScriptTypings(languageOptions) {
+ return languageOptions?.parserOptions?.program || languageOptions?.parserOptions?.project || languageOptions?.parserOptions?.projectService;
+}

const BOM = "\uFEFF";
function compareMessagesByFixRange(a, b) {
@@ -139,15 +166,32 @@ function pickFlatConfigFromOptions(options) {
}

function createRuleTester(options) {
- const linter = new Linter({ configType: "flat" });
+ const languageOptions = deepMerge(
+ options.languageOptions ?? {
+ parser: options.parser,
+ parserOptions: options.parserOptions
+ },
+ ...toArray(options.configs).map((c) => c.languageOptions).filter((c) => c !== void 0)
+ );
+ const linter = new Linter({
+ configType: "flat",
+ cwd: isUsingTypeScriptParser(options) ? languageOptions?.parserOptions?.tsconfigRootDir : void 0
+ });
const defaultConfigs = toArray(options.configs);
{
const inlineConfig = pickFlatConfigFromOptions(options);
if (inlineConfig)
defaultConfigs.unshift(inlineConfig);
}
+ const defaultFilenames = {
+ js: "file.js",
+ ts: "file.ts",
+ jsx: "react.jsx",
+ tsx: "react.tsx",
+ ...options.defaultFilenames
+ };
function each(c) {
- const testcase = normalizeTestCase(c);
+ const testcase = normalizeTestCase(c, languageOptions, defaultFilenames);
const {
recursive = 10,
verifyAfterFix = true,
@@ -260,7 +304,7 @@ ${result.output}
if (cases.valid?.length) {
describe("valid", () => {
for (const c of cases.valid) {
- const _case = normalizeTestCase(c, "valid");
+ const _case = normalizeTestCase(c, languageOptions, defaultFilenames, "valid");
let run2 = it;
if (_case.only)
run2 = it.only;
@@ -276,7 +320,7 @@ ${result.output}
if (cases.invalid?.length) {
describe("invalid", () => {
for (const c of cases.invalid) {
- const _case = normalizeTestCase(c, "invalid");
+ const _case = normalizeTestCase(c, languageOptions, defaultFilenames, "invalid");
let run2 = it;
if (_case.only)
run2 = it.only;
@@ -312,4 +356,4 @@ function runClassic(ruleName, rule, cases, options) {
return tester.run(cases);
}

-export { createRuleTester, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
+export { createRuleTester, isUsingTypeScriptParser, isUsingTypeScriptTypings, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };
Loading

0 comments on commit e87cfe1

Please sign in to comment.