Skip to content

Commit 5d28139

Browse files
committed
test: add worker interview tests and SDK edge case coverage
25 worker interview tests simulating user sessions across all graph types, features, and edge cases. 8 SDK edge case tests for self-loops, disconnected nodes, RL/BT directions, label edge cases, and arrowheads.
1 parent f15177e commit 5d28139

File tree

2 files changed

+690
-0
lines changed

2 files changed

+690
-0
lines changed

src/sdk.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,4 +1405,112 @@ A[Start]-->B[End]`);
14051405
expect(arrows[0].strokeStyle).toBe("dashed");
14061406
});
14071407
});
1408+
1409+
describe("edge cases", () => {
1410+
it("self-loop edge creates valid arrow", async () => {
1411+
const d = new Diagram();
1412+
const a = d.addBox("A", { row: 0, col: 0 });
1413+
d.connect(a, a);
1414+
1415+
const result = await d.render({ format: "excalidraw" });
1416+
const arrow = result.json.elements.find(e => e.type === "arrow");
1417+
expect(arrow).toBeDefined();
1418+
// Self-loop arrow exists — bindings may be null depending on layout engine
1419+
expect(arrow!.points!.length).toBeGreaterThanOrEqual(2);
1420+
});
1421+
1422+
it("disconnected nodes included in stats", async () => {
1423+
const d = new Diagram();
1424+
const a = d.addBox("A", { row: 0, col: 0 });
1425+
const b = d.addBox("B", { row: 1, col: 0 });
1426+
const c = d.addBox("C", { row: 2, col: 0 });
1427+
d.connect(a, b);
1428+
1429+
const result = await d.render({ format: "excalidraw" });
1430+
expect(result.stats!.nodes).toBe(3);
1431+
expect(result.stats!.edges).toBe(1);
1432+
});
1433+
1434+
it("RL direction renders without error", async () => {
1435+
const d = new Diagram({ direction: "RL" });
1436+
const a = d.addBox("A", { row: 0, col: 0 });
1437+
const b = d.addBox("B", { row: 0, col: 1 });
1438+
d.connect(a, b);
1439+
1440+
const result = await d.render({ format: "excalidraw" });
1441+
const elA = result.json.elements.find(e => e.id === a);
1442+
const elB = result.json.elements.find(e => e.id === b);
1443+
expect(elA).toBeDefined();
1444+
expect(elB).toBeDefined();
1445+
// RL reversal depends on Graphviz WASM; TS fallback places L→R
1446+
if (isWasmLoaded()) {
1447+
expect(elB!.x).toBeLessThan(elA!.x);
1448+
}
1449+
});
1450+
1451+
it("BT direction renders without error", async () => {
1452+
const d = new Diagram({ direction: "BT" });
1453+
const a = d.addBox("A", { row: 0, col: 0 });
1454+
const b = d.addBox("B", { row: 1, col: 0 });
1455+
d.connect(a, b);
1456+
1457+
const result = await d.render({ format: "excalidraw" });
1458+
const elA = result.json.elements.find(e => e.id === a);
1459+
const elB = result.json.elements.find(e => e.id === b);
1460+
expect(elA).toBeDefined();
1461+
expect(elB).toBeDefined();
1462+
// BT reversal depends on Graphviz WASM; TS fallback places T→B
1463+
if (isWasmLoaded()) {
1464+
expect(elB!.y).toBeLessThan(elA!.y);
1465+
}
1466+
});
1467+
1468+
it("empty label produces element", async () => {
1469+
const d = new Diagram();
1470+
const id = d.addBox("");
1471+
1472+
const result = await d.render({ format: "excalidraw" });
1473+
const shape = result.json.elements.find(e => e.id === id);
1474+
expect(shape).toBeDefined();
1475+
});
1476+
1477+
it("200-char label produces wider element", async () => {
1478+
const d = new Diagram();
1479+
const id = d.addBox("A".repeat(200));
1480+
1481+
const result = await d.render({ format: "excalidraw" });
1482+
const shape = result.json.elements.find(e => e.id === id);
1483+
expect(shape).toBeDefined();
1484+
expect(shape!.width).toBeGreaterThan(180);
1485+
});
1486+
1487+
it("special chars in label don't break JSON", async () => {
1488+
const label = '<script>alert("xss")</script>&amp;';
1489+
const d = new Diagram();
1490+
const id = d.addBox(label);
1491+
1492+
const result = await d.render({ format: "excalidraw" });
1493+
expect(() => JSON.stringify(result.json)).not.toThrow();
1494+
const textEl = result.json.elements.find(e => e.id === `${id}-text`);
1495+
expect(textEl).toBeDefined();
1496+
expect(textEl!.text).toBe(label);
1497+
});
1498+
1499+
it("all arrowhead types wire through", async () => {
1500+
const arrowheadTypes = [null, "arrow", "bar", "dot", "triangle", "diamond", "diamond_outline"] as const;
1501+
1502+
for (const arrowhead of arrowheadTypes) {
1503+
const d = new Diagram();
1504+
const a = d.addBox("A", { row: 0, col: 0 });
1505+
const b = d.addBox("B", { row: 1, col: 0 });
1506+
d.connect(a, b, "label", { startArrowhead: arrowhead, endArrowhead: arrowhead });
1507+
1508+
const result = await d.render({ format: "excalidraw" });
1509+
const arrow = result.json.elements.find(e => e.type === "arrow");
1510+
expect(arrow).toBeDefined();
1511+
expect(arrow!.startArrowhead).toBe(arrowhead);
1512+
expect(arrow!.endArrowhead).toBe(arrowhead);
1513+
}
1514+
});
1515+
});
14081516
});

0 commit comments

Comments
 (0)