157 lines
6.3 KiB
JavaScript
157 lines
6.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readdir, readFile } from "node:fs/promises";
|
|
import { extname, join } from "node:path";
|
|
import { test } from "node:test";
|
|
|
|
const sourceRoot = new URL("../src/", import.meta.url);
|
|
|
|
async function sourceFiles(relativeDirectory) {
|
|
const directory = new URL(`${relativeDirectory}/`, sourceRoot);
|
|
const entries = await readdir(directory, {
|
|
recursive: true,
|
|
withFileTypes: true,
|
|
});
|
|
return entries
|
|
.filter((entry) => entry.isFile() && [".ts", ".tsx"].includes(extname(entry.name)))
|
|
.map((entry) => join(entry.parentPath, entry.name));
|
|
}
|
|
|
|
async function read(relativePath) {
|
|
return readFile(new URL(relativePath, sourceRoot), "utf8");
|
|
}
|
|
|
|
test("dependency direction keeps core and reusable components below workspaces", async () => {
|
|
const coreFiles = await sourceFiles("core");
|
|
const componentFiles = await sourceFiles("components");
|
|
|
|
for (const file of coreFiles) {
|
|
const source = await readFile(file, "utf8");
|
|
assert.doesNotMatch(
|
|
source,
|
|
/from\s+["'][^"']*(?:workspaces|\/App)["']/,
|
|
`${file} imports an application composition layer`,
|
|
);
|
|
assert.doesNotMatch(
|
|
source,
|
|
/@nodedc\/ui-(?:react|dom)/,
|
|
`${file} imports a visual adapter from the domain layer`,
|
|
);
|
|
}
|
|
|
|
for (const file of componentFiles) {
|
|
const source = await readFile(file, "utf8");
|
|
assert.doesNotMatch(
|
|
source,
|
|
/from\s+["'][^"']*(?:workspaces|\/App)["']/,
|
|
`${file} imports a workspace composition layer`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test("shared visual primitives come only from the Design Guideline packages", async () => {
|
|
const packageJson = JSON.parse(
|
|
await readFile(new URL("../package.json", import.meta.url), "utf8"),
|
|
);
|
|
for (const packageName of [
|
|
"@nodedc/tokens",
|
|
"@nodedc/ui-core",
|
|
"@nodedc/ui-react",
|
|
]) {
|
|
assert.equal(typeof packageJson.dependencies[packageName], "string");
|
|
}
|
|
|
|
const files = await sourceFiles(".");
|
|
for (const file of files) {
|
|
const source = await readFile(file, "utf8");
|
|
assert.doesNotMatch(source, /lucide-react/);
|
|
assert.doesNotMatch(source, /NODEDC_DESIGN_GUIDELINE\/(?:apps|src)\//);
|
|
}
|
|
});
|
|
|
|
test("laboratory UI is a bounded feature slice, not a central workspace branch", async () => {
|
|
const workspaceHub = await read("workspaces/Workspaces.tsx");
|
|
const laboratory = await read(
|
|
"workspaces/laboratory/LaboratoryArchiveWorkspace.tsx",
|
|
);
|
|
const workspaceCss = await read("styles/workspaces.css");
|
|
const laboratoryCss = await read("styles/laboratory.css");
|
|
const laboratoryReportingCss = await read("styles/laboratory-reporting.css");
|
|
const e30Review = await read("workspaces/E30ReviewWorkspace.tsx");
|
|
const e30HumanReview = await read(
|
|
"workspaces/E30HumanReviewPanel.tsx",
|
|
);
|
|
const e30HumanReviewCss = await read("styles/e30-human-review.css");
|
|
|
|
assert.doesNotMatch(
|
|
workspaceHub,
|
|
/fetchE(?:29|30)|LaboratoryWorkTemplate|function\s+E(?:29|30)LaboratoryResult/,
|
|
);
|
|
assert.match(
|
|
workspaceHub,
|
|
/<LaboratoryArchiveWorkspace[\s\S]*SpatialView=\{SpatialWorkspace\}/,
|
|
);
|
|
assert.match(laboratory, /export function LaboratoryArchiveWorkspace/);
|
|
assert.match(laboratory, /type LaboratoryWorkspaceProps = WorkspaceRendererProps/);
|
|
assert.doesNotMatch(workspaceCss, /\.(?:lab-|laboratory-|e30-)/);
|
|
assert.match(laboratoryCss, /\.laboratory-work-template/);
|
|
assert.match(laboratoryCss, /\.e30-review-workspace/);
|
|
assert.match(laboratoryReportingCss, /\.laboratory-summary__brief/);
|
|
assert.match(laboratoryReportingCss, /\.laboratory-result-conclusion/);
|
|
assert.doesNotMatch(laboratory, /E30HumanReviewPanel/);
|
|
assert.match(e30Review, /<E30HumanReviewPanel/);
|
|
assert.doesNotMatch(e30Review, /E30EngineeringAuditPanel/);
|
|
assert.match(e30HumanReview, /from "@nodedc\/ui-react"/);
|
|
assert.doesNotMatch(laboratoryCss, /\.e30-human-review/);
|
|
assert.match(e30HumanReviewCss, /\.e30-human-review/);
|
|
});
|
|
|
|
test("Observatory owns a bounded explicit-open lifecycle around the shared recorded viewer", async () => {
|
|
const workspaceHub = await read("workspaces/Workspaces.tsx");
|
|
const observatory = await read("workspaces/observatory/ObservatoryWorkspace.tsx");
|
|
const observatoryCore = await read("core/observatory/catalog.ts");
|
|
const recordedRun = await read("core/observatory/recordedRun.ts");
|
|
const sharedReplay = await read(
|
|
"components/laboratory/CanonicalResultRerunReplay.tsx",
|
|
);
|
|
const workspaceCss = await read("styles/workspaces.css");
|
|
const observatoryCss = await read("styles/observatory.css");
|
|
|
|
assert.match(
|
|
workspaceHub,
|
|
/case "observatory":[\s\S]*<ObservatoryWorkspace definition=\{props\.definition\} \/>/,
|
|
);
|
|
assert.match(observatory, /export function ObservatoryWorkspace/);
|
|
assert.match(observatory, /useObservatoryCatalog/);
|
|
assert.match(observatory, /data-observatory-authority="observation-only"/);
|
|
assert.match(
|
|
observatory,
|
|
/data-observatory-viewer={replay\.kind === "ready" \|\| replay\.kind === "composition" \? "attached" : "detached"}/,
|
|
);
|
|
assert.doesNotMatch(
|
|
`${observatory}\n${observatoryCore}`,
|
|
/(?:core|workspaces)\/laboratory|\/api\/v1\/laboratory|RerunViewport|ObservationSessionSelect/,
|
|
);
|
|
assert.match(observatory, /replay\.kind === "ready"[\s\S]*<CanonicalVegetationRerunReplay/);
|
|
assert.match(observatory, /closeReplay\(\);[\s\S]*setSelectedSessionId/);
|
|
assert.doesNotMatch(
|
|
observatory,
|
|
/replayObservationSession|deleteObservationSession|useObservationSessions|useAdvancedLaboratoryCatalog/,
|
|
);
|
|
assert.match(recordedRun, /fetchVegetationShadowResultMetadata/);
|
|
assert.doesNotMatch(
|
|
recordedRun,
|
|
/advanced-index|resolveObservationSessionReplay|resolveCanonicalLabReplay|RerunViewport/,
|
|
);
|
|
assert.equal(sharedReplay.match(/<RerunViewport\b/g)?.length, 1);
|
|
assert.match(sharedReplay, /recordedSessionRerunProfile/);
|
|
assert.match(sharedReplay, /useState<0 \| 1>\(hasTgs \? 1 : 0\)/);
|
|
assert.match(sharedReplay, /hasTgs \? 0\.000001 : 0/);
|
|
for (const adapter of ["CanonicalVegetationRerunReplay", "PortableResultReplay"]) {
|
|
const source = await read(`components/laboratory/${adapter}.tsx`);
|
|
assert.match(source, /<CanonicalResultRerunReplay/);
|
|
assert.doesNotMatch(source, /<RerunViewport|<video|setInterval|Canvas|THREE\./);
|
|
}
|
|
assert.doesNotMatch(workspaceCss, /\.observatory-/);
|
|
assert.match(observatoryCss, /\.observatory-workspace/);
|
|
});
|