Files
fusion/scripts/__tests__/check-workspace-package-graph.test.mjs
gsxdsm f2c729bf77 FN-8994: add workspace package graph validation
Prevent cold workspace installs from failing on missing or unglobbed local packages.

- Validate workspace-protocol dependencies and overrides against glob-covered packages.
- Add static-gate coverage and regression tests for missing plugin packages.
- Document the workspace package graph check.

Files changed:
 docs/testing.md                                    |   4 +-
 package.json                                       |   9 +-
 scripts/__tests__/check-workspace-package-graph.test.mjs | 103 +++++++++++++++
 scripts/check-workspace-package-graph.mjs          | 138 +++++++++++++++++++++
 4 files changed, 249 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-8994

Fusion-Task-Lineage: 17dbe062-79aa-4417-ae38-43df881e9fa4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 14:56:14 -07:00

104 lines
4.6 KiB
JavaScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
matchesWorkspaceGlob,
readWorkspacePackageGraph,
scanWorkspacePackageGraph,
validateWorkspacePackageGraph,
} from "../check-workspace-package-graph.mjs";
import { readStaticGateChecks } from "../run-static-gate-checks.mjs";
const GLOBS = ["packages/*", "plugins/fusion-plugin-*"];
const VALID_PLUGIN = {
filePath: "plugins/fusion-plugin-claude-runtime/package.json",
manifest: { name: "@fusion-plugin-examples/claude-runtime" },
};
function validate(manifests, workspaceGlobs = GLOBS) {
return validateWorkspacePackageGraph({ manifests, workspaceGlobs });
}
describe("check-workspace-package-graph", () => {
it("matches package globs without relying on node:path.matchesGlob", () => {
assert.equal(matchesWorkspaceGlob("packages/dashboard", "packages/*"), true);
assert.equal(matchesWorkspaceGlob("packages/dashboard/nested", "packages/*"), false);
assert.equal(matchesWorkspaceGlob("plugins/fusion-plugin-claude-runtime", "plugins/fusion-plugin-*"), true);
assert.equal(matchesWorkspaceGlob("plugins/examples/claude-runtime", "plugins/examples/*"), true);
});
it("passes against the live repository", () => {
assert.deepEqual(scanWorkspacePackageGraph(), []);
});
it("includes the root importer without treating it as an unglobbed package", () => {
const { manifests } = readWorkspacePackageGraph();
assert.equal(manifests.some(({ filePath, isRoot }) => filePath === "package.json" && isRoot), true);
assert.deepEqual(validate([{ filePath: "package.json", isRoot: true, manifest: { name: "fusion-workspace" } }]), []);
});
it("rejects dangling workspace dependencies from the root importer", () => {
const violations = validate([{
filePath: "package.json",
isRoot: true,
manifest: { dependencies: { "@fusion-plugin-examples/missing": "workspace:*" } },
}]);
assert.equal(violations.length, 1);
assert.match(violations[0], /package\.json/);
assert.match(violations[0], /@fusion-plugin-examples\/missing/);
});
it("rejects dangling workspace-protocol overrides", () => {
const violations = validate([{
filePath: "package.json",
isRoot: true,
manifest: { pnpm: { overrides: { "@fusion-plugin-examples/missing": "workspace:*" } } },
}]);
assert.equal(violations.length, 1);
assert.match(violations[0], /overrides\.@fusion-plugin-examples\/missing/);
});
it("reconstructs the missing claude-runtime package symptom", () => {
const violations = validate([{
filePath: "packages/dashboard/package.json",
manifest: { dependencies: { "@fusion-plugin-examples/claude-runtime": "workspace:*" } },
}]);
assert.deepEqual(violations.length, 1);
assert.match(violations[0], /packages\/dashboard\/package\.json/);
assert.match(violations[0], /@fusion-plugin-examples\/claude-runtime/);
});
it("checks every dependency block and accepts published or non-workspace dependencies", () => {
for (const blockName of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
const violations = validate([{ filePath: "packages/dashboard/package.json", manifest: { [blockName]: { missing: "workspace:*" } } }]);
assert.equal(violations.length, 1, `${blockName} must be checked`);
}
assert.deepEqual(validate([
VALID_PLUGIN,
{ filePath: "packages/dashboard/package.json", manifest: { dependencies: { "@fusion-plugin-examples/claude-runtime": "workspace:*", external: "^1.2.3" } } },
{ filePath: "packages/empty/package.json", manifest: {} },
{ filePath: "packages/unnamed/package.json", manifest: { name: "" } },
]), []);
});
it("reports every dangling declaration across manifests", () => {
const violations = validate([
{ filePath: "packages/one/package.json", manifest: { dependencies: { one: "workspace:*" } } },
{ filePath: "packages/two/package.json", manifest: { optionalDependencies: { two: "workspace:*" } } },
]);
assert.equal(violations.length, 2);
});
it("rejects package directories outside workspace globs", () => {
const violations = validate([
{ filePath: "plugins/unlisted/package.json", manifest: { name: "unlisted" } },
], ["packages/*"]);
assert.equal(violations.length, 1);
assert.match(violations[0], /plugins\/unlisted\/package\.json/);
assert.match(violations[0], /not covered/);
});
it("is included in the blocking static gate inventory", () => {
assert.equal(readStaticGateChecks().includes("scripts/check-workspace-package-graph.mjs"), true);
});
});