Skip to content

Commit ba342cc

Browse files
committed
test(architecture): add TypeScript unit tests for drawGroups and remove JS duplicate
1 parent 451fc2e commit ba342cc

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

packages/mermaid/src/diagrams/architecture/svgDraw.spec.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,116 @@
1+
import { vi } from 'vitest';
2+
import { drawGroups } from './svgDraw.js';
3+
4+
// Minimal Mock for D3 element
5+
const MockD3 = (name: string) => {
6+
const children: any[] = [];
7+
const elem: any = {
8+
__name: name,
9+
__children: children,
10+
};
11+
elem.append = (tag: string) => {
12+
const child = MockD3(tag);
13+
children.push(child);
14+
return child;
15+
};
16+
elem.attr = vi.fn(() => elem);
17+
elem.html = vi.fn(() => elem);
18+
return elem;
19+
};
20+
21+
describe('architecture svgDraw drawGroups', () => {
22+
it('calculates group bbox from children getBBox when available', async () => {
23+
const groupsEl = MockD3('svg');
24+
25+
// Mock cy with one group node that has two children
26+
const child1: any = {
27+
id: () => 's1',
28+
position: () => ({ x: 100, y: 50 }),
29+
data: () => ({ width: 40, height: 20 }),
30+
children: () => [],
31+
};
32+
const child2: any = {
33+
id: () => 's2',
34+
position: () => ({ x: 200, y: 150 }),
35+
data: () => ({ width: 60, height: 30 }),
36+
children: () => [],
37+
};
38+
39+
const groupNode: any = {
40+
data: () => ({ id: 'g1', type: 'group', label: 'My Group' }),
41+
children: () => [child1, child2],
42+
boundingBox: () => ({ x1: 0, y1: 0, x2: 0, y2: 0 }),
43+
};
44+
45+
const cy: any = {
46+
nodes: () => [groupNode],
47+
};
48+
49+
// Mock db with getElementById returning elements that have node().getBBox()
50+
const db: any = {
51+
getConfigField: (k: string) => {
52+
if (k === 'padding') {
53+
return 10;
54+
}
55+
if (k === 'fontSize') {
56+
return 12;
57+
}
58+
if (k === 'iconSize') {
59+
return 24;
60+
}
61+
return 0;
62+
},
63+
getElementById: (id: string) => {
64+
if (id === 's1') {
65+
return { node: () => ({ getBBox: () => ({ width: 40, height: 20 }) }) };
66+
}
67+
if (id === 's2') {
68+
return { node: () => ({ getBBox: () => ({ width: 60, height: 30 }) }) };
69+
}
70+
return null;
71+
},
72+
setElementForId: vi.fn(),
73+
};
74+
75+
await drawGroups(groupsEl, cy, db);
76+
77+
// Expect a rect appended for the group
78+
const rects = groupsEl.__children.filter((c: any) => c.__name === 'rect');
79+
expect(rects.length).toBe(1);
80+
const rect = rects[0];
81+
// attr should have been called to set id, x, y, width, height
82+
expect(rect.attr).toHaveBeenCalledWith('id', 'group-g1');
83+
expect(rect.attr).toHaveBeenCalledWith('class', 'node-bkg');
84+
// db.setElementForId should have been called with group id
85+
expect(db.setElementForId).toHaveBeenCalledWith('g1', rect);
86+
});
87+
88+
it('falls back to cytoscape boundingBox when no children', async () => {
89+
const groupsEl = MockD3('svg');
90+
91+
const groupNode: any = {
92+
data: () => ({ id: 'g2', type: 'group', label: 'Empty Group' }),
93+
children: () => [],
94+
boundingBox: () => ({ x1: 10, y1: 20, x2: 110, y2: 120 }),
95+
};
96+
const cy: any = { nodes: () => [groupNode] };
97+
98+
const db: any = {
99+
getConfigField: (k: string) => (k === 'padding' ? 8 : k === 'iconSize' ? 24 : 12),
100+
getElementById: () => null,
101+
setElementForId: vi.fn(),
102+
};
103+
104+
await drawGroups(groupsEl, cy, db);
105+
106+
const rects = groupsEl.__children.filter((c: any) => c.__name === 'rect');
107+
expect(rects.length).toBe(1);
108+
const rect = rects[0];
109+
expect(rect.attr).toHaveBeenCalledWith('id', 'group-g2');
110+
expect(db.setElementForId).toHaveBeenCalledWith('g2', rect);
111+
});
112+
});
113+
1114
import { describe } from 'vitest';
2115
import { draw } from './architectureRenderer.js';
3116
import { Diagram } from '../../Diagram.js';

0 commit comments

Comments
 (0)