import { readFileSync } from "node:fs"; const page = readFileSync(new URL("../src/features/dataflow/DataflowPage.tsx", import.meta.url), "utf8"); const canvas = readFileSync(new URL("../src/features/dataflow/DataflowCanvas.tsx", import.meta.url), "utf8"); const interactions = readFileSync(new URL("../src/features/dataflow/graphInteractions.ts", import.meta.url), "utf8"); const css = readFileSync(new URL("../src/styles/dataflow.css", import.meta.url), "utf8"); const moduleEntry = readFileSync(new URL("../src/module.ts", import.meta.url), "utf8"); const checks = [ [page.includes(" node.id === selectedNodeId)"), "selected node preservation across SQL roundtrips" ], [page.includes("useUnsavedDraftGuard"), "unsaved-change guard"], [canvas.includes("application/x-govoplan-dataflow-node"), "palette drop handling"], [canvas.includes("isValidConnection"), "edge validation"], [canvas.includes("connectionRadius={32}"), "visible connection drop radius"], [canvas.includes("initialWidth: 180"), "known initial node width"], [canvas.includes('change.type !== "dimensions"'), "measurement-only change filtering"], [canvas.includes("onReconnect={onReconnect}"), "edge reconnection"], [canvas.includes("onReconnectEnd="), "edge deletion on dropped reconnection"], [canvas.includes("selectedEdgeId"), "persistent edge selection"], [ canvas.includes("newGraphEdgeId()") && interactions.includes("return `edge-${crypto.randomUUID()}`"), "bounded opaque edge identifiers" ], [ canvas.includes("closestProximityConnection") && interactions.includes("definitionConnectionError"), "validated proximity connection" ], [css.includes(".dataflow-edge-proximity"), "proximity connection indicator"], [ moduleEntry.indexOf("@xyflow/react/dist/style.css") < moduleEntry.indexOf("./styles/dataflow.css"), "XyFlow base styles before GovOPlaN overrides" ], [css.includes("height: calc(100vh - 115px)"), "full-height workspace"], [css.includes(".dataflow-preview-table-wrap"), "bounded preview scrolling"], [ /\.dataflow-palette-items\s*\{[^}]*grid-auto-rows:\s*max-content;[^}]*overflow-y:\s*auto;/s.test(css), "bounded palette scrolling" ], [ /\.dataflow-inspector-fields\s*\{[^}]*grid-auto-rows:\s*max-content;[^}]*overflow-y:\s*auto;/s.test(css), "bounded inspector scrolling" ] ]; const missing = checks.filter(([present]) => !present).map(([, label]) => label); if (missing.length) { throw new Error(`Dataflow UI structure is missing: ${missing.join(", ")}`); } console.log("Dataflow page structure checks passed.");