Skip to content

Commit 18d19f8

Browse files
committed
Build/Test Tools: Add visual regression tests for admin pages.
1 parent dbf8614 commit 18d19f8

3 files changed

Lines changed: 446 additions & 140 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Global stylesheet applied during screenshot capture.
3+
*
4+
* Hides volatile elements that change between environments or runs,
5+
* preventing false positives in visual regression comparisons.
6+
* Applied via Playwright's stylePath config option.
7+
*
8+
* See: https://playwright.dev/docs/test-snapshots#stylepath
9+
*/
10+
11+
/*
12+
* Uses `visibility: hidden` instead of `display: none` to preserve
13+
* each element's layout space. Collapsing elements with `display: none`
14+
* would shift surrounding content and cause false positives elsewhere.
15+
*/
16+
17+
/* WordPress version/update nag in the admin footer. */
18+
#footer-upgrade {
19+
visibility: hidden !important;
20+
}
21+
22+
/* Admin bar user-specific content (Howdy, gravatar). */
23+
#wp-admin-bar-root-default {
24+
visibility: hidden !important;
25+
}
26+
27+
/* Gutenberg plugin menu item — not present in all environments. */
28+
#toplevel_page_gutenberg {
29+
visibility: hidden !important;
30+
}
31+
32+
/* Gravatar images — external service, different per environment. */
33+
.avatar {
34+
visibility: hidden !important;
35+
}
36+
37+
/* Date columns in list tables — relative timestamps shift between runs. */
38+
.column-date {
39+
visibility: hidden !important;
40+
}
41+
42+
/* Dashboard widgets with dynamic counts and activity. */
43+
#dashboard_right_now .inside,
44+
#dashboard_activity .inside {
45+
visibility: hidden !important;
46+
}
47+
48+
/* Update-related timestamps. */
49+
.update-last-checked {
50+
visibility: hidden !important;
51+
}
52+
53+
/*
54+
* Admin notices — various nags (PHP deprecation, updates, etc.).
55+
* `.error:not(#error)` excludes the `<div id="error">` database error
56+
* container from wpdb (wp-includes/class-wpdb.php) as a defensive measure.
57+
*/
58+
.notice,
59+
.update-nag,
60+
.updated,
61+
.error:not(#error),
62+
#message {
63+
visibility: hidden !important;
64+
}
65+
66+
/* General Settings — live date/time preview changes on every run. */
67+
#local-time,
68+
.example {
69+
visibility: hidden !important;
70+
}
71+
72+
/* Users list table — post counts vary based on test data. */
73+
.column-posts {
74+
visibility: hidden !important;
75+
}

tests/visual-regression/playwright.config.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/**
2+
* Playwright config for visual regression tests.
3+
*
4+
* Captures full-page screenshots of WordPress admin screens and compares
5+
* them against baseline snapshots. Intended for local use to catch
6+
* unintended visual changes during development.
7+
*
8+
* Usage:
9+
* npm run test:visual -- --update-snapshots # generate baselines
10+
* npm run test:visual # compare against baselines
11+
*
12+
* @see tests/visual-regression/config/screenshot.css for globally hidden elements.
13+
* @see tests/visual-regression/specs/visual-snapshots.test.js for the test spec.
14+
*/
15+
116
/**
217
* External dependencies
318
*/
@@ -15,9 +30,53 @@ process.env.STORAGE_STATE_PATH ??= path.join(
1530
'storage-states/admin.json'
1631
);
1732

33+
// Reporters:
34+
// - 'list' — prints pass/fail per test in the terminal.
35+
// - 'github' — adds inline PR annotations when running in CI.
36+
// - 'html' — generates a visual report with side-by-side diff images;
37+
// opens automatically after local runs.
38+
const reporter = [
39+
[ 'list' ],
40+
...( process.env.CI ? [ [ 'github' ] ] : [] ),
41+
[
42+
'html',
43+
{
44+
open: process.env.CI ? 'never' : 'always',
45+
outputFolder: path.join(
46+
process.env.WP_ARTIFACTS_PATH,
47+
'visual-report'
48+
),
49+
},
50+
],
51+
];
52+
1853
const config = defineConfig( {
1954
...baseConfig,
20-
globalSetup: undefined,
55+
fullyParallel: true,
56+
// No retries — visual diffs are expected when regressions exist;
57+
// retrying would just re-confirm the same diff.
58+
retries: 0,
59+
// Serialize tests in CI to reduce flakiness from resource contention.
60+
workers: process.env.CI ? 1 : undefined,
61+
reporter,
62+
use: {
63+
...baseConfig.use,
64+
viewport: { width: 1280, height: 720 },
65+
},
66+
expect: {
67+
toHaveScreenshot: {
68+
// Only disables CSS animations/transitions. JavaScript-driven
69+
// animations (e.g. jQuery .animate()) can still cause flakes.
70+
animations: 'disabled',
71+
// Captures the entire scrollable page, not just the viewport.
72+
// The viewport width (1280) still matters — it controls layout.
73+
fullPage: true,
74+
// 1% tolerance — catches real regressions while ignoring
75+
// sub-pixel anti-aliasing differences across environments.
76+
maxDiffPixelRatio: 0.01,
77+
stylePath: path.join( __dirname, 'config', 'screenshot.css' ),
78+
},
79+
},
2180
webServer: {
2281
...baseConfig.webServer,
2382
command: 'npm run env:start',

0 commit comments

Comments
 (0)