Skip to content
Latchkey

Visual regression: non-deterministic rendering (fonts, animations, dates) in CI

A screenshot is only stable if the page renders identically every run. Clocks, relative dates, animations, spinners, blinking carets, and randomized data all change the pixels without any code change, producing false diffs. Freeze them before capturing.

What this error means

Visual tests fail intermittently across tools (Playwright, jest-image-snapshot, Percy) with diffs on timestamps, a spinner frame, a moving carousel, or a text caret. Re-running produces a different result.

visual-regression
# diff clusters on:
#  - "Updated 2 minutes ago" text
#  - a loading spinner captured mid-rotation
#  - a blinking text caret in an input

Common causes

Time and dates rendered live

A visible clock or relative timestamp changes every run, so the captured pixels differ even though nothing in the code changed.

Animations, spinners, and carets not frozen

Anything in motion at capture time is caught at a different frame each run, and a blinking caret toggles on or off between captures.

How to fix it

Freeze time and disable motion

Pin the clock, disable CSS animations and transitions, and hide the caret before capturing.

tests/state.spec.ts
await page.clock.setFixedTime(new Date('2026-06-30T12:00:00Z'));
await page.addStyleTag({ content: '*{animation:none!important;transition:none!important;caret-color:transparent!important}' });

Seed random data and wait for readiness

Use a fixed random seed and wait for network idle and fonts before capture so the content is deterministic.

tests/state.spec.ts
await page.waitForLoadState('networkidle');
await page.evaluate(() => document.fonts.ready);

How to prevent it

  • Freeze the clock and seed randomness for every visual test.
  • Disable animations, transitions, and the caret at capture.
  • Wait for fonts and network idle before taking the screenshot.

Frequently asked questions

What causes "Non-deterministic rendering flakiness"?
A visible clock or relative timestamp changes every run, so the captured pixels differ even though nothing in the code changed.
How do I fix Non-deterministic rendering flakiness?
Pin the clock, disable CSS animations and transitions, and hide the caret before capturing.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card