test(scripts): cover verify-format-coverage's sibling-guard vouch
From Copilot's thirteenth pass of #1962. This PR added `verify:dep-lockstep` to the vouch loop in `verify-format-coverage.mjs` without a test for it. The existing tests exercise `rootReachesScript` in isolation and the opposite direction (dep-lockstep vouching for format-coverage), so a typo in a sibling's name here would have left `test:scripts` green while that guard silently stopped being enforced — the same "a gate that stops gating" failure the vouch cycle exists to prevent, one level up. Three cases, reusing the fixture-repo approach: dropping either sibling from `validate` exits 1 naming that sibling, and with both wired no sibling is reported missing. The last asserts on the *reason* rather than the exit status, since the fixture has no client manifests to harvest globs from and so fails later for an unrelated reason. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
This commit is contained in:
parent
87c1e05420
commit
8a2035c4d1
1 changed files with 97 additions and 0 deletions
97
scripts/verify-format-coverage.main.test.mjs
Normal file
97
scripts/verify-format-coverage.main.test.mjs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// 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/);
|
||||
});
|
||||
Loading…
Reference in a new issue