Visual Tests

KeyValue
StatusActive
OwnerQA Automation
Updated2026-03-26
ScopeStructural 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 IsThis Suite Is Not
structural layout regression detectionpixel-perfect screenshot comparison
a weekly check for layout drifta replacement for functional tests
a signal that something changeda definitive pass/fail for every visual detail
CI-stable by designsensitive 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

MetricCurrent Snapshot
total tests18
passing18
pass rate100%
tests per site3
sites covered6
scheduleweekly

The Three Tests Per Site

TestTagWhat Is Compared
homepage above fold@visual @criticalabove-fold viewport of homepage
header component@visual @componentheader element (selector per site)
footer component@visual @componentfooter 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 ContentWhy
consent overlays (CPEX, Didomi)storageState prevents them, but belt-and-suspenders
ad containers and iframesad delivery varies per run
timestamps and view counterschange every minute
live tickers and breaking news bannerschange every minute
all images, pictures, SVGsnews images rotate constantly
all text contentheadlines, bylines, article text rotate constantly
video players and canvasesplayback state varies
animations and transitionsdisabled 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.

TestmaxDiffPixelsmaxDiffPixelRatiothreshold
homepage above fold5,0000.05 (5%)0.30
header component2,0000.03 (3%)0.25
footer component3,0000.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.

PathContents
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.png
  • blesk-header-visual-darwin.png
  • blesk-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.

SiteHeader SelectorFooter Selector
Bleskdiv.navigation__wrapperfooter#footer, footer.footer-2024
Autodiv.header-wrapperfooter
E15div.headerfooter > div.footer-wrapper, footer
Reflexheader, .header-wrapperfooter
iSportdiv.navigation__wrapper, headerfooter#footer, footer
Opiniodiv[class="header"], [class="Header"]div.g-ui-footer, footer

These selectors are production-verified and stored in the spec file.

How To Run

CommandWhat It Does
npm run test:visualAll 18 tests across 6 sites
SITE=blesk npm run test:visualBlesk only (3 tests)
npx playwright test --update-snapshots --project=visualUpdate all baselines
SITE=blesk npx playwright test --update-snapshots --project=visualUpdate 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.

SituationAction
deliberate site redesign or header/footer updateupdate snapshots after verifying the new layout is correct
new nav item addedupdate snapshots
logo or brand changeupdate snapshots
CI platform changed (macOS → Linux)regenerate all baselines on the new platform
test fails in CI but looks correct in local reviewcheck 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 PatternLikely Cause
header element missing entirelyselector broke or header removed from DOM
footer grid collapsed to single columnCSS regression
navigation shifted 50+ pixels downsticky header CSS changed
entire above-fold viewport is blankpage failed to load properly
diff concentrated in one componentthat component's layout changed

Infrastructure Design Decisions

DecisionReason
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 testfull-page screenshots amplify content rotation diffs
footer clipped to 600px heightdynamic 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
NeedGo To
functional homepage testsSmoke Tests
high-level suite listTest Types