mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
f442a083fb
Fix tester script. It was broken by changes last week.
222 lines
6.4 KiB
TypeScript
222 lines
6.4 KiB
TypeScript
/*
|
|
* A script for running a test case with both ESLint and Oxlint.
|
|
* Purpose is to be able to "spot the difference" between the two.
|
|
*/
|
|
|
|
// oxlint-disable no-console
|
|
|
|
// Use the conformance testing version of `RuleTester`,
|
|
// which modifies test cases before they run
|
|
import { RuleTester as OxlintRuleTester } from "./src/rule_tester.ts";
|
|
import { setCurrentGroup } from "./src/capture.ts";
|
|
// // @ts-expect-error - internal module of ESLint with no types
|
|
// import { RuleTester as ESLintRuleTester } from "./submodules/eslint/lib/rule-tester/index.js";
|
|
import { RuleTester as ESLintRuleTester } from "eslint";
|
|
// @ts-expect-error - internal module of ESLint with no types
|
|
import { builtinRules } from "./submodules/eslint/lib/unsupported-api.js";
|
|
import tsEslintParser from "@typescript-eslint/parser";
|
|
|
|
import type { Rule } from "#oxlint/plugins";
|
|
import type { ValidTestCase, InvalidTestCase } from "./src/rule_tester.ts";
|
|
|
|
type ValidTestCaseWithoutCode = Omit<ValidTestCase, "code"> & { code?: string };
|
|
type InvalidTestCaseWithoutCode = Omit<InvalidTestCase, "code"> & { code?: string };
|
|
type TestCaseWithoutCode = ValidTestCaseWithoutCode | InvalidTestCaseWithoutCode;
|
|
|
|
// Reset `describe` + `it` to simple pass-through functions.
|
|
// Importing from `rule_tester.ts` sets up `RuleTester` to use `capture.ts`'s `describe` / `it`,
|
|
// which we don't want for manual testing.
|
|
// `OxlintRuleTesterOriginal` is the original `RuleTester` exported by `oxlint`.
|
|
const OxlintRuleTesterOriginal = Object.getPrototypeOf(OxlintRuleTester);
|
|
|
|
const simpleDescribe = (name: string, fn: () => void) => fn();
|
|
const simpleIt = (name: string, fn: () => void) => fn();
|
|
|
|
OxlintRuleTesterOriginal.describe = simpleDescribe;
|
|
OxlintRuleTesterOriginal.it = simpleIt;
|
|
|
|
// Set global `describe` and `it` for ESLint's `RuleTester`
|
|
(globalThis as any).describe = simpleDescribe;
|
|
(globalThis as any).it = simpleIt;
|
|
|
|
// Set a dummy group to set CWD in `RuleTester` to current directory
|
|
setCurrentGroup({ testFilesDirPath: import.meta.dirname } as any);
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
|
(Obviously these instructions are aimed at AI, hence the rather rude and demanding tone.
|
|
Sorry humans! In fact, sorry to you too AI.)
|
|
|
|
# HOW TO USE THIS SCRIPT
|
|
|
|
DO NOT edit this file except the section between the bottom of this comment and the start of the next comment
|
|
"Run test case with both ESLint and Oxlint".
|
|
|
|
## 1. Select a test
|
|
|
|
Select a failing test case to investigate from `snapshot.md`.
|
|
|
|
## 2. Copy details
|
|
|
|
Copy details from `snapshot.md` for the case into the variables in this script, below this comment.
|
|
|
|
e.g.:
|
|
|
|
Details of test case from `snapshot.md`:
|
|
|
|
------------- Snapshot extract begins -------------
|
|
|
|
#### block-scoped-var > invalid
|
|
|
|
```js
|
|
for (var a = 0;;) {} a;
|
|
```
|
|
|
|
```json
|
|
{
|
|
"errors": [
|
|
{
|
|
"messageId": "outOfScope",
|
|
"data": {
|
|
"name": "a",
|
|
"definitionLine": 1,
|
|
"definitionColumn": 10
|
|
},
|
|
"line": 1,
|
|
"column": 22
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
------------- Snapshot extract ends -------------
|
|
|
|
Fill in the variables below as follows:
|
|
|
|
------------- Script setup begins -------------
|
|
|
|
const ruleName = "block-scoped-var";
|
|
|
|
const code = `for (var a = 0;;) {} a;`;
|
|
|
|
const isInvalid = true;
|
|
|
|
const testCase: TestCaseWithoutCode = {
|
|
"errors": [
|
|
{
|
|
"messageId": "outOfScope",
|
|
"data": {
|
|
"name": "a",
|
|
"definitionLine": 1,
|
|
"definitionColumn": 10
|
|
},
|
|
"line": 1,
|
|
"column": 22
|
|
}
|
|
]
|
|
};
|
|
|
|
------------- Script setup ends -------------
|
|
|
|
## 3. Run the test
|
|
|
|
Run this script with `node conformance/tester.ts`.
|
|
|
|
Observe the output. ESLint should not produce any errors, but Oxlint will.
|
|
|
|
## 4. Discover the cause
|
|
|
|
Add `console.log` statements to the rule's code in `submodules/eslint/lib/rules`.
|
|
|
|
Run this script again. Find out what is happening differently between ESLint and Oxlint.
|
|
|
|
## 5. Clean up
|
|
|
|
`submodules/eslint` is a git repo.
|
|
Use git to throw away the changes you made to the rule's code (`console.log`).
|
|
Leave the eslint repo as it was before you started, ready to investigate another case.
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
const ruleName = "block-scoped-var";
|
|
const rule = builtinRules.get(ruleName) as unknown as Rule;
|
|
|
|
// import rule from "./submodules/stylistic/packages/eslint-plugin/rules/jsx-props-no-multi-spaces/jsx-props-no-multi-spaces.ts";
|
|
|
|
const code = `for (var a = 0;;) {} a;`;
|
|
|
|
const isInvalid = true;
|
|
|
|
const testCase: TestCaseWithoutCode = {
|
|
errors: [
|
|
{
|
|
messageId: "outOfScope",
|
|
data: {
|
|
name: "a",
|
|
definitionLine: 1,
|
|
definitionColumn: 10,
|
|
},
|
|
line: 1,
|
|
column: 22,
|
|
},
|
|
],
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Run test case with both ESLint and Oxlint
|
|
// -----------------------------------------------------------------------------
|
|
|
|
runBoth(rule, isInvalid, code, testCase);
|
|
|
|
function runBoth(rule: Rule, isInvalid: boolean, code: string, testCase: TestCaseWithoutCode) {
|
|
testCase = { code, ...testCase };
|
|
|
|
// Run case with ESLint
|
|
console.log("--------------------");
|
|
console.log("ESLint");
|
|
console.log("--------------------");
|
|
|
|
const eslintValid: ValidTestCase[] = [],
|
|
eslintInvalid: InvalidTestCase[] = [];
|
|
if (isInvalid) {
|
|
eslintInvalid.push(testCase as InvalidTestCase);
|
|
} else {
|
|
eslintValid.push(testCase as ValidTestCase);
|
|
}
|
|
|
|
runOne(ESLintRuleTester, rule, eslintValid, eslintInvalid);
|
|
|
|
// Run case with Oxlint
|
|
console.log("\n--------------------");
|
|
console.log("Oxlint");
|
|
console.log("--------------------");
|
|
|
|
if (testCase?.languageOptions?.parser === tsEslintParser) {
|
|
testCase.languageOptions = { parserOptions: {}, ...testCase.languageOptions };
|
|
delete testCase.languageOptions.parser;
|
|
testCase.languageOptions.parserOptions!.lang =
|
|
testCase.languageOptions.parserOptions!.ecmaFeatures?.jsx === true ? "tsx" : "ts";
|
|
}
|
|
|
|
const oxlintValid: ValidTestCase[] = [],
|
|
oxlintInvalid: InvalidTestCase[] = [];
|
|
if (isInvalid) {
|
|
oxlintInvalid.push(testCase as InvalidTestCase);
|
|
} else {
|
|
oxlintValid.push(testCase as ValidTestCase);
|
|
}
|
|
|
|
runOne(OxlintRuleTester, rule, oxlintValid, oxlintInvalid);
|
|
}
|
|
|
|
function runOne(RuleTester: any, rule: Rule, valid: ValidTestCase[], invalid: InvalidTestCase[]) {
|
|
try {
|
|
const tester = new RuleTester();
|
|
tester.run("my-rule", rule, { valid, invalid });
|
|
console.log("No errors");
|
|
} catch (err) {
|
|
console.log("ERROR:");
|
|
console.log(err);
|
|
}
|
|
}
|