Skip to main content
Version: v1.0.0

Getting Started with @qs/design-tests

Status: Stable

This guide walks you through setting up visual regression testing for your project using @qs/design-tests.

Installation​

Install the package as a dev dependency:

pnpm add -D @qs/design-tests

Configuration​

Create a .designTests.js file in your project root:

module.exports = {
projects: {
myapp: {
key: "myapp",
name: "My Application",
url: "http://localhost:6006", // Your Storybook or application URL

// Optional: Test specific pages (for non-Storybook projects)
pages: [
{ name: "Homepage", path: "/en/" },
{ name: "About", path: "/en/about" },
],

// Optional: Filter which stories to test
ignoreList: ["components/internal/*"],
}
},

viewports: [
{ name: "mobile", width: 375, height: 812 },
{ name: "tablet", width: 768, height: 1024 },
{ name: "desktop", width: 1440, height: 900 },
],

stability: {
strategy: "advanced",
waitForNetworkIdle: true,
waitBeforeScreenshot: 1000,
},
};

Check the configuration before the first run. The command validates it against the schema and prints what it resolves to, without launching a browser:

pnpm exec design-tests config --config .designTests.js

First Run​

Run the tests for the first time:

pnpm exec design-tests run --config .designTests.js --all

No baseline exists yet, so the run reports every test as NEW and writes its screenshot to the actual directory (design-tests/actual-images by default). The run prints the platform it captured on, and the report shows every new image:

🖥️  Capture platform: linux-x64, Chromium 112.0.5615.29, Playwright 1.32.3, Node v24.0.0
BASELINE.json records no capture platform yet; `design-tests baseline-update` writes it.
...
📸 🌱 NEW! [#1/150] mobile pages/homepage "Homepage" (2314ms)
...
✅ Tests complete: 0 passed, 150 new (4m 12s)
🚪 Exit 0 (report-only mode: 0 once the report is written, 2 on an empty run; pass --fail-on-changes to exit 1 on visual diffs)

Create the Baseline​

Review the images in the report (design-tests/report/index.html), then promote them:

pnpm exec design-tests baseline-update --config .designTests.js

This copies every NEW screenshot into the baseline directory and writes BASELINE.json beside them, recording the deployment reference and the capture platform. Commit both:

git add design-tests/baseline-images/
git commit -m "Add design tests baseline"
git push

Subsequent Runs​

On subsequent runs, the tests compare against the baseline:

pnpm exec design-tests run --config .designTests.js --all

If everything matches:

✅ Tests complete: 150 passed (4m 08s)

If there are visual changes:

🔍 Tests complete: 138 passed, 12 diffs (4m 10s)

🔗 Non-Passed Test URLs:

🔄 Changed:
[MYAPP] pages/homepage "Homepage" (desktop) [2.34% diff] - http://localhost:6006/iframe.html?id=pages-homepage--homepage&viewMode=story

Review the HTML report at design-tests/report/index.html to see the differences. When they are intended, design-tests baseline-update promotes them; see Baseline Management.

Baselines are platform-sensitive: font rendering and anti-aliasing differ between macOS, Windows and Linux. Capture baselines on the platform your CI runs on — for Linux CI, in a Linux container:

# Add docker-compose.yml to your project
# Run tests in Docker
docker compose run --rm design-tests

BASELINE.json records the platform the baseline was captured on. A later run on another platform warns at the top of its log, and baseline-update refuses to promote such a run unless --allow-platform-change is passed.

Next Steps​

Common Issues​

Tests fail immediately​

Make sure your application URL is accessible from where the tests run:

curl -I http://localhost:6006

Every test reporting FAIL with HTTP 404 or a connection error points at the configured url: check it before the page.

Baseline images differ between local and CI​

The run prints ⚠️ Capture platform differs from the baseline when this is the cause. Capture baselines in the container CI uses:

docker compose run --rm design-tests

An override does not apply​

design-tests config lists every override that reached the configuration and names variables that start with DESIGN_TESTS_ but set nothing — DESIGN_TESTS_PLAYWRIGHT_WORKERS with one underscore, for example.

Too many screenshots​

Use ignoreList to exclude stories you don't want to test:

projects: {
myapp: {
ignoreList: [
"internal/*",
"examples/*",
"deprecated/*"
]
}
}