Skip to content

Commit 2d6527f

Browse files
author
Mukul Kumar Yadav
committed
test(venn): strengthen jsdom render guard for issue mermaid-js#7656 fix
Address review feedback on PR mermaid-js#7758. - vennRenderer.spec.ts: the existing jsdom render test for issue mermaid-js#7656 only asserted that the "Innovation" label appeared in the DOM, which venn.js emits for any declared labeled union regardless of whether the circles actually overlap. The test passed even with expandImpliedSubsets bypassed. Replace it with an assertion on the rendered geometry: the three implied pairwise intersections (A-B, A-C, B-C) must be present in addition to the user-declared A-B-C intersection, and the 3-way intersection path must not be the degenerate "M 0 0" placeholder venn.js emits when an area has no visible geometry. Verified to fail when the fix is bypassed. - vennRenderer.ts: extract the synthesized-pair default size into a defaultSubsetSize(arity) helper using the same expression as vennDB.addSubsetData (10 / arity^2), and add a comment so the two defaults stay in sync. - docs/syntax/venn.md: add a "Higher-arity unions" section with a 3-set Desirable/Feasible/Viable Innovation example, since bare 3-way unions now render correctly.
1 parent e41c8e7 commit 2d6527f

4 files changed

Lines changed: 75 additions & 5 deletions

File tree

docs/syntax/venn.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ venn-beta
5353
union A,B["AB"]
5454
```
5555

56+
### Higher-arity unions
57+
58+
`union` accepts three or more set names. The diagram renders the implied
59+
pairwise overlaps automatically, so the label on the higher-arity union has a
60+
visible region to sit in:
61+
62+
```mermaid-example
63+
venn-beta
64+
set Desirable
65+
set Feasible
66+
set Viable
67+
union Desirable,Feasible,Viable["Innovation"]
68+
```
69+
70+
```mermaid
71+
venn-beta
72+
set Desirable
73+
set Feasible
74+
set Viable
75+
union Desirable,Feasible,Viable["Innovation"]
76+
```
77+
5678
### Sizes
5779

5880
Use `:N` suffix to set the size of a set or union:

packages/mermaid/src/diagrams/venn/vennRenderer.spec.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ describe('vennRenderer', () => {
165165
expect(debugCircle).not.toBeNull();
166166
});
167167

168-
it('renders label for 3-way union without explicit pairwise unions (issue #7656)', async () => {
168+
it('renders an overlapping layout for a bare 3-way union (issue #7656)', async () => {
169169
document.body.innerHTML = '<svg id="venn"></svg>';
170170
const diagram = createDiagram({
171171
getSubsetData: () => [
@@ -178,9 +178,36 @@ describe('vennRenderer', () => {
178178

179179
await draw('', 'venn', '1.0', diagram);
180180

181-
const intersectionTexts = [...document.querySelectorAll('.venn-intersection text')];
182-
const labels = intersectionTexts.map((el) => el.textContent);
183-
expect(labels).toContain('Innovation');
181+
// The label being present is necessary but not sufficient: venn.js emits a
182+
// `.venn-intersection text` element for any declared labeled union, even
183+
// when the circles do not actually overlap.
184+
const intersectionLabels = [...document.querySelectorAll('.venn-intersection text')].map(
185+
(el) => el.textContent
186+
);
187+
expect(intersectionLabels).toContain('Innovation');
188+
189+
// What the fix actually guarantees is that the layout produces overlapping
190+
// circles, which is visible in two complementary ways in the DOM:
191+
// 1. venn.js renders the three implied pairwise intersections, in addition
192+
// to the user-declared 3-way intersection.
193+
// 2. The 3-way intersection's SVG path is a real region, not the
194+
// degenerate `"M 0 0"` placeholder venn.js emits when an area has no
195+
// visible geometry on screen.
196+
const intersections = [...document.querySelectorAll('.venn-intersection')];
197+
const setsByPath = new Map<string, string | null>();
198+
for (const node of intersections) {
199+
const data = (node as unknown as { __data__?: { sets?: string[] } }).__data__;
200+
const sets = data?.sets ?? [];
201+
if (sets.length >= 2) {
202+
const key = [...sets].sort().join('|');
203+
setsByPath.set(key, node.querySelector('path')?.getAttribute('d') ?? null);
204+
}
205+
}
206+
expect([...setsByPath.keys()].sort()).toEqual(['A|B', 'A|B|C', 'A|C', 'B|C']);
207+
const threeWayPath = setsByPath.get('A|B|C');
208+
expect(threeWayPath).toBeTruthy();
209+
expect(threeWayPath).not.toBe('M 0 0');
210+
expect((threeWayPath ?? '').length).toBeGreaterThan(20);
184211
});
185212
});
186213

packages/mermaid/src/diagrams/venn/vennRenderer.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,17 @@ function buildStyleByKey(styleData: VennStyleData[]): Map<string, Record<string,
3434
// and renders the circles disjointly. We synthesize the missing pairwise
3535
// subsets here so the layout produces the expected overlapping diagram.
3636
// User-declared subsets are preserved verbatim.
37+
//
38+
// Synthesized pairs use the same default size that `vennDB.addSubsetData`
39+
// would have produced for an undeclared 2-way union, so a bare 3-way union
40+
// renders identically to one declared with all three pairwise unions left
41+
// at their defaults. Keep this expression in sync with vennDB.
42+
const defaultSubsetSize = (arity: number) => 10 / Math.pow(arity, 2);
43+
3744
export function expandImpliedSubsets(subsets: VennData[]): VennData[] {
3845
const existingKeys = new Set(subsets.map((s) => s.sets.join('|')));
3946
const implied: VennData[] = [];
40-
const defaultPairSize = 10 / 4;
47+
const defaultPairSize = defaultSubsetSize(2);
4148
for (const subset of subsets) {
4249
if (subset.sets.length < 3) {
4350
continue;

packages/mermaid/src/docs/syntax/venn.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ venn-beta
3232
union A,B["AB"]
3333
```
3434

35+
### Higher-arity unions
36+
37+
`union` accepts three or more set names. The diagram renders the implied
38+
pairwise overlaps automatically, so the label on the higher-arity union has a
39+
visible region to sit in:
40+
41+
```mermaid-example
42+
venn-beta
43+
set Desirable
44+
set Feasible
45+
set Viable
46+
union Desirable,Feasible,Viable["Innovation"]
47+
```
48+
3549
### Sizes
3650

3751
Use `:N` suffix to set the size of a set or union:

0 commit comments

Comments
 (0)