Guide
Visual regression testing: what it is and how to set it up
Visual regression testing catches the changes your functional tests cannot see. This guide covers how it works, how to wire it into CI, how Percy approaches it and how the same workflow runs in Snapvisor.
What visual regression testing is
Visual regression testing captures a screenshot of your UI, compares it against an approved baseline, and flags every difference for a person to review. Intended changes get approved and become the new baseline; unintended ones get rejected before they merge.
It exists because functional tests assert behavior, not appearance. These are the failures it is built to surface:
- Layout shift. A CTA drifts out of place after an unrelated CSS change. Pixels move; tests stay green.
- Color regression. A token update repaints a primary button off-brand. No assertion ever checks the hue.
- Text overflow. A longer string clips inside a fixed button. Logic is fine — the label is unreadable.
How a visual regression workflow runs
- Capture. Your CI uploads screenshots from the Storybook stories, Playwright, Cypress or Puppeteer specs you already run.
- Compare. Each screenshot is diffed against the baseline, the last approved build on your base branch.
- Review. The result lands as a status check on the pull request. Approve the intended changes, reject the regressions.
- Update the baseline. Approving a change promotes it to the new baseline for that branch, so intended changes never need approving twice.
The very first build on a branch has nothing to compare against, so it becomes the baseline and is approved automatically. Run it on a base branch that already looks right.
Set it up with Snapvisor
The path from an empty project to a reviewed build is four steps. The getting started guide has the full version.
- Create a project and copy its token. Sign up, create a project, and copy its project token (
ARGOS_TOKEN) from the project settings. Store it as a CI secret, never in the repository. - Install the SDK for your test runner.
npm install --save-dev @snapvisor/cli @snapvisor/playwright - Register the reporter and capture screenshots. The Playwright reporter uploads the screenshots when the run finishes.
// playwright.config.ts import { defineConfig } from "@playwright/test"; import { createArgosReporterOptions } from "@snapvisor/playwright/reporter"; export default defineConfig({ reporter: [ process.env.CI ? ["dot"] : ["list"], [ "@snapvisor/playwright/reporter", createArgosReporterOptions({ uploadToArgos: !!process.env.CI }), ], ], });// tests/example.spec.ts import { test } from "@playwright/test"; import { argosScreenshot } from "@snapvisor/playwright"; test("screenshot homepage", async ({ page }) => { await page.goto("http://localhost:3000"); await argosScreenshot(page, "homepage"); }); - Run it in CI. No wrapper command is needed; the token comes from the environment.
- run: npm run build - run: npx playwright test # captures via argosScreenshot, uploads via the reporter env: ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
Snapvisor Free includes 7,000 screenshots a month with no card to start. Pro starts at $9/month with 15,000 included; see pricing.
Keep the screenshots trustworthy
- Stable captures.
argosScreenshotstabilizes the page before it captures: it waits for web fonts, images andaria-busyregions to settle, hides carets and scrollbars and normalizes font anti-aliasing. - Browsers and sizes. To cover Chromium, Firefox and WebKit, run them as Playwright projects. Pass
viewportson a capture for each size you care about. - Flaky changes. Reviewers can mark a recurring change as ignored, and Snapvisor can auto-ignore changes that keep reappearing. See flaky test detection.
- Big suites. Shard screenshot uploads across CI jobs and review them as one build. See parallel testing.
Visual regression testing with Percy
Percy is BrowserStack's visual testing product. These are the parts of its workflow that matter when you set up or compare tools, each from Percy's public documentation (checked 2026-10-11, sources below):
- Capture. Percy captures a snapshot of the DOM within the test browser and sends it to Percy's API to be rendered across browsers and widths. Screenshots are taken in Percy's infrastructure, not inside your test suite. The default
widthsare 375 and 1280 pixels. - CI. You set the
PERCY_TOKENenvironment variable in your CI service and wrap the test command withpercy exec, for examplepercy exec -- node test.js. - Baseline. A build on the main branch is compared against the previous build on that branch; a pull request build is compared against the merge base, the common ancestor commit of your branch and the target branch. With no base build, every snapshot is marked as new, and the first build has no visual comparisons.
- Review. You can approve a whole build, groups of matching visual changes, or individual snapshots, and approved snapshots keep their approval across builds on the branch. A snapshot that is not ready can be sent back with a request for changes.
The same workflow in Snapvisor
The loop is the same: capture, compare against a baseline, review, approve. The differences are in how each stage is done.
- Capture. Percy sends a DOM snapshot and renders it; Snapvisor takes a real screenshot in the browser your test is already running in with
argosScreenshot, and your pipeline uploads the images. - Browsers and widths. Percy renders them for you; with Snapvisor you ask for them:
viewportson each call and one Playwright project per browser engine. - CI.
PERCY_TOKENandpercy execbecomeARGOS_TOKENwith no wrapper. On GitHub Actions you can skip the token with tokenless authentication. - Baseline. Snapvisor diffs against the last approved build on your base branch, found by walking your Git history to the first ancestor commit that has an approved build. See baseline builds.
- Review. Changes land as a status check on the pull request, and you approve or reject them in the review UI. Approving promotes the change to the baseline for that branch.
For plans, free tiers, browser coverage and AI-agent access side by side, read Snapvisor vs Percy.
Moving from Percy
You keep your test runner and your CI. What changes is the snapshot call, the token and where baselines live.
- Replace each
percySnapshotcall with its Snapvisor equivalent (argosScreenshoton Playwright and Cypress, or@snapvisor/storybookfor Storybook). - Swap
PERCY_TOKENforARGOS_TOKENand removepercy execfrom your CI scripts. - Run the first Snapvisor build on a base branch that is visually correct. Percy baselines cannot be imported, so that build becomes the new baseline.
- Require the Snapvisor check in branch protection and take the Percy check out of the required checks.
The full mapping, with Playwright, Cypress and Storybook examples, is in Migrate from Percy.
Comparing other tools
Frequently asked questions
Visual regression testing captures screenshots of your UI, compares each one against an approved baseline, and flags the differences for a person to review, so unintended visual changes are caught before they ship.
Functional tests assert behavior. A layout shift, an off-brand color or a clipped label can leave every one of them green, because no assertion checks how the page looks. Visual regression tests compare the rendered result.
No. Point Snapvisor at your existing Storybook, Playwright, Cypress or Puppeteer suite using the @snapvisor SDKs and it captures screenshots from the stories and pages you already have.
Percy's documentation says it captures a snapshot of the DOM within the test browser and sends it to Percy's API to be rendered across browsers and widths, so screenshots are taken in Percy's infrastructure rather than in your test suite. Snapvisor takes the screenshot in the browser your own test is running in.
You keep your test runner and your CI. You swap the snapshot call (percySnapshot becomes argosScreenshot), use ARGOS_TOKEN instead of PERCY_TOKEN and drop percy exec. Percy baselines do not carry over: your first Snapvisor build on your base branch becomes the new baseline.
Snapvisor Free includes 7,000 screenshots a month. Pro starts at $9/month with 15,000 included, then usage-based, with a 14-day trial.