Reference

Storybook Adapter

Test your Storybook stories with ViSnap

The Storybook adapter lets you test individual stories from your Storybook v8+ build. It's the recommended way to use ViSnap for component testing.

Configuration

// visnap.config.ts|js
testCase: [
  {
    name: "@visnap/storybook-adapter",
    options: {
      source: "./storybook-static",
      // port: 4477,
      // include: "*",
      // exclude: "*-skip*",
      // discovery: { evalTimeoutMs: 10000, maxRetries: 2, retryDelayMs: 200 },
    },
  },
];

Options

Options are provided under adapters.testCase[i].options.

source

Type: string
Required: Yes

Path or URL to your Storybook build. Use a local directory like "./storybook-static" or a remote URL.

port

Type: number (>0)
Required: No

Port for the local static server when using a local build directory.

include

Type: string | string[]
Required: No

Patterns to include specific stories. Use wildcards like "*Button*" to test only stories with "Button" in the name.

exclude

Type: string | string[]
Required: No

Patterns to exclude stories from testing. Use "*-skip*" to skip stories with "skip" in their name.

Discovery Options

discovery.evalTimeoutMs

Type: number (>0)
Required: No

How long to wait when evaluating story metadata. Increase if stories are slow to load.

discovery.maxRetries

Type: number (>=0)
Required: No

Number of times to retry if story discovery fails.

discovery.retryDelayMs

Type: number (>=0)
Required: No

Wait time between discovery retries.

Story Configuration

Configure visual testing options directly in your stories:

export default {
  title: "Button",
  component: Button,
  parameters: {
    visualTesting: {
      skip: false, // Skip this story
      screenshotTarget: "#storybook-root", // Custom screenshot target
      threshold: 0.05, // Custom threshold for this story
      browser: ["chromium", "firefox"], // Specific browsers
      viewport: { width: 1200, height: 800 }, // Custom viewport
      disableCSSInjection: true, // Disable global CSS injection
      interactions: [
        // Execute interactions before screenshot
        { type: "click", selector: "button" },
        { type: "fill", selector: "input", text: "test" },
      ],
    },
  },
};

Story Parameters

skip

Skip this story entirely:

visualTesting: {
  skip: true
}

screenshotTarget

Specify which element to screenshot (default: "#storybook-root"):

visualTesting: {
  screenshotTarget: ".my-component"
}

threshold

Override the global threshold for this story:

visualTesting: {
  threshold: 0.05 // 5% difference threshold
}

browser

Test only specific browsers:

visualTesting: {
  browser: ["chromium", "firefox"] // test in both browsers
}

viewport

Use a custom viewport for this story:

visualTesting: {
  viewport: { width: 1200, height: 800 }
}

disableCSSInjection

Disable global CSS injection for this story:

visualTesting: {
  disableCSSInjection: true
}

interactions

Execute user interactions before taking the screenshot:

visualTesting: {
  interactions: [
    { type: "click", selector: "button.primary" },
    { type: "fill", selector: 'input[name="email"]', text: "test@example.com" },
    { type: "waitForTimeout", duration: 500 },
    { type: "hover", selector: ".tooltip-trigger" },
  ]
}

elementsToMask

Type: string[]
Required: No

Overlay specific elements with solid colors to hide dynamic content and stabilize tests.

visualTesting: {
  elementsToMask: [".timestamp", "#ad-slot", ".user-avatar"]
}

See Screenshot Stabilization for detailed examples and best practices.

Common Use Cases

Form Testing

Test form interactions by filling fields and submitting:

visualTesting: {
  interactions: [
    { type: "fill", selector: 'input[name="email"]', text: "test@example.com" },
    { type: "click", selector: 'button[type="submit"]' },
    { type: "waitForTimeout", duration: 1000 },
  ]
}

State Testing

Test different component states like hover or loading:

visualTesting: {
  interactions: [
    { type: "hover", selector: ".button" },
    { type: "click", selector: "button.load-data" },
    { type: "wait", selector: ".loading-spinner" },
  ]
}