import assert from "node:assert/strict"; import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { scanQueryErrorRendering, scanSource } from "./check-query-error-rendering.mjs"; const rulesFor = (source) => scanSource(source, "ui/src/x.tsx").map((finding) => finding.rule); test("flags raw error renders", () => { assert.deepEqual(rulesFor("
{error.message}
"), ["raw-error-message"]); assert.deepEqual(rulesFor("{query.error?.message}
"), ["raw-error-message"]); assert.deepEqual(rulesFor("{saveError.message}
"), ["raw-error-message"]); assert.deepEqual(rulesFor("{(error as Error).message}
"), ["cast-error-message"]); }); test("flags isError render branches but not optional chaining or types", () => { assert.deepEqual(rulesFor("{isError ?{error.message}
;\n"); writeFileSync(join(root, "pages", "Legacy.tsx"), "export const B = () =>{error.message}
;\n"); const findings = scanQueryErrorRendering({ root, allowlist: new Set(), enforcedFiles: new Set() }); assert.equal(findings.length, 2); assert.ok(findings.every((finding) => finding.enforced === false)); const migrated = findings.find((finding) => finding.path.endsWith("Migrated.tsx")); const enforced = scanQueryErrorRendering({ root, allowlist: new Set(), enforcedFiles: new Set([migrated.path]) }); assert.deepEqual( enforced.map((finding) => [finding.path.endsWith("Migrated.tsx"), finding.enforced]).sort(), [[false, false], [true, true]], ); } finally { rmSync(root, { recursive: true, force: true }); } }); test("scans a tree, skips tests, and honors the allowlist", () => { const root = mkdtempSync(join(tmpdir(), "query-error-rendering-")); try { mkdirSync(join(root, "pages")); writeFileSync(join(root, "pages", "Page.tsx"), "export const A = () =>{error.message}
;\n"); writeFileSync(join(root, "pages", "Page.test.tsx"), "expect({error.message}
);\n"); const findings = scanQueryErrorRendering({ root, allowlist: new Set(), enforcedFiles: new Set() }); assert.equal(findings.length, 1); assert.equal(findings[0].rule, "raw-error-message"); assert.equal(findings[0].line, 1); const allowed = scanQueryErrorRendering({ root, allowlist: new Set([`${findings[0].path}:raw-error-message`]), enforcedFiles: new Set(), }); assert.equal(allowed.length, 0); } finally { rmSync(root, { recursive: true, force: true }); } });