Skip to content

Commit 20f1afe

Browse files
committed
Add mobile-specific regression tests and visual snapshots for mobile-chromium
1 parent 0935125 commit 20f1afe

4 files changed

Lines changed: 73 additions & 4 deletions

File tree

playwright.config.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@ export default defineConfig({
5353
maxDiffPixelRatio: 0,
5454
},
5555
},
56-
// chromium is the source of truth for visual snapshots — those specs
57-
// self-skip on firefox/webkit via `test.skip(browserName !== 'chromium')`.
58-
// firefox/webkit cover structural, a11y, JSON-LD, and link tests so we
59-
// catch browser-specific CSS/JS regressions cheaply.
56+
// chromium is the source of truth for desktop visual snapshots — those
57+
// specs self-skip on firefox/webkit via grepInvert. firefox/webkit cover
58+
// structural, a11y, JSON-LD, and link tests so we catch browser-specific
59+
// CSS/JS regressions cheaply. mobile-chromium runs the whole suite at a
60+
// Pixel 7 viewport so the @media (max-width: 640px) branch (mobile-search
61+
// hoist) is regression-tested. tests/mobile.spec.ts is mobile-only and
62+
// contains the breakpoint-specific assertions + a mobile-only screenshot.
6063
projects: [
6164
{
6265
name: 'chromium',
@@ -65,6 +68,7 @@ export default defineConfig({
6568
viewport: { width: 1280, height: 800 },
6669
deviceScaleFactor: 1,
6770
},
71+
testIgnore: /mobile\.spec\.ts/,
6872
},
6973
{
7074
name: 'firefox',
@@ -73,6 +77,7 @@ export default defineConfig({
7377
viewport: { width: 1280, height: 800 },
7478
},
7579
grepInvert: /visual:/,
80+
testIgnore: /mobile\.spec\.ts/,
7681
},
7782
{
7883
name: 'webkit',
@@ -81,6 +86,17 @@ export default defineConfig({
8186
viewport: { width: 1280, height: 800 },
8287
},
8388
grepInvert: /visual:/,
89+
testIgnore: /mobile\.spec\.ts/,
90+
},
91+
{
92+
name: 'mobile-chromium',
93+
use: {
94+
...devices['Pixel 7'],
95+
},
96+
// Skip desktop visual snapshots — those expect 1280px viewport and
97+
// their baselines are platform-keyed without a mobile axis. The
98+
// `mobile snapshot:` prefix in mobile.spec.ts bypasses this filter.
99+
grepInvert: /visual:/,
84100
},
85101
],
86102
webServer: {
159 KB
Loading
154 KB
Loading

tests/mobile.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { test, expect } from '@playwright/test';
2+
import AxeBuilder from '@axe-core/playwright';
3+
4+
// Mobile-specific regression tests. Only runs in the `mobile-chromium`
5+
// Playwright project (Pixel 7 viewport ≈ 412×915). Desktop projects skip
6+
// this file via `testIgnore` in playwright.config.ts.
7+
//
8+
// Visual tests use the prefix `mobile snapshot:` rather than the desktop
9+
// `visual:` prefix so the desktop projects' grepInvert doesn't interfere.
10+
11+
test.describe('mobile breakpoint', () => {
12+
test('mobile-search is visible, sidebar-search is hidden', async ({
13+
page,
14+
}) => {
15+
await page.goto('/');
16+
await expect(page.locator('.mobile-search')).toBeVisible();
17+
await expect(page.locator('.sidebar-search')).toBeHidden();
18+
});
19+
20+
test('home page has no critical or serious a11y violations at mobile width', async ({
21+
page,
22+
}) => {
23+
await page.goto('/');
24+
await page.waitForLoadState('domcontentloaded');
25+
26+
const results = await new AxeBuilder({ page })
27+
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
28+
.exclude('[id^="embedded-badge-"]')
29+
.exclude('#disqus_thread')
30+
.analyze();
31+
32+
const blocking = results.violations.filter(
33+
(v) => v.impact === 'critical' || v.impact === 'serious',
34+
);
35+
const formatted = blocking.map((v) => ({
36+
id: v.id,
37+
impact: v.impact,
38+
help: v.help,
39+
helpUrl: v.helpUrl,
40+
nodes: v.nodes.map((n) => ({ html: n.html, target: n.target })),
41+
}));
42+
expect(formatted, `axe-core violations on / at mobile`).toEqual([]);
43+
});
44+
45+
test('mobile snapshot: home above the fold', async ({ page }) => {
46+
await page.goto('/');
47+
await page.waitForLoadState('domcontentloaded');
48+
await expect(page).toHaveScreenshot(
49+
`home-mobile-${process.platform}.png`,
50+
{ fullPage: false },
51+
);
52+
});
53+
});

0 commit comments

Comments
 (0)