testLintConfigAndJsPlugins
Lint: a lint.config definition sets rules, and the packages it imports are JS plugins.
import { setUp } from "#codebase/tcmts/cli/test/e2e/lint"; import assert from "node:assert/strict"; export const testLintConfigAndJsPlugins = () => { const { run, tcm, write } = setUp(); tcm("add", "ui.tsx"); write("cfg.ts", `// tcm: namespace lint\nimport noOnlyTests from "eslint-plugin-no-only-tests";\n\nexport const config = {\n jsPlugins: [noOnlyTests],\n rules: { "no-debugger": "error", "no-only-tests/no-only-tests": "error" },\n};\n`); assert.match(tcm("add", "cfg.ts"), /eslint-plugin-no-only-tests has no types .*typed as any/, "an untyped plugin is fine, with a warning"); // the configuration changed, so everything is linted against it const r = run("lint"); assert.equal(r.status, 1); assert.match(r.out, /ui\.half #\w+\n {2}2:3 {2}error {2}`debugger` statement is not allowed/); assert.match(r.out, /1 error\(s\), 1 warning\(s\) in 3 definition\(s\)/); // an error stops a save; the plugin's rule works like a built-in one write("only.ts", `// tcm: namespace ui\nexport const testOnly = () => {\n const describe = { only: (_name: string, fn: () => void) => fn() };\n describe.only("x", () => {});\n};\n`); const blocked = run("add", "only.ts"); assert.notEqual(blocked.status, 0); assert.match(blocked.out, /4:12 {2}error {2}describe\.only not permitted no-only-tests\(no-only-tests\)/); assert.match(blocked.out, /only\.ts has lint errors; nothing was saved/); assert.match(tcm("ls", "ui"), /^(?![\s\S]*testOnly)/, "nothing was saved"); }