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
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`. Use when the project ships self-hosted visual regression coverage in Playwright (no external snapshot service).
responsive-breakpoint-runner
Produces a single breakpoint-matrix report (rows = pages/stories, columns = viewports) across Percy, Chromatic, Playwright snapshots, or Storybook test-runner. Routes per-engine viewport syntax, runs each, and aggregates the results into one cross-breakpoint view. Use when the team needs one unified pass/fail view across three or more viewport widths instead of separate per-engine or per-breakpoint reports. The matrix-view output is the distinguishing trait: it dispatches to playwright-snapshots (and the other engines) rather than replacing any single-engine skill.
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 a markdown + JSON artifact for the CI step. Use this skill when the gate's input is pre-classified diff data and the enforcement concern is reviewer approval, not when the goal is fanning out to multiple engines (use a multi-engine CI orchestrator for that).
visual-diff-summarizer
Triages a PR's visual regression diffs when there are too many changed screenshots to review one by one. Clusters snapshots (from Percy, Chromatic, Playwright `toHaveScreenshot`, Storybook, Loki) by component / route, separates changes that match PR intent from cascade / regression suspects, recommends which baselines to update, and emits one PR comment pointing the reviewer at the screenshots that need actual eyes. Use when a PR has 20+ visual diffs / changed screenshots and the reviewer needs help deciding which to open.