mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* chore(tooling): migrate workspace to TypeScript 7 * fix(docker): stage plugin manifests before native web type checking * perf(guard): batch native parsing with bounded AST retention * fix(tooling): port main's AST tests to native TypeScript
93 lines
3.4 KiB
TypeScript
93 lines
3.4 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import { describe, expect, test, vi } from "vitest";
|
|
|
|
import {
|
|
loadScriptsArchitectureSources,
|
|
scriptsArchitectureErrors,
|
|
} from "../../../scripts/lib/guard/architecture.ts";
|
|
import { runGuardChecks } from "../../../scripts/lib/guard/core.ts";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
|
|
describe("scripts guard library", () => {
|
|
test("the live repository satisfies its layered dependency contract", async () => {
|
|
const sources = await loadScriptsArchitectureSources(repoRoot);
|
|
expect(scriptsArchitectureErrors(sources)).toEqual([]);
|
|
});
|
|
|
|
test("root scripts cannot bypass the public guard entrypoint", () => {
|
|
const sources = new Map([
|
|
["scripts/check.ts", 'import "./lib/guard/core.ts";'],
|
|
["scripts/lib/guard/core.ts", ""],
|
|
["scripts/guard.ts", 'import "./lib/guard/core.ts";'],
|
|
]);
|
|
expect(scriptsArchitectureErrors(sources)).toEqual(
|
|
expect.arrayContaining([
|
|
expect.stringContaining("must consume guard policy through scripts/guard.ts"),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test("guard internals cannot reverse-depend on the CLI or form cycles", () => {
|
|
const sources = new Map([
|
|
["scripts/guard.ts", 'import "./lib/guard/core.ts";'],
|
|
["scripts/lib/guard/core.ts", 'import "./architecture.ts";'],
|
|
["scripts/lib/guard/architecture.ts", 'import "./core.ts";\nimport "../../guard.ts";\nprocess.exitCode = 1;'],
|
|
]);
|
|
const errors = scriptsArchitectureErrors(sources);
|
|
expect(errors).toEqual(
|
|
expect.arrayContaining([
|
|
expect.stringContaining("must not depend on the guard CLI entrypoint"),
|
|
expect.stringContaining("contains CLI process control"),
|
|
expect.stringContaining("module cycle"),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test.each([
|
|
'import type { T } from "./lib/guard/core.ts";',
|
|
'type T = import("./lib/guard/core.ts").T;',
|
|
'void import("./lib/guard/core.ts");',
|
|
'const guard = require("./lib/guard/core.ts");',
|
|
'import guard = require("./lib/guard/core.ts");',
|
|
])("detects native AST import edges: %s", (source) => {
|
|
const errors = scriptsArchitectureErrors(new Map([
|
|
["scripts/check.ts", source],
|
|
["scripts/lib/guard/core.ts", "export interface T {}"],
|
|
]));
|
|
expect(errors).toContain("scripts/check.ts must consume guard policy through scripts/guard.ts, not scripts/lib/guard/core.ts");
|
|
});
|
|
|
|
test("the core runs every check and fails closed on exceptions", async () => {
|
|
const afterFailure = vi.fn(async () => true);
|
|
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
await expect(
|
|
runGuardChecks(
|
|
[
|
|
{
|
|
name: "broken",
|
|
run: async () => {
|
|
throw new Error("boom");
|
|
},
|
|
},
|
|
{ name: "after", run: afterFailure },
|
|
],
|
|
{ repoRoot },
|
|
),
|
|
).resolves.toBe(false);
|
|
expect(afterFailure).toHaveBeenCalledOnce();
|
|
consoleError.mockRestore();
|
|
});
|
|
|
|
test("the architecture check is registered in the public guard entrypoint", () => {
|
|
const names = execFileSync("pnpm", ["--silent", "guard", "--list-checks"], {
|
|
cwd: repoRoot,
|
|
encoding: "utf8",
|
|
}).trim().split("\n");
|
|
expect(names).toContain("scripts library architecture");
|
|
});
|
|
});
|