visual-regression
Visual Regression Testing
Catch unintended UI changes by comparing screenshots across builds.
Playwright Visual Comparisons
Generate baseline screenshots
# Run visual tests and create baseline
npx playwright test --update-snapshots
# Run specific visual test file
npx playwright test visual.spec.ts --update-snapshots
Run comparisons
# Compare against baseline
npx playwright test visual.spec.ts
# With specific threshold (0 = exact, 0.2 = 20% tolerance)
# Set in test file: expect(page).toHaveScreenshot({ maxDiffPixelRatio: 0.01 })
Example test
// visual.spec.ts
import { test, expect } from '@playwright/test';
test('homepage visual', async ({ page }) => {
await page.goto('http://localhost:3000');
await expect(page).toHaveScreenshot('homepage.png', {
fullPage: true,
maxDiffPixelRatio: 0.01,
});
});
test('component visual', async ({ page }) => {
await page.goto('http://localhost:3000/components');
const card = page.locator('.card').first();
await expect(card).toHaveScreenshot('card-component.png');
});
test('responsive visual', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await page.goto('http://localhost:3000');
await expect(page).toHaveScreenshot('homepage-mobile.png', { fullPage: true });
});
Percy (Cloud Visual Testing)
# Install
npm install --save-dev @percy/cli @percy/playwright
# Run with Percy snapshots
npx percy exec -- npx playwright test
# Percy environment
export PERCY_TOKEN=your_token_here
Percy in test
import { percySnapshot } from '@percy/playwright';
test('homepage', async ({ page }) => {
await page.goto('http://localhost:3000');
await percySnapshot(page, 'Homepage');
});
Chromatic (Storybook Visual Testing)
# Install
npm install --save-dev chromatic
# Run visual tests against Storybook
npx chromatic --project-token=$CHROMATIC_TOKEN
# Accept all changes (after review)
npx chromatic --project-token=$CHROMATIC_TOKEN --auto-accept-changes
Manual Screenshot Comparison
# Take screenshots with Playwright CLI
npx playwright screenshot http://localhost:3000 before.png
# Make changes, then:
npx playwright screenshot http://localhost:3000 after.png
# Compare with ImageMagick
compare before.png after.png diff.png
identify -verbose diff.png | grep -i "mean"
Notes
- Snapshots are OS and browser-specific. Generate baselines in CI, not locally.
- Use
maxDiffPixelRationot exact match — antialiasing causes 1-pixel diffs across environments. - Percy/Chromatic handle cross-browser and responsive comparisons automatically but require cloud accounts.
- Visual tests are slow. Run them as a separate CI job, not with unit tests.
- Review visual diffs carefully — auto-approving defeats the purpose.
More from thinkfleetai/thinkfleet-engine
local-whisper
Local speech-to-text using OpenAI Whisper. Runs fully offline after model download. High quality transcription with multiple model sizes.
149flyio-cli-public
Use the Fly.io flyctl CLI for deploying and operating apps on Fly.io: deploys (local or remote builder), viewing status/logs, SSH/console, secrets/config, scaling, machines, volumes, and Fly Postgres (create/attach/manage databases). Use when asked to deploy to Fly.io, debug fly deploy/build/runtime failures, set up GitHub Actions deploys/previews, or safely manage Fly apps and Postgres.
24kagi-search
Web search using Kagi Search API. Use when you need to search the web for current information, facts, or references. Requires KAGI_API_KEY in the environment.
22feishu-bridge
Connect a Feishu (Lark) bot to ThinkFleet via WebSocket long-connection. No public server, domain, or ngrok required. Use when setting up Feishu/Lark as a messaging channel, troubleshooting the Feishu bridge, or managing the bridge service (start/stop/logs). Covers bot creation on Feishu Open Platform, credential setup, bridge startup, macOS launchd auto-restart, and group chat behavior tuning.
13bambu-local
Control Bambu Lab 3D printers locally via MQTT (no cloud). Supports A1, A1 Mini, P1P, P1S, X1C.
10voice-transcribe
Transcribe audio files using OpenAI's gpt-4o-mini-transcribe model with vocabulary hints and text replacements. Requires uv (https://docs.astral.sh/uv/).
10