How to Fix Flaky Visual Tests by Freezing Time and Randomness
Clocks, relative dates, and random data change every run, so freeze the time and seed randomness before capturing to make snapshots deterministic.
Use Playwright page.clock to pin the time and stub Math.random via an init script so date displays and randomized content render identically on every run.
Steps
- Install a fixed clock with
page.clock.setFixedTime. - Seed or stub
Math.randomviaaddInitScript. - Stub network responses that return random data.
- Regenerate baselines against the frozen state.
Test
feed.spec.ts
await page.clock.install({ time: new Date('2026-01-01T00:00:00Z') });
await page.addInitScript(() => {
let seed = 42;
Math.random = () => {
seed = (seed * 9301 + 49297) % 233280;
return seed / 233280;
};
});
await page.goto('/');
await expect(page).toHaveScreenshot('feed.png');Gotchas
- Install the clock and init script before navigation, or the page reads the real values first.
- Relative timestamps (e.g. "2 hours ago") still need a fixed clock to be stable.
Related guides
How to Mask Dynamic Regions in Visual TestsHide timestamps, ads, and avatars from visual comparisons with Playwright toHaveScreenshot mask, so genuinely…
How to Wait for Fonts and Network Idle Before a ScreenshotPrevent flaky visual diffs by waiting for document.fonts.ready and networkidle before capturing, so late font…