percy-visual-regression-testing
Authors Percy visual snapshot tests via the @percy/cli + framework SDK (Playwright, Cypress, Selenium, Storybook), runs them with `percy exec -- <test command>`, configures viewports / masking / ignored regions, and reviews diffs in the Percy build UI. Use when the project ships visual regression coverage to BrowserStack Percy.
percy-visual-regression-testing
Overview
Percy is BrowserStack's visual testing platform. The integration shape is two-layered: the CLI (@percy/cli) plus a framework SDK (@percy/playwright, @percy/cypress, @percy/selenium, @percy/storybook, etc. - the Percy CLI README lists the available SDKs as Playwright, Cypress, Selenium, Storybook, Puppeteer, Appium, plus framework-specific wrappers like Ember, Gatsby, Jekyll, and a custom SDK option).
The CLI starts a local snapshot server, the SDK calls percySnapshot(page, name) from inside your tests, and the build appears in the Percy UI for baseline review.
When to use
If the project does not already use BrowserStack, evaluate chromatic-visual-regression-testing (Storybook-first) or playwright-snapshots (self-hosted) before adopting Percy.
Authoring snapshots
Install (Playwright example)
npm install --save-dev @percy/cli @percy/playwrightBoth packages are required: @percy/cli runs the local snapshot server, @percy/playwright exposes the percySnapshot function (percy-playwright).
Snapshot in a Playwright test
const { chromium } = require('playwright');
const percySnapshot = require('@percy/playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('http://example.com/', { waitUntil: 'networkidle2' });
await percySnapshot(page, 'Example Site');
await browser.close();
})();(Adapted from percy-playwright.)
Options to percySnapshot(page, name, options)
Per the percy-playwright README:
| Option | Effect |
|---|---|
percyCSS | CSS injected immediately before the screenshot. Use this to neutralize timestamps, ad slots, or animations. |
fullPage | Capture the entire scrollable page rather than the viewport. |
freezeAnimatedImage | Freeze animated images (GIF / APNG) so the diff is deterministic. |
ignoreRegionSelectors | CSS selectors whose bounding boxes are excluded from the diff. |
customIgnoreRegions | Coordinate-based exclusion zones for ad-hoc cases. |
Other SDKs (@percy/cypress, @percy/selenium, @percy/storybook) expose the same shape with framework-specific calling conventions - check the matching SDK README on github.com/percy.
Configuration file
The Percy CLI looks for config in this order (percy-config):
The first found wins, searched from CWD up to the home directory. Use this file to set project-wide defaults (viewports, percyCSS, network idle timeout). For the current schema of the snapshot block (widths array, minimum height, etc.), check the latest percy-cli release - the schema evolves with major versions and reproducing it from memory risks drift.
Running
The canonical invocation is percy exec -- <test command> (percy-exec):
export PERCY_TOKEN=<your project token>
percy exec -- npx playwright test
percy exec -- yarn cypress run
percy exec -- npx jestpercy exec starts a local snapshot server on port 5338 (configurable), proxies snapshot requests from the SDK during the test run, and finalizes the build when the wrapped command exits (percy-exec).
Useful percy exec flags
Per percy-exec:
| Flag | Purpose |
|---|---|
--parallel | Mark the build as part of a parallel CI matrix. |
--partial | Allow the build to be marked partial (e.g. early exit). |
-P, --port <n> | Override the local server port (default 5338). |
-d, --dry-run | Capture snapshots locally without uploading. |
-h, --allowed-hostname | Restrict asset discovery to specific hostnames. |
--disallowed-hostname | Inverse of allowed; useful for blocking analytics URLs. |
-t, --network-idle-timeout <ms> | Tune asset-discovery timing for slow apps. |
--debug | Verbose logging for troubleshooting. |
PERCY_TOKEN is the only required env var (percy-cli); the SDK no-ops when the token is absent (so tests stay green locally without a token).
Reviewing diffs
A successful Percy build appears in the Percy UI grouped by snapshot name; visual changes between commits appear as side-by-side diffs that require explicit approval before the build is marked passed. Percy also integrates with PR statuses so a build with unapproved changes shows as pending on the PR until a reviewer approves (percy-overview).
The newer "AI Agents" mode generates natural-language summaries of visual changes and reduces noise on cosmetically-irrelevant diffs (percy-overview); this is opt-in per project.
CI integration
The minimal pattern: install @percy/cli + the SDK, expose PERCY_TOKEN as a CI secret, wrap the test command in percy exec.
# .github/workflows/visual.yml
name: visual
on:
pull_request:
push:
branches: [main]
jobs:
percy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run Percy + Playwright
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
run: npx percy exec -- npx playwright testFor a parallel CI matrix (e.g. sharded Playwright tests), add --parallel to percy exec and use Percy's parallel-build coordinator (percy-exec).