Skip to content

Commit 6e9cb0a

Browse files
heavygeecursoragent
andcommitted
test(web): Playwright asserts click expands diagram vs inline
Measure inline vs lightbox bounding box after click; require visible growth (area ratio or max dimension) plus dialog + shadow SVG content. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 7da96ec commit 6e9cb0a

1 file changed

Lines changed: 69 additions & 29 deletions

File tree

web/e2e/mermaid-lightbox.spec.ts

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,31 @@ type LightboxMetrics = {
1515
shapes: { rect: number; path: number; line: number }
1616
}
1717

18-
async function openLightboxForCase(page: import('@playwright/test').Page, caseId: string) {
19-
await page.goto(`/mermaid-lightbox-e2e.html?case=${encodeURIComponent(caseId)}`)
20-
await page.waitForSelector('[data-mermaid-diagram][data-rendered="true"]', { timeout: 20_000 })
21-
await page.locator('[data-mermaid-diagram][data-rendered="true"]').click()
22-
await page.waitForSelector('[role="dialog"]', { timeout: 10_000 })
18+
type ExpandMetrics = {
19+
inlineW: number
20+
inlineH: number
21+
lightboxW: number
22+
lightboxH: number
23+
areaRatio: number
24+
}
2325

24-
await page.waitForFunction(() => {
26+
async function readExpandMetrics(page: import('@playwright/test').Page): Promise<ExpandMetrics> {
27+
return page.evaluate(() => {
28+
const inlineSvg = document.querySelector('[data-mermaid-diagram][data-rendered="true"] svg')
29+
const inlineBox = inlineSvg?.getBoundingClientRect()
2530
const host = document.querySelector('[data-mermaid-lightbox]')
26-
const svg = host?.shadowRoot?.querySelector('svg')
27-
const box = svg?.getBoundingClientRect()
28-
return Boolean(box && box.width > 0 && box.height > 0)
29-
}, { timeout: 15_000 })
30-
31-
await page
32-
.waitForFunction(
33-
(minCoverage) => {
34-
const host = document.querySelector('[data-mermaid-lightbox]')
35-
const svg = host?.shadowRoot?.querySelector('svg')
36-
const box = svg?.getBoundingClientRect()
37-
if (!box || box.width <= 0) return false
38-
const vw = window.visualViewport?.width ?? window.innerWidth
39-
const vh = window.visualViewport?.height ?? window.innerHeight
40-
return Math.max(box.width / vw, box.height / vh) >= minCoverage
41-
},
42-
MIN_COVERAGE,
43-
{ timeout: 8_000 },
44-
)
45-
.catch(() => {
46-
// Final expect below surfaces fit failures.
47-
})
31+
const lightboxSvg = host?.shadowRoot?.querySelector('svg')
32+
const lightboxBox = lightboxSvg?.getBoundingClientRect()
33+
const inlineArea = (inlineBox?.width ?? 0) * (inlineBox?.height ?? 0)
34+
const lightboxArea = (lightboxBox?.width ?? 0) * (lightboxBox?.height ?? 0)
35+
return {
36+
inlineW: inlineBox?.width ?? 0,
37+
inlineH: inlineBox?.height ?? 0,
38+
lightboxW: lightboxBox?.width ?? 0,
39+
lightboxH: lightboxBox?.height ?? 0,
40+
areaRatio: inlineArea > 0 ? lightboxArea / inlineArea : 0,
41+
}
42+
})
4843
}
4944

5045
async function readLightboxMetrics(page: import('@playwright/test').Page): Promise<LightboxMetrics> {
@@ -107,10 +102,55 @@ function assertMetrics(caseId: string, metrics: LightboxMetrics) {
107102
}
108103
}
109104

105+
/** Lightbox should be visibly larger than the inline chat preview after click. */
106+
const MIN_EXPAND_AREA_RATIO = Number(process.env.MERMAID_E2E_MIN_EXPAND_RATIO ?? '1.4')
107+
110108
for (const caseId of MERMAID_LIGHTBOX_CASE_IDS) {
111109
test(`mermaid lightbox: ${caseId}`, async ({ page }) => {
112-
await openLightboxForCase(page, caseId)
110+
await page.goto(`/mermaid-lightbox-e2e.html?case=${encodeURIComponent(caseId)}`)
111+
await page.waitForSelector('[data-mermaid-diagram][data-rendered="true"]', { timeout: 20_000 })
112+
113+
const beforeExpand = await readExpandMetrics(page)
114+
expect(beforeExpand.lightboxW, `${caseId}: dialog closed before click`).toBe(0)
115+
116+
await page.locator('[data-mermaid-diagram][data-rendered="true"]').click()
117+
await page.waitForSelector('[role="dialog"]', { timeout: 10_000 })
118+
await page.waitForFunction(() => {
119+
const host = document.querySelector('[data-mermaid-lightbox]')
120+
const svg = host?.shadowRoot?.querySelector('svg')
121+
const box = svg?.getBoundingClientRect()
122+
return Boolean(box && box.width > 0 && box.height > 0)
123+
}, { timeout: 15_000 })
124+
125+
await page
126+
.waitForFunction(
127+
(minCoverage) => {
128+
const host = document.querySelector('[data-mermaid-lightbox]')
129+
const svg = host?.shadowRoot?.querySelector('svg')
130+
const box = svg?.getBoundingClientRect()
131+
if (!box || box.width <= 0) return false
132+
const vw = window.visualViewport?.width ?? window.innerWidth
133+
const vh = window.visualViewport?.height ?? window.innerHeight
134+
return Math.max(box.width / vw, box.height / vh) >= minCoverage
135+
},
136+
MIN_COVERAGE,
137+
{ timeout: 8_000 },
138+
)
139+
.catch(() => undefined)
140+
141+
const expand = await readExpandMetrics(page)
142+
const inlineMax = Math.max(expand.inlineW, expand.inlineH)
143+
const lightboxMax = Math.max(expand.lightboxW, expand.lightboxH)
144+
const expandedVisibly =
145+
expand.areaRatio >= MIN_EXPAND_AREA_RATIO || lightboxMax > inlineMax * 1.05
146+
expect(expandedVisibly, `${caseId}: expand inline ${Math.round(expand.inlineW)}x${Math.round(expand.inlineH)} → lightbox ${Math.round(expand.lightboxW)}x${Math.round(expand.lightboxH)}`).toBe(true)
147+
113148
const metrics = await readLightboxMetrics(page)
114149
assertMetrics(caseId, metrics)
150+
151+
test.info().annotations.push({
152+
type: 'expand',
153+
description: `${caseId}: inline ${Math.round(expand.inlineW)}x${Math.round(expand.inlineH)} → lightbox ${Math.round(expand.lightboxW)}x${Math.round(expand.lightboxH)} (${expand.areaRatio.toFixed(1)}x area)`,
154+
})
115155
})
116156
}

0 commit comments

Comments
 (0)