Files
servers/scripts/lib/workspaces.test.mjs
cliffhallandClaude Opus 5.5 a9cf19e162 feat: coverage and lockstep guards, root validate, per-package CI legs
- verify:format-coverage and verify:typecheck-coverage ported from the
  Inspector, with the Inspector's tsc-program and resolve-node-bin libs
  (+ tests), adapted to npm workspaces via a new lib/workspaces.mjs that
  reads the root workspaces patterns from disk and checks the root
  validate still runs `npm run validate --workspaces`.
- verify:dep-lockstep: every shared toolchain devDependency (typescript,
  vitest, @vitest/coverage-v8, prettier, @types/node) is declared with one
  range everywhere, or once at the root.
- Root validate = validate:guards (root format/lint, the guards,
  test:scripts) + npm run validate --workspaces.
- typescript.yml: each matrix leg runs only its own package's validate;
  the root-guards job runs validate:guards.
- Removes #4863's temporary verify:format-coverage wiring allowance, and
  fixes the four root-lint findings in the skills scripts.

Refs #4864

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-09-29 00:10:03 -04:00

126 lines
4.6 KiB
JavaScript

// Tests for `workspaces.mjs` (#4864): which workspaces the root gate covers,
// and whether the root `validate` still runs each one. One case per rule.
// Run via `npm run test:scripts`.
import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { rootRunsWorkspaceValidate, workspaceDirs } from "./workspaces.mjs";
const runs = (validate, dir = "src/a", extra = {}) =>
rootRunsWorkspaceValidate({ validate, ...extra }, dir);
test("rootRunsWorkspaceValidate: the aggregate form covers every workspace", () => {
assert.ok(runs("npm run validate --workspaces"));
assert.ok(runs("npm run validate -ws", "src/b"));
assert.ok(runs("npm run-script validate --workspaces"));
assert.ok(runs("npm run guards && npm run validate --workspaces"));
});
test("rootRunsWorkspaceValidate: the per-workspace forms cover only their own dir", () => {
for (const cmd of [
"npm run validate --workspace src/a",
"npm run validate --workspace=src/a",
"npm run validate -w src/a",
"npm run validate -w ./src/a/",
"cd src/a && npm run validate",
"cd ./src/a && npm run validate",
"npm --prefix src/a run validate",
]) {
assert.ok(runs(cmd), cmd);
assert.ok(!runs(cmd, "src/b"), `${cmd} must not vouch for src/b`);
}
});
test("rootRunsWorkspaceValidate: a prefix-sibling dir does not count", () => {
assert.ok(!runs("npm run validate -w src/a-next"));
assert.ok(!runs("cd src/a-next && npm run validate"));
});
test("rootRunsWorkspaceValidate: --if-present is refused (it skips a workspace with no validate)", () => {
assert.ok(!runs("npm run validate --workspaces --if-present"));
assert.ok(!runs("npm run validate --if-present -w src/a"));
});
test("rootRunsWorkspaceValidate: another script name is not validate", () => {
assert.ok(!runs("npm run validate:fast --workspaces"));
assert.ok(!runs("npm run check --workspaces"));
});
test("rootRunsWorkspaceValidate: a mention or a masked failure is not an invocation", () => {
assert.ok(!runs("echo npm run validate --workspaces"));
assert.ok(!runs("npm run validate --workspaces || true"));
assert.ok(!runs("true || npm run validate --workspaces"));
});
test("rootRunsWorkspaceValidate: follows delegation and lifecycle hooks", () => {
assert.ok(
runs("npm run validate:ts", "src/a", {
"validate:ts": "npm run validate --workspaces",
}),
);
assert.ok(
runs("npm run guards", "src/a", {
postvalidate: "npm run validate -w src/a",
}),
);
});
test("rootRunsWorkspaceValidate: a cd holds only within its own script body", () => {
// `cd` then a delegated script: npm starts the delegate from the root again,
// so the delegate's bare `npm run validate` is the ROOT's validate.
assert.ok(
!runs("cd src/a && npm run other", "src/a", {
other: "npm run validate",
}),
);
// Workspace flags are resolved from the workspace root, so under a `cd`
// they are not the root's aggregate.
assert.ok(!runs("cd src/b && npm run validate -w src/a"));
});
test("rootRunsWorkspaceValidate: nothing reachable, nothing run", () => {
assert.ok(!rootRunsWorkspaceValidate({}, "src/a"));
assert.ok(!rootRunsWorkspaceValidate(undefined, "src/a"));
});
function fixture(layout) {
const dir = mkdtempSync(path.join(tmpdir(), "workspaces-"));
for (const [rel, withManifest] of Object.entries(layout)) {
mkdirSync(path.join(dir, rel), { recursive: true });
if (withManifest) writeFileSync(path.join(dir, rel, "package.json"), "{}");
}
return dir;
}
test("workspaceDirs: expands a trailing /* and a plain dir, flags missing manifests", () => {
const dir = fixture({
"src/a": true,
"src/b": false,
"src/node_modules": false,
tools: true,
});
try {
assert.deepEqual(workspaceDirs(dir, ["src/*", "tools", "./missing"]), [
{ dir: "src/a", hasManifest: true },
{ dir: "src/b", hasManifest: false },
{ dir: "tools", hasManifest: true },
]);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test("workspaceDirs: a pattern it cannot read fails loudly instead of matching nothing", () => {
assert.throws(() => workspaceDirs("/nowhere", ["src/**"]), /unsupported/);
assert.throws(
() => workspaceDirs("/nowhere", ["packages/*/x"]),
/unsupported/,
);
assert.throws(() => workspaceDirs("/nowhere", [{}]), /unsupported/);
assert.throws(() => workspaceDirs("/nowhere", []), /no `workspaces`/);
assert.throws(() => workspaceDirs("/nowhere", undefined), /no `workspaces`/);
});