// Regression tests for `verify-format-coverage`'s sibling-guard vouch (Copilot, // #1962). The three root guards form a cycle so that dropping any one from // `validate` is caught by another — but the vouch branch itself had no test, so // a typo in a sibling's name would leave `test:scripts` green while that guard // silently stopped being enforced. That is the same "a gate that stops gating" // failure the cycle exists to prevent, one level up. // // The vouch runs before any file enumeration, so the fixture needs only a // `package.json` and the script. Run via `npm run test:scripts`. import { test } from "node:test"; import assert from "node:assert/strict"; import { execFileSync, spawnSync } from "node:child_process"; import { cpSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptsDir = path.dirname(fileURLToPath(import.meta.url)); /** A `validate` chain running each named guard, plus the always-present self. */ function scriptsRunning(guards) { const scripts = { validate: ["verify:format-coverage", ...guards] .map((g) => `npm run ${g}`) .join(" && "), "verify:format-coverage": "node scripts/verify-format-coverage.mjs", }; for (const g of guards) scripts[g] = `node scripts/${g.slice(7)}.mjs`; return scripts; } /** * Run `verify-format-coverage` in a throwaway repo whose root `validate` runs * exactly `guards`. realpath'd because the script only executes when * `import.meta.url` matches `process.argv[1]`, and macOS `tmpdir()` is a * symlink — see the note in `verify-dep-lockstep.main.test.mjs`. */ function runWithGuards(guards) { const dir = realpathSync(mkdtempSync(path.join(tmpdir(), "format-cov-"))); try { writeFileSync( path.join(dir, "package.json"), JSON.stringify( { name: "fixture", scripts: scriptsRunning(guards) }, null, 2, ), ); mkdirSync(path.join(dir, "scripts", "lib"), { recursive: true }); for (const rel of [ "verify-format-coverage.mjs", path.join("lib", "npm-scripts.mjs"), ]) cpSync(path.join(scriptsDir, rel), path.join(dir, "scripts", rel)); execFileSync("git", ["init", "-q"], { cwd: dir }); execFileSync("git", ["add", "-A"], { cwd: dir }); const r = spawnSync( process.execPath, [path.join(dir, "scripts", "verify-format-coverage.mjs")], { cwd: dir, encoding: "utf8" }, ); return { status: r.status, out: `${r.stdout}${r.stderr}` }; } finally { rmSync(dir, { recursive: true, force: true }); } } const BOTH_SIBLINGS = ["verify:typecheck-coverage", "verify:dep-lockstep"]; test("vouch: fails when `verify:dep-lockstep` is dropped from validate", () => { const { status, out } = runWithGuards(["verify:typecheck-coverage"]); assert.equal(status, 1, out); assert.match(out, /no longer runs `verify:dep-lockstep`/); }); test("vouch: fails when `verify:typecheck-coverage` is dropped from validate", () => { const { status, out } = runWithGuards(["verify:dep-lockstep"]); assert.equal(status, 1, out); assert.match(out, /no longer runs `verify:typecheck-coverage`/); }); test("vouch: passes when both siblings are still wired", () => { // The run still fails afterwards — the fixture has no client manifests to // harvest globs from — so assert on the *reason*, not the exit status: no // sibling may be reported missing. const { out } = runWithGuards(BOTH_SIBLINGS); assert.doesNotMatch(out, /no longer runs/); });