/** * Coverage + shape gate for the node icon registry (Task 1681). The coverage * case is the standing guard the task's Observability section names: it fails * the moment a colour label is added without an intentional Lucide glyph, so a * new node type can never silently ship as the fallback dot. */ import { describe, it, expect } from "vitest"; import { ADDITIONAL_BASE_LABELS, ALL_GRAPH_LABELS, FALLBACK_LABEL_COLOUR, GRAPH_LABEL_COLOURS, colourForLabel, iconForLabel, nodeImageDataUri, } from "../index.js"; import { assembleNodeLabelUniverse } from "./coverage-source.js"; describe("node-label universe coverage", () => { const universe = [...assembleNodeLabelUniverse()]; const styleable = universe.filter((l) => !ADDITIONAL_BASE_LABELS.has(l)); it("gives every standalone node label a colour and an icon", () => { const missing = styleable.filter( (l) => colourForLabel(l) === FALLBACK_LABEL_COLOUR || iconForLabel(l) === null, ); expect(missing).toEqual([]); }); it("gives no additional-base label a colour of its own", () => { const wrong = [...ADDITIONAL_BASE_LABELS].filter( (l) => colourForLabel(l) !== FALLBACK_LABEL_COLOUR, ); expect(wrong).toEqual([]); }); it("returns null for an unregistered label", () => { expect(iconForLabel("NoSuchLabel")).toBeNull(); }); it("every glyph is stroke-based inner SVG markup", () => { for (const label of ALL_GRAPH_LABELS) { const svg = iconForLabel(label); expect(svg, label).toMatch(/<(path|circle|rect|line|polyline)\b/); // inner markup only — no wrapping element expect(svg, label).not.toMatch(/ { it("builds a data URI carrying the label colour and its glyph", () => { const uri = nodeImageDataUri("Person"); expect(uri).not.toBeNull(); expect(uri!.startsWith("data:image/svg+xml,")).toBe(true); const decoded = decodeURIComponent(uri!.slice("data:image/svg+xml,".length)); // the disc carries the registry colour for the label expect(decoded).toContain(GRAPH_LABEL_COLOURS.Person); // the glyph is stroked white on top expect(decoded).toContain("stroke='#fff'"); // Person's Lucide glyph includes a circle (the head) expect(decoded).toContain(" { const person = nodeImageDataUri("Person")!; const property = nodeImageDataUri("Property")!; expect(decodeURIComponent(person)).toContain(GRAPH_LABEL_COLOURS.Person); expect(decodeURIComponent(property)).toContain(GRAPH_LABEL_COLOURS.Property); expect(person).not.toEqual(property); }); it("returns null for an unregistered label", () => { expect(nodeImageDataUri("NoSuchLabel")).toBeNull(); }); });