Visual Tests
| Key | Value |
|---|---|
| Status | Active |
| Owner | QA Automation |
| Updated | 2026-03-26 |
| Scope | Structural layout regression detection across all 6 CNC sites |
Visual tests exist because structural layout changes are invisible to functional tests. A navigation bar that shifts position, a footer that loses its grid, or a header that loses its branding elements will not cause a smoke test to fail. Visual tests catch that class of change by comparing screenshots against stored baselines.
What This Suite Is — And Is Not
| This Suite Is | This Suite Is Not |
|---|---|
| structural layout regression detection | pixel-perfect screenshot comparison |
| a weekly check for layout drift | a replacement for functional tests |
| a signal that something changed | a definitive pass/fail for every visual detail |
| CI-stable by design | sensitive to content rotation or ad delivery |
News sites change text, images, and ads every few minutes. The suite hides all content and compares only layout structure — grid, spacing, background colors, borders, element positions.
Current Shape
| Metric | Current Snapshot |
|---|---|
| total tests | 18 |
| passing | 18 |
| pass rate | 100% |
| tests per site | 3 |
| sites covered | 6 |
| schedule | weekly |
The Three Tests Per Site
| Test | Tag | What Is Compared |
|---|---|---|
| homepage above fold | @visual @critical | above-fold viewport of homepage |
| header component | @visual @component | header element (selector per site) |
| footer component | @visual @component | footer element, clipped to 600px height |
What Is Hidden Before Comparison
All dynamic content is hidden via CSS injection before the screenshot is taken. This makes comparisons stable across runs without being meaningless.
| Hidden Content | Why |
|---|---|
| consent overlays (CPEX, Didomi) | storageState prevents them, but belt-and-suspenders |
| ad containers and iframes | ad delivery varies per run |
| timestamps and view counters | change every minute |
| live tickers and breaking news banners | change every minute |
| all images, pictures, SVGs | news images rotate constantly |
| all text content | headlines, bylines, article text rotate constantly |
| video players and canvases | playback state varies |
| animations and transitions | disabled to prevent mid-animation captures |
What remains in the comparison is: grid structure, spacing, background colors, borders, element positions, and block-level layout. A header that moves or a footer that loses columns will show up as a diff.
Comparison Thresholds
Thresholds are deliberately generous because even with content hidden, minor rendering differences occur between CI machines.
| Test | maxDiffPixels | maxDiffPixelRatio | threshold |
|---|---|---|---|
| homepage above fold | 5,000 | 0.05 (5%) | 0.30 |
| header component | 2,000 | 0.03 (3%) | 0.25 |
| footer component | 3,000 | 0.03 (3%) | 0.25 |
The threshold value (0.25–0.30) is the per-pixel color similarity threshold used by Playwright's image comparison engine. Values above zero allow for sub-pixel anti-aliasing differences.
Snapshot Baseline Location
Baseline screenshots are stored alongside the spec file.
| Path | Contents |
|---|---|
tests/visual.spec.ts-snapshots/ | 18 PNG files (3 per site) |
File naming convention: {site}-{test-type}-visual-{platform}.png
Examples:
blesk-homepage-fold-visual-darwin.pngblesk-header-visual-darwin.pngblesk-footer-visual-darwin.png
Platform suffix (darwin) is added automatically by Playwright based on the OS where the baseline was captured. Baselines captured on macOS must be compared on macOS; CI must use the same platform.
Header And Footer Selectors
| Site | Header Selector | Footer Selector |
|---|---|---|
| Blesk | div.navigation__wrapper | footer#footer, footer.footer-2024 |
| Auto | div.header-wrapper | footer |
| E15 | div.header | footer > div.footer-wrapper, footer |
| Reflex | header, .header-wrapper | footer |
| iSport | div.navigation__wrapper, header | footer#footer, footer |
| Opinio | div[class="header"], [class="Header"] | div.g-ui-footer, footer |
These selectors are production-verified and stored in the spec file.
How To Run
| Command | What It Does |
|---|---|
npm run test:visual | All 18 tests across 6 sites |
SITE=blesk npm run test:visual | Blesk only (3 tests) |
npx playwright test --update-snapshots --project=visual | Update all baselines |
SITE=blesk npx playwright test --update-snapshots --project=visual | Update baselines for one site |
When To Update Snapshots
Snapshots should be updated when a change is intentional and the diff represents the expected new state.
| Situation | Action |
|---|---|
| deliberate site redesign or header/footer update | update snapshots after verifying the new layout is correct |
| new nav item added | update snapshots |
| logo or brand change | update snapshots |
| CI platform changed (macOS → Linux) | regenerate all baselines on the new platform |
| test fails in CI but looks correct in local review | check if the diff is a genuine regression or a platform difference |
When Visual Failures Signal A Real Regression
Not every visual diff is worth investigating, but some patterns reliably mean something broke.
| Diff Pattern | Likely Cause |
|---|---|
| header element missing entirely | selector broke or header removed from DOM |
| footer grid collapsed to single column | CSS regression |
| navigation shifted 50+ pixels down | sticky header CSS changed |
| entire above-fold viewport is blank | page failed to load properly |
| diff concentrated in one component | that component's layout changed |
Infrastructure Design Decisions
| Decision | Reason |
|---|---|
storageState handles consent (not armCncConsent) | avoids locator-handler loops that could block screenshot capture |
waitUntil: 'domcontentloaded' (not networkidle) | CNC ad scripts never fully settle; networkidle would hang |
| above-fold viewport only for homepage test | full-page screenshots amplify content rotation diffs |
| footer clipped to 600px height | dynamic topic link sections at bottom change length between runs |
| infrastructure errors → skip (not fail) | a navigation timeout on one site should not block the other five |
Related Pages
| Need | Go To |
|---|---|
| functional homepage tests | Smoke Tests |
| high-level suite list | Test Types |