Skip to content

Commit 7cb202d

Browse files
committed
test(webview): cover layout drift modes
1 parent 0f90a56 commit 7cb202d

10 files changed

Lines changed: 84 additions & 9 deletions

webview-ui/src/components/ui/__tests__/AccessibilityContrast.visual.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ for (const theme of visualThemes) {
181181
}),
182182
).rejects.toThrow("Unsupported background image")
183183

184-
const snapshot = page.locator("#root")
185-
await expect(snapshot).toHaveScreenshot(`accessibility-gallery-resting-${theme.name}.png`)
184+
await expect(component).toHaveScreenshot(`accessibility-gallery-resting-${theme.name}.png`)
186185

187186
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur())
188187
for (
@@ -205,6 +204,6 @@ for (const theme of visualThemes) {
205204
minimum: 3,
206205
label: `${theme.name} input focus indicator against fill`,
207206
})
208-
await expect(snapshot).toHaveScreenshot(`accessibility-gallery-focus-${theme.name}.png`)
207+
await expect(component).toHaveScreenshot(`accessibility-gallery-focus-${theme.name}.png`)
209208
})
210209
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

webview-ui/src/components/welcome/__tests__/WelcomeViewProvider.visual.tsx

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,73 @@
11
import React from "react"
2+
import type { Locator } from "@playwright/test"
23

34
import { expect, test } from "../../../../playwright/coverage-fixture"
45
import { AppProviders } from "../../../../playwright/AppProviders"
56
import { expectContrast } from "../../../../playwright/contrast"
67
import { applyVisualTheme, visualThemes } from "../../../../playwright/themes"
78
import { WelcomeLanding } from "../WelcomeLanding"
89

10+
const textSpacingStyles = `
11+
/* WCAG 1.4.12 text-spacing override values. */
12+
* {
13+
line-height: 1.5 !important;
14+
letter-spacing: 0.12em !important;
15+
word-spacing: 0.16em !important;
16+
}
17+
18+
p {
19+
margin-bottom: 2em !important;
20+
}
21+
`
22+
23+
async function expectScreenContentToFit(screen: Locator) {
24+
const layout = await screen.evaluate((element) => {
25+
const screenRect = element.getBoundingClientRect()
26+
const content = Array.from(element.querySelectorAll("h2, p, button")).map((item) => {
27+
const rect = item.getBoundingClientRect()
28+
return {
29+
left: rect.left,
30+
right: rect.right,
31+
clientWidth: item.clientWidth,
32+
scrollWidth: item.scrollWidth,
33+
clientHeight: item.clientHeight,
34+
scrollHeight: item.scrollHeight,
35+
}
36+
})
37+
38+
return {
39+
clientWidth: element.clientWidth,
40+
scrollWidth: element.scrollWidth,
41+
left: screenRect.left,
42+
right: screenRect.right,
43+
content,
44+
}
45+
})
46+
47+
expect(layout.scrollWidth).toBeLessThanOrEqual(layout.clientWidth)
48+
for (const item of layout.content) {
49+
expect(item.left).toBeGreaterThanOrEqual(layout.left)
50+
expect(item.right).toBeLessThanOrEqual(layout.right)
51+
expect(item.scrollWidth).toBeLessThanOrEqual(item.clientWidth)
52+
expect(item.scrollHeight).toBeLessThanOrEqual(item.clientHeight)
53+
}
54+
}
55+
56+
async function mountWelcomeScreen(mount: (component: React.ReactElement) => Promise<Locator>) {
57+
const component = await mount(
58+
<AppProviders initialState={{ apiConfiguration: {} }}>
59+
<WelcomeLanding onGetStarted={() => undefined} onImportSettings={() => undefined} />
60+
</AppProviders>,
61+
)
62+
return { component, screen: component.locator(".fixed.inset-0") }
63+
}
64+
965
for (const theme of visualThemes) {
1066
test(`renders the full welcome screen in the VS Code ${theme.name} theme`, async ({ mount, page }) => {
1167
await page.setViewportSize({ width: 480, height: 640 })
1268
await applyVisualTheme(page, theme)
13-
const component = await mount(
14-
<AppProviders initialState={{ apiConfiguration: {} }}>
15-
<WelcomeLanding onGetStarted={() => undefined} onImportSettings={() => undefined} />
16-
</AppProviders>,
17-
)
69+
const { component, screen } = await mountWelcomeScreen(mount)
1870

19-
const screen = component.locator(".fixed.inset-0")
2071
const heading = component.getByRole("heading", { level: 2 })
2172
const action = component.getByRole("button", { name: /provider/i }).first()
2273
await expect(heading).toBeVisible()
@@ -38,4 +89,29 @@ for (const theme of visualThemes) {
3889

3990
await expect(screen).toHaveScreenshot(`welcome-screen-${theme.name}.png`)
4091
})
92+
93+
test(`reflows the welcome screen at 320px in the VS Code ${theme.name} theme`, async ({ mount, page }) => {
94+
await page.setViewportSize({ width: 320, height: 640 })
95+
await applyVisualTheme(page, theme)
96+
const { component, screen } = await mountWelcomeScreen(mount)
97+
98+
await expect(component.getByRole("heading", { level: 2 })).toBeVisible()
99+
await expect(component.getByRole("button", { name: /provider/i }).first()).toBeVisible()
100+
await expect(component.getByRole("button", { name: /import/i })).toBeVisible()
101+
await expectScreenContentToFit(screen)
102+
await expect(screen).toHaveScreenshot(`welcome-screen-reflow-${theme.name}.png`)
103+
})
104+
105+
test(`supports WCAG text spacing in the VS Code ${theme.name} theme`, async ({ mount, page }) => {
106+
await page.setViewportSize({ width: 480, height: 640 })
107+
await applyVisualTheme(page, theme)
108+
const { component, screen } = await mountWelcomeScreen(mount)
109+
await page.addStyleTag({ content: textSpacingStyles })
110+
111+
await expect(component.getByRole("heading", { level: 2 })).toBeVisible()
112+
await expect(component.getByRole("button", { name: /provider/i }).first()).toBeVisible()
113+
await expect(component.getByRole("button", { name: /import/i })).toBeVisible()
114+
await expectScreenContentToFit(screen)
115+
await expect(screen).toHaveScreenshot(`welcome-screen-text-spacing-${theme.name}.png`)
116+
})
41117
}

0 commit comments

Comments
 (0)