Guides
Test any web page or application directly with the URL adapter - no Storybook required. This approach is perfect for testing marketing sites, landing pages, or web apps that don't use Storybook.
Prerequisites
- A running web application or accessible URLs
- ViSnap installed in your project
Installation
- Install ViSnap:
npm install -D @visnap/cli- Initialize configuration:
npx visnap init- Configure the URL adapter in
visnap.config.ts:
// visnap.config.ts
import { type VisualTestingToolConfig } from '@visnap/protocol';
const config: VisualTestingToolConfig = {
adapters: {
// Browser settings - how screenshots are captured
browser: {
name: "@visnap/playwright-adapter",
options: {
launch: { browser: 'chromium', headless: true },
context: { colorScheme: 'light', reducedMotion: 'reduce' },
}
},
// Test source - what URLs to test
testCase: [
{
name: "@visnap/url-adapter",
options: {
urls: [
{ id: "homepage", url: "http://localhost:3000/" },
{ id: "about", url: "http://localhost:3000/about" },
{ id: "pricing", url: "http://localhost:3000/pricing" },
],
}
}
]
}
};
export default config;- Start your application:
Before running visual tests, ensure the URLs you want to test are accessible.
- Create baseline screenshots:
npx visnap update- Run visual tests:
npx visnap test- Open report:
npx visnap openURL-Level Options
Each URL requires an id and url. Optional fields allow per-URL customization:
{
id: "homepage",
url: "http://localhost:3000/",
title: "Homepage", // Display name for reports
viewport: { width: 1200, height: 800 }, // Custom viewport
threshold: 0.05, // Custom threshold (0.0-1.0)
screenshotTarget: "body", // Custom screenshot target
elementsToMask: [".sticky", "#ad"], // Mask dynamic elements
disableCSSInjection: true, // Disable global CSS injection
interactions: [ // Execute before screenshot
// See Interactive Testing guide for examples
],
}Common options:
title: "Display Name"- Custom name in reportsviewport: { width: 375, height: 667 }- Mobile viewportthreshold: 0.01- More strict comparison (1% difference)screenshotTarget: ".hero"- Screenshot specific elementelementsToMask: [".dynamic"]- Hide elements that change frequentlydisableCSSInjection: true- Disable global CSS injectioninteractions: [...]- Execute actions before screenshot
Pattern Filtering
Use include/exclude to select URLs by id using minimatch patterns:
options: {
urls: [
{ id: "homepage", url: "http://localhost:3000/" },
{ id: "about", url: "http://localhost:3000/about" },
{ id: "pricing", url: "http://localhost:3000/pricing" },
{ id: "admin-dashboard", url: "http://localhost:3000/admin" },
],
include: ["homepage", "about", "pricing"], // Only test these
exclude: ["*admin*"], // Exclude admin pages
}Troubleshooting
URL not loading? Make sure your app is running and accessible:
curl http://localhost:3000/Screenshots not working? Check your screenshot target exists:
screenshotTarget: "body" // ensure this element existsNext Steps
- Interactive Testing - Test hover states and forms
- Screenshot Stabilization - Make tests more stable
- CI Integration - Run tests in your pipeline