Published March 10, 2026
Visual regression tests only work when the baseline is stable. The moment a test pulls a real image from an external server, you introduce latency, potential 404s, and content that changes without warning. Deterministic placeholder fixtures give your test suite a foundation that never shifts — the same pixel grid, the same labels, the same file hash on every run.
A single changing image in a visual baseline can invalidate an entire screenshot comparison. Playwright, Cypress, and Percy all work by diffing pixels between a stored baseline and the current run. If the baseline was captured with one image and the current run loads a different one — even a visually similar one — the diff will flag it.
This creates a noise problem: engineers spend time triaging diffs that are not caused by code changes. Over time, teams start ignoring diffs or increasing the tolerance threshold until real regressions slip through. Deterministic fixtures eliminate this class of false positive entirely.
A deterministic fixture is any image file that is:
1. Committed to version control (not fetched at test time) 2. Generated from a stable, reproducible process 3. Named and sized to match the component it represents
Placeholder images satisfy all three conditions. You generate them once from a known configuration, commit the files, and reference them by path in your test setup. The pixel output is always identical because the generator is pure — same input produces same output every time.
Start by listing the image sizes your test suite uses. Open your test files or your component library and collect every unique width×height combination that an `<img>` tag, `background-image`, or `<Image>` component expects.
Paste the list into PlacePack — one size per line in the format `WxH` or `label:WxH`. Add a text template like `{label} {w}×{h}` so filenames are self-documenting. Download the ZIP, extract it into a `__fixtures__/` directory, and update your test setup to load images from there.
Most components have several visual states: default, loading, error, and success. Each state might use a different image with different sizing or coloring. Rather than maintaining multiple fixture directories, use per-item color overrides in PlacePack to encode state meaning into the image itself.
For example, use a neutral slate color for default states, amber for loading or warning states, and red for error states. When a Playwright screenshot shows a red placeholder, you immediately know which component state is being exercised without reading the test name.
Playwright test using fixture images
import { test, expect } from "@playwright/test";
test("card renders in error state", async ({ page }) => {
await page.goto("/card?state=error");
// image loaded from __fixtures__/card_error_320x180.png
await expect(page).toHaveScreenshot("card-error.png");
});Percy and Chromatic both compare rendered pages against stored snapshots. When those pages contain dynamic images, every deploy risks producing a new baseline. Switching to fixture images means the image layer of your baseline never changes unless you explicitly regenerate the fixtures.
To integrate, replace any dynamic image sources in your test environment with references to the fixture files. In a Next.js app you might do this with an environment variable that swaps the image base URL. In a React app using MSW you can intercept image requests and respond with the fixture blobs.
Treat placeholder fixtures like any other generated asset: check them into version control and review changes in pull requests. When a component's dimensions change, regenerate only the affected sizes, commit the updated files, and approve the new baseline in Percy or Chromatic.
Store the PlacePack share URL in your project documentation so any team member can reproduce or extend the fixture set without guessing the original configuration.
Ready to generate placeholder images?
Open the generator with the right preset pre-loaded and download your pack in seconds.