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.
Install with skills.sh (any agent)
npx skills add testland/qa --skill percy-visual-regression-testingpercy-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 (opens in new window) 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 (opens in new window)).
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 (opens in new window).)
Options to percySnapshot(page, name, options)
Per the percy-playwright README (opens in new window):
| 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 (opens in new window)):
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 (opens in new window) 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 (opens in new window)):
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 (opens in new window)).
Useful percy exec flags
Per percy-exec (opens in new window):
| 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 (opens in new window)); 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 (opens in new window)).
The newer "AI Agents" mode generates natural-language summaries of visual changes and reduces noise on cosmetically-irrelevant diffs (percy-overview (opens in new window)); 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 (opens in new window)).
References
Related skills
chart-render-tests
Chart-render regression testing across the three chart-library families - Canvas (Chart.js: locator screenshot snapshot + `canvas.toDataURL()` diff with animations disabled), SVG (D3: `outerHTML` structural snapshot with generated-ID normalization + per-element data-binding tests), and declarative specs (Vega / Vega-Lite: JSON Schema validation + Vega-Lite → Vega compile test). Detects the family from package.json imports (chart.js / d3 / vega-lite), then applies the matching recipe; full per-library depth with citations in references/chartjs.md, references/d3.md, references/vega.md. Use when a dashboard or data product renders charts and their output needs regression coverage - before a chart-library major upgrade, after a theming change, or when runtime-generated Vega specs must be proven valid before render.
chromatic-visual-regression-testing
Authors and runs Chromatic visual tests on Storybook, Playwright, or Cypress projects via the `chromatic` CLI; configures baselines, TurboSnap, UI Review, and CI gating; reads exit codes for change-vs-error classification. Use when the project ships visual regression coverage to Chromatic Cloud.
playwright-snapshots
Authors Playwright `expect(page).toHaveScreenshot()` assertions, configures masks / clips / threshold / maxDiffPixels per test, manages the per-OS / per-browser snapshot directory, and runs the update flow with `--update-snapshots`; references/ carry the responsive-breakpoint viewport matrix (one project per breakpoint, cross-breakpoint matrix report, plus Chromatic / Percy / Storybook test-runner viewport syntax). Use when the project ships self-hosted visual regression coverage in Playwright (no external snapshot service), or needs a unified multi-viewport breakpoint matrix.
storybook-visual-regression-testing
Sets up visual regression coverage for a Storybook project - either via the official @chromatic-com/storybook addon (hosted) or via @storybook/test-runner with a postVisit hook that calls Playwright's toHaveScreenshot (self-hosted). Covers test-runner install, lifecycle hooks (setup / preVisit / postVisit), and CI integration. Use when a repo already has a working `.storybook/` config and the team wants per-story visual coverage rather than page-level snapshots.
visual-baseline-conventions
Reference catalog for visual regression coverage decisions - which Storybook stories or pages get baselines, how to choose breakpoints, when to mask vs adjust threshold, when to add or remove a baseline, and a decision matrix for picking among Percy / Chromatic / Playwright / Storybook test-runner. Use when designing visual coverage for a new project or auditing an existing baseline set.
visual-baseline-gate
Consumes pre-classified visual-diff JSON and a reviewer-signed acceptance log to produce a single go/no-go CI verdict for visual regression. Blocks when intentional baseline changes lack a non-author reviewer sign-off or when regressions are present, and emits the binding gate artifacts - visual-gate.json + visual-gate.md - with fail-closed handling of a missing classifier run and author-cannot-self-approve enforcement, so the pipeline can exit non-zero on BLOCK. Use when the gate's input is pre-classified diff data and the enforcement concern is reviewer approval and a binding CI verdict.