1454c7792a
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
3.3 KiB
TypeScript
85 lines
3.3 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { parseFlowchart } from "../src/mermaidFlowchartDiff";
|
|
|
|
describe("parseFlowchart", () => {
|
|
it("captures the header and node declarations with labels + shapes", () => {
|
|
const g = parseFlowchart("flowchart LR\n A[Start] --> B(Middle)\n B --> C{End}");
|
|
expect(g.header).toBe("flowchart LR");
|
|
expect(g.nodes.get("A")).toMatchObject({ id: "A", label: "Start", open: "[", close: "]" });
|
|
expect(g.nodes.get("B")).toMatchObject({ id: "B", label: "Middle", open: "(", close: ")" });
|
|
expect(g.nodes.get("C")).toMatchObject({ id: "C", label: "End", open: "{", close: "}" });
|
|
});
|
|
|
|
it("captures edges in declaration order with from/to and index", () => {
|
|
const g = parseFlowchart("graph TD\n A-->B\n B-->C");
|
|
expect(g.edges.map((e) => [e.from, e.to, e.index])).toEqual([
|
|
["A", "B", 0],
|
|
["B", "C", 1],
|
|
]);
|
|
});
|
|
|
|
it("records a node referenced only in an edge (no explicit declaration)", () => {
|
|
const g = parseFlowchart("flowchart LR\n A-->B");
|
|
expect(g.nodes.has("A")).toBe(true);
|
|
expect(g.nodes.has("B")).toBe(true);
|
|
expect(g.nodes.get("A")?.label).toBeUndefined();
|
|
});
|
|
|
|
it("handles a labelled edge `A -->|yes| B`", () => {
|
|
const g = parseFlowchart("flowchart LR\n A -->|yes| B");
|
|
expect(g.edges[0]).toMatchObject({ from: "A", to: "B", label: "yes" });
|
|
});
|
|
|
|
it("ignores comments and blank lines", () => {
|
|
const g = parseFlowchart("flowchart LR\n%% a comment\n\n A-->B");
|
|
expect(g.edges).toHaveLength(1);
|
|
});
|
|
});
|
|
|
|
import { diffFlowchart } from "../src/mermaidFlowchartDiff";
|
|
|
|
describe("diffFlowchart", () => {
|
|
it("colors an added node with the cwAdded class", () => {
|
|
const before = "flowchart LR\n A-->B";
|
|
const current = "flowchart LR\n A-->B\n B-->C";
|
|
const out = diffFlowchart(before, current);
|
|
expect(out).toContain("classDef cwAdded");
|
|
expect(out).toMatch(/class\s+C\s+cwAdded/);
|
|
});
|
|
|
|
it("colors a changed node (same id, new label) with cwChanged", () => {
|
|
const before = "flowchart LR\n A[Old]-->B";
|
|
const current = "flowchart LR\n A[New]-->B";
|
|
const out = diffFlowchart(before, current);
|
|
expect(out).toMatch(/class\s+A\s+cwChanged/);
|
|
});
|
|
|
|
it("styles an added edge via linkStyle on its current index", () => {
|
|
const before = "flowchart LR\n A-->B";
|
|
const current = "flowchart LR\n A-->B\n A-->C";
|
|
const out = diffFlowchart(before, current);
|
|
// edge index 1 (A-->C) is the added one
|
|
expect(out).toMatch(/linkStyle\s+1\s+stroke:#2ea043/);
|
|
});
|
|
|
|
it("ghosts a removed node in place with cwRemoved (re-injected decl)", () => {
|
|
const before = "flowchart LR\n A-->B\n B-->C[Gone]";
|
|
const current = "flowchart LR\n A-->B";
|
|
const out = diffFlowchart(before, current);
|
|
expect(out).toContain("C[Gone]"); // re-injected
|
|
expect(out).toMatch(/class\s+C\s+cwRemoved/);
|
|
});
|
|
|
|
it("is deterministic (same inputs → identical output)", () => {
|
|
const before = "flowchart LR\n A-->B";
|
|
const current = "flowchart LR\n A-->B\n B-->C\n A-->D";
|
|
expect(diffFlowchart(before, current)).toBe(diffFlowchart(before, current));
|
|
});
|
|
|
|
it("preserves the original current source as the prefix", () => {
|
|
const current = "flowchart LR\n A-->B\n B-->C";
|
|
const out = diffFlowchart("flowchart LR\n A-->B", current);
|
|
expect(out.startsWith(current)).toBe(true);
|
|
});
|
|
});
|