Vitest Plugin
The @pxdiff/vitest package integrates pxdiff into Vitest Browser Mode tests. Take screenshots during component tests and get instant diff results against baselines.
Installation
Section titled “Installation”npm install --save-dev @pxdiff/vitestPeer dependency: vitest >= 4.0.0
Vitest Browser Mode requires a browser provider. We recommend @vitest/browser-playwright:
npm install --save-dev @vitest/browser-playwright1. Configure Vitest
Section titled “1. Configure Vitest”Add the pxdiff plugin to your vitest.config.ts:
import { pxdiffPlugin } from "@pxdiff/vitest/plugin";import { playwright } from "@vitest/browser-playwright";import { defineConfig } from "vitest/config";
export default defineConfig({ plugins: [pxdiffPlugin()], test: { browser: { enabled: true, provider: playwright(), instances: [{ browser: "chromium" }], }, },});The plugin automatically registers the toMatchPxdiff matcher and the browser commands needed for screenshot upload — no manual setup files required.
For TypeScript support, add the type augmentation to your tsconfig.json:
{ "compilerOptions": { "types": ["@pxdiff/vitest/types"] }}2. Set Environment Variables
Section titled “2. Set Environment Variables”export PXDIFF_API_KEY=pxd_your_key_hereThat’s it. No global setup file, no fixture boilerplate.
Use the toMatchPxdiff matcher on page (from vitest/browser) or any Locator:
import { expect, it } from "vitest";import { page } from "vitest/browser";import { render } from "vitest-browser-react";
it("button visual regression", async () => { await render(<Button variant="primary">Click me</Button>);
// Full-page screenshot await expect(page).toMatchPxdiff("button-primary");});Component Screenshots
Section titled “Component Screenshots”it("card renders correctly", async () => { const screen = await render(<Card title="Hello" />);
// Screenshot the full page (includes component in context) await expect(page).toMatchPxdiff("card-default", { path: ["components", "Card"], });});Ignoring Dynamic Content
Section titled “Ignoring Dynamic Content”await expect(page).toMatchPxdiff("dashboard", { ignoreSelectors: [".timestamp", ".random-avatar"],});Elements with data-pxdiff="ignore" or data-chromatic="ignore" are always hidden automatically:
<span data-pxdiff="ignore">Dynamic content here</span>Tolerance Threshold
Section titled “Tolerance Threshold”await expect(page).toMatchPxdiff("chart", { maxDiffPixelRatio: 0.01, // Allow up to 1% pixel difference});Display Hierarchy
Section titled “Display Hierarchy”Use path to organize screenshots into a tree in the review UI:
await expect(page).toMatchPxdiff("button-hover", { path: ["components", "Button"],});pxdiffPlugin(options?)
Section titled “pxdiffPlugin(options?)”Vite plugin that configures pxdiff for Vitest Browser Mode.
| Option | Type | Default | Description |
|---|---|---|---|
suite | string | "vitest" | Suite name for grouping snapshots |
blocking | boolean | true | Whether changed snapshots fail the test |
apiUrl | string | PXDIFF_API_URL or "https://pxdiff.com" | API URL |
git.branch | string | (auto-detected) | Git branch override |
git.commit | string | (auto-detected) | Git commit override |
local | boolean | (auto-detected) | Local mode (from PXDIFF_LOCAL or absence of CI) |
autoApprove | boolean | (auto-detected) | From PXDIFF_AUTO_APPROVE |
toMatchPxdiff(name, options?)
Section titled “toMatchPxdiff(name, options?)”Custom matcher for visual regression assertions. Works on any object with a .screenshot() method — page and Locator instances from vitest/browser.
await expect(page).toMatchPxdiff("snapshot-name", options);| Option | Type | Default | Description |
|---|---|---|---|
blocking | boolean | (from plugin) | Override blocking mode for this snapshot |
ignoreSelectors | string[] | CSS selectors to hide via visibility: hidden | |
maxDiffPixelRatio | number | Max acceptable diff ratio (0–1). Pass if below this | |
path | string[] | Display hierarchy path for tree grouping in review UI |
Pass/Fail Logic
Section titled “Pass/Fail Logic”The matcher determines pass/fail as follows:
- Pass: unchanged, new, auto-approved, within
maxDiffPixelRatio, non-blocking mode, or CI mode (soft-fail) - Fail: changed snapshots in blocking mode
In CI mode (when PXDIFF_SESSION_ID is set and not local), the matcher always passes. The pxdiff GitHub check run reports the overall result instead.
CI Integration
Section titled “CI Integration”With pxdiff run
Section titled “With pxdiff run”The recommended approach for CI is to wrap your Vitest tests with pxdiff run:
- name: Visual Regression run: pxdiff run -- npx vitest run env: PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}This creates a GitHub check run, groups all screenshots into one session, and reports results back to the PR.
Standalone
Section titled “Standalone”You can also run Vitest tests without pxdiff run. Screenshots are still uploaded and diffed individually:
- name: Visual Tests run: npx vitest run env: PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}Framework Integration
Section titled “Framework Integration”React (via vitest-browser-react)
Section titled “React (via vitest-browser-react)”import { pxdiffPlugin } from "@pxdiff/vitest/plugin";import react from "@vitejs/plugin-react";import { playwright } from "@vitest/browser-playwright";import { defineConfig } from "vitest/config";
export default defineConfig({ plugins: [react(), pxdiffPlugin()], test: { browser: { enabled: true, provider: playwright(), instances: [{ browser: "chromium" }], }, },});import { expect, it } from "vitest";import { page } from "vitest/browser";import { render } from "vitest-browser-react";
it("renders correctly", async () => { await render(<MyComponent />); await expect(page).toMatchPxdiff("my-component");});With Tailwind CSS
Section titled “With Tailwind CSS”If your components use Tailwind, add the Tailwind Vite plugin:
import { pxdiffPlugin } from "@pxdiff/vitest/plugin";import tailwindcss from "@tailwindcss/vite";import react from "@vitejs/plugin-react";import { playwright } from "@vitest/browser-playwright";import { defineConfig } from "vitest/config";
export default defineConfig({ plugins: [tailwindcss(), react(), pxdiffPlugin()], test: { browser: { enabled: true, provider: playwright(), instances: [{ browser: "chromium" }], }, },});Environment Variables
Section titled “Environment Variables”| Variable | Description |
|---|---|
PXDIFF_API_KEY | (required) API authentication key |
PXDIFF_API_URL | API base URL (default: https://pxdiff.com) |
PXDIFF_SESSION_ID | Session ID for grouping (set by pxdiff run or auto-generated) |
PXDIFF_LOCAL | Set to true for local development mode |
PXDIFF_AUTO_APPROVE | Set to true to auto-approve all changes |
PXDIFF_BRANCH | Override git branch detection |
PXDIFF_COMMIT | Override git commit detection |