Diagnose unstable captures

Inspect the observations, establish the cause, then make capture repeatable.

Open a snapshot in build review and expand Stability history. Difora compares retained current captures with the same name, branch, full commit SHA and complete recorded environment. Each observation links to its build and snapshot.

The diagnostic never changes review decisions, baselines, ignore regions, thresholds or CI exit codes. Variation does not establish that a change is harmless, and the suggested checks do not identify its cause automatically.

Record comparable settings

Use the capture metadata helpers available in client 0.10.1. Provide the renderer OS and a pinned environment identity. Keep the environment revision the same while its browser, fonts and rendering stack are unchanged; a container digest or versioned capture profile is useful. A CI execution ID belongs to the run, not the environment revision.

import { diforaScreenshot } from 'difora/playwright';

await diforaScreenshot(page, 'checkout', {
  dir: './screenshots',
  captureMetadata: {
    os: { name: 'Linux' },
    environment: {
      id: 'visual-ci',
      revision: 'renderer-and-fonts-v1', // Your pinned capture stack
    },
  },
});

The helper observes browser name/version, viewport, device scale, color scheme, locale and timezone, and records its producer and capture options. The diagnostic also requires full-page, animation, caret and mask-count settings. All recorded fields must match, including optional theme, variant, clip and OS version. Unrecorded settings are unknown; supplied metadata is not independently attested.

Upload the full Git commit SHA (40 or 64 hexadecimal characters); the CLI normally detects it. A short or missing SHA is insufficient for this diagnostic. Captures from other commits remain inspectable but do not establish instability at the selected commit.

Repeat fresh captures

Run the capture suite again at the same commit in the same pinned environment, starting with an empty screenshot directory. Upload each fresh suite as a separate build. Re-uploading saved PNGs does not test capture stability.

A comparison rerun processes existing images and adds no new observation. Parallel attempts sharing a run ID count once, using their newest eligible capture, because retries may inherit completed shards. Fresh captures within those retries are conservatively counted as one submitted run too.

Control time, random values and data

Inspect the linked images for changing application inputs. Use fixed fixture data and a seeded application random source where the behavior permits it. Keep genuine product differences visible. For a date display, Playwright can fix the clock before navigation:

await page.clock.setFixedTime(new Date('2026-09-01T09:00:00Z'));
await page.goto('/checkout');

For timer-dependent behavior, choose the appropriate Playwright clock controls. Use explicit network fixtures when testing a known response, and verify the page reached the intended state before capture.

Control motion and the caret

Difora's Playwright helper captures with animations: 'disabled' and caret: 'hide'. For screenshots captured outside the helper, configure equivalent screenshot options. Video, animated images and application-driven canvas updates may need their own stable test state.

Wait for the intended state

Wait for an application-specific ready condition and for required fonts and images. Avoid treating an arbitrary sleep as proof of readiness. Changing full-page dimensions can be a clue that content or layout is still settling. Confirm that clue in the observations before changing the test.

await expect(page.getByTestId('checkout-ready')).toBeVisible();
await page.evaluate(() => document.fonts.ready);
await expect(page.getByRole('img', { name: 'Product' })).toBeVisible();
// Also wait for the image's decoded content if it is loaded asynchronously.

Keep baselines and later captures in the same pinned rendering environment. Browser/platform differences can affect the pixels even when the application is unchanged. See Playwright visual comparisons.

What the evidence can tell you

The history contains up to 30 matching snapshots within the latest 100 retained builds on the selected branch, through the selected build. It shows exclusions and sample limits. Expired and deleted captures are unavailable. This is a recent sample, not an all-time score.

Outcome groups use exact decoded pixels and image dimensions, before review thresholds and ignore regions. Different PNG encoding and invisible RGB beneath fully transparent pixels do not create new outcomes. Small pixel differences may be below your comparison threshold. Different dimensions remain different outcomes.

Older images may lack derived pixel evidence. New metadata-bearing captures and an explicitly requested comparison rerun can compute it. A rerun still uses the original capture; it does not prove a fresh execution occurred. An unavailable computation is shown as missing evidence.

Read capture recipes, CI setup and comparison configuration for the surrounding workflow.