ScreenshotNeo

BlogHow-to

How to Visually Test Vue.js Components with Storybook

Build a Vue Storybook visual regression workflow: choose useful component states, compare screenshots with baselines, review diffs, and add interaction tests where needed.

By the ScreenshotNeo team4 October 20268 min read

To visually test Vue.js components with Storybook, create stories for the component states that matter, capture those stories as images, and compare each run with an accepted baseline. Review every difference: accept intentional design changes as the new baseline, or fix unexpected changes and run the check again. A visual diff checks appearance; it does not prove that interactions or application behavior work.

What Storybook visual testing checks

A visual test renders a story and compares its image with an earlier capture. It can surface visible changes in layout, color, size, contrast, and other appearance details. The story is the test case, so the quality of the check depends on whether your stories cover the states your team cares about.

For example, a button might need stories for its default, disabled, loading, and destructive states. A dialog might need open and validation-error states. Include realistic content and relevant prop combinations, especially where text length, optional icons, or empty values can affect layout.

Visual tests answer “does this rendered state still look as expected?” They do not establish that a button submits a form, that a dialog closes on Escape, or that an error message appears at the right time. Use interaction tests for those questions.

Set up Storybook for Vue 3 with Vite

Storybook’s documented Vue 3 and Vite integration lists Vue 3 and Vite 5 or later as requirements. In the project directory, run:

npm create storybook@latest

Follow the setup prompts, then start Storybook:

npm run storybook

These commands and compatibility details can change. If your Vue project uses another build tool or framework combination, check the current Storybook Vue 3 and Vite framework documentation for the matching setup.

Make stories that cover meaningful component states

Stories are the visual test cases. Start with the states a user can encounter and the variations most likely to affect appearance. Keep each story focused so a difference is easy to interpret.

A minimal Vue component and story can look like this:

// src/components/StatusButton.vue
<script setup>
defineProps({
  label: { type: String, required: true },
  disabled: { type: Boolean, default: false },
  variant: { type: String, default: 'primary' },
})
</script>

<template>
  <button :class="['status-button', `status-button--${variant}`]" :disabled="disabled">
    {{ label }}
  </button>
</template>
// src/components/StatusButton.stories.js
import StatusButton from './StatusButton.vue'

export default {
  title: 'Components/StatusButton',
  component: StatusButton,
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'danger'],
    },
  },
}

export const Primary = {
  args: {
    label: 'Save changes',
    variant: 'primary',
    disabled: false,
  },
}

export const Disabled = {
  args: {
    label: 'Save changes',
    variant: 'primary',
    disabled: true,
  },
}

export const Destructive = {
  args: {
    label: 'Delete account',
    variant: 'danger',
    disabled: false,
  },
}

Adapt the component and story syntax to your project’s conventions. For a form control, include representative values such as empty, populated, invalid, and disabled. For a responsive component, plan how each relevant viewport is represented and captured by your chosen visual-testing setup.

Story coverage checklist

  • Include the default state and meaningful prop variations.
  • Represent empty, long, or unusual content where it can change layout.
  • Include loading, disabled, error, and success states when the component supports them.
  • Keep stories deterministic: avoid data or time-dependent content that changes between runs.
  • Give stories clear names so reviewers can identify the changed state.

Compare stories against visual baselines

Storybook’s visual-testing workflow captures story images and compares them with prior baselines. The first run establishes the baseline. Later runs report differences for review. A visual change is a signal to investigate, not an automatic verdict that the change is a bug.

  1. Open the Storybook visual-testing workflow and run the stories you want to check.
  2. On the first run, establish the baseline for each covered state.
  3. After a component or style change, run the visual check again.
  4. Inspect each reported difference in context. Decide whether the appearance change was intended.
  5. Accept intentional design updates as the new baseline. If a difference is unexpected, fix the component or story and rerun the check.

For a hosted workflow, Storybook documents Chromatic visual testing and the @chromatic-com/storybook addon. The documented setup uses npx storybook@latest add @chromatic-com/storybook, then asks you to sign in to Chromatic, select or create a project, and link it to the addon. Confirm the current instructions before setup because commands and service details can change.

npx storybook@latest add @chromatic-com/storybook

Storybook documents a chromatic.config.json configuration file with options including projectId, optional buildScriptName, debug, and zip. Use the current integration documentation for the accepted values and configuration syntax; do not copy an old project identifier or assume an option’s default.

For team automation, configure the CI environment with the authentication and project token required by the current service instructions. Storybook describes pull or merge request checks that notify a team about test errors or UI changes. Check current provider-specific setup and plan behavior directly before relying on it.

Choose the test that answers your question

Test type What it observes What you maintain How to interpret a result
Visual test Rendered appearance as an image Representative stories and accepted image baselines Review differences; accept intended changes or investigate unexpected ones
Interaction test Behavior after simulated user actions Actions and assertions, often in a story’s play function Assertions indicate whether the expected behavior occurred
Snapshot test Rendered DOM or HTML output Markup snapshots Review markup changes; snapshots can be noisy to maintain
Accessibility check Accessibility issues covered by the configured checks Accessible markup and any applicable test configuration Use findings alongside appearance and behavior checks

Storybook interaction tests can use a story’s play function to simulate actions and assert outcomes, with the Vitest addon or test-runner. Keep those checks alongside visual tests when both appearance and behavior matter. Accessibility checks are complementary; they do not replace either kind of test.

// Example shape for an interaction story; adapt imports to your setup.
export const CanSubmit = {
  args: { label: 'Save changes' },
  play: async ({ canvas, userEvent }) => {
    const button = canvas.getByRole('button', { name: 'Save changes' })
    await userEvent.click(button)
    // Add an assertion for the expected visible or application outcome.
  },
}

Use the interaction testing APIs supported by the addon or test-runner version in your project. A click without an outcome assertion does not verify the behavior you intend to protect.

Keep visual checks reliable and useful

Control sources of variation

Dynamic dates, random values, remote content, animations, and fonts that load inconsistently can make captures differ even when the component code has not meaningfully changed. Use fixed story data, stable asset sources, and predictable component state. Where your visual-testing tool offers controls for animations or rendering, follow its documentation and apply them consistently.

Make every difference reviewable

Small, focused stories make it easier to identify the cause of a change. When a diff appears, check the story’s props and content first, then inspect shared styles, fonts, assets, and layout rules. If a story no longer represents a state the product supports, update or remove it deliberately rather than repeatedly accepting a misleading baseline.

Balance coverage with maintenance

More stories can cover more combinations, but each story and baseline needs to remain meaningful as the component evolves. Prioritize states with distinct appearances or higher user impact. Avoid generating every possible prop combination when many combinations render identically; add cases that protect a real visual distinction.

Performance, reliability, and cost

The workflow adds image capture and comparison work for the stories you choose to cover. The dossier does not establish a benchmark for run time, a cost advantage, or a coverage percentage, so plan capacity using your own story count, CI setup, and current service documentation. A focused set of representative states helps keep review work manageable.

Reliability depends on repeatable rendering and deliberate baseline review. Treat an unexplained diff as unresolved until someone identifies its cause. For hosted testing, account setup, project configuration, credentials, and any service limits are specific to the provider and may change; verify them before making them part of a release process.

Troubleshooting

Symptom Likely cause What to do
Storybook does not start after setup Framework or build-tool requirements do not match the documented Vue 3 and Vite integration, or setup did not complete. Read the current framework setup for your Vue and build-tool combination, then rerun the documented setup steps.
A story appears in Storybook but is absent from visual results The story may not be included in the selected visual-testing run or project configuration. Check the current integration’s story selection and build configuration; confirm that the story is included in the run.
Many differences appear on every run Story output may depend on time, random data, remote content, fonts, or animation. Make inputs and assets deterministic, then rerun and review whether the baseline still represents the intended appearance.
A baseline changed but the UI looks correct The visual change may be intentional, such as a design update. Review the affected story and accept the new baseline only after confirming the change is intended.
The image matches but a control does not work Visual checks assess rendered appearance, not user behavior. Add or update an interaction test that performs the action and asserts its outcome.
Chromatic setup asks for project credentials or fails to link The account, project, token, or addon configuration may be incomplete or outdated. Follow the current Chromatic and Storybook integration setup and keep credentials in the CI environment as instructed.

Or skip the browser setup

If you need a screenshot of a rendered page or component demo without managing capture infrastructure, ScreenshotNeo is a website screenshot API and MCP server. For a publicly accessible Storybook URL, make one request:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Replace the example target with your deployed Storybook URL. See the ScreenshotNeo API documentation for request options. ScreenshotNeo can accept cookie and consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, failed loads, timeouts, and cache hits cost nothing, and responses include X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for 1,000 free screenshots a month with no card.

FAQ

Does a visual regression test replace unit tests?

No. It checks rendered appearance. Use unit or interaction tests for logic and behavior that an image comparison cannot establish.

Should every prop combination get its own story?

No. Add stories for states and combinations that create meaningful visual differences or protect important user-facing states.

Can I use Storybook visual tests without Chromatic?

Storybook documents Chromatic as its cloud visual-testing integration. The appropriate alternative depends on your capture and comparison setup; verify the current Storybook documentation for available options.

When should I accept a changed baseline?

After reviewing the affected state and confirming the visual change is intentional. Acceptance records the new expected appearance; it does not establish that related behavior is correct.

Sources