import { readdirSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { ESLint } from "eslint"; import { beforeAll } from "vitest"; // The one ESLint the lint-rule contract tests probe with (`*.contract.test.ts` that pin a selector in // eslint.config.js). Its first lint loads the whole config and every plugin: ~1.5 s warm, measured at // 8 s cold, past vitest's 5 s per test, so the first probe of a file timed out once. The // hook below pays that cost once per test file, under its own budget; importing this registers it. const FRONTEND = fileURLToPath(new URL("../../", import.meta.url)); // The probes lint TEXT under file names that do not exist (`__probe.tsx`, `x.ts`, a feature-folder // `Button.tsx`). The src config runs type-aware rules, whose project service refuses a // file no tsconfig includes, so those names are let into TypeScript's default project here — the // probe still runs the real config, typed rules included, rather than a copy with them switched off. const PROBE_FILES = [ "src/*/__*probe.ts", "src/*/__*probe.tsx", "src/components/ui/__*probe.tsx", "src/lib/api/__*probe.ts", "src/components/Button.tsx", "src/lib/x.ts", ]; export const eslint = new ESLint({ cwd: FRONTEND, overrideConfig: { files: ["src/**/*.{ts,tsx}"], languageOptions: { parserOptions: { projectService: { allowDefaultProject: PROBE_FILES, defaultProject: "tsconfig.json" }, tsconfigRootDir: FRONTEND, }, }, }, }); /** Every component file in ui/, by name — for a probe that pins which of them a rule exempts. */ export const uiFiles = (): string[] => readdirSync(new URL("../components/ui/", import.meta.url)) .filter((f) => f.endsWith(".tsx") && !f.includes(".test.")) .sort(); beforeAll(async () => { await eslint.lintText("", { filePath: "src/components/__probe.tsx" }); }, 60_000);