Component Testing Storybook
Use Storybook as a component workshop and optional test runner — stories as living specs, interaction tests, and a11y checks.
- testing
- component-testing
Storybook isolates UI components with controls and stories. Teams use it for design review, documentation, visual regression, and — increasingly — interaction tests that run in CI without a full app shell.
Docs: Storybook, Interaction testing, Test runner.
Stories as executable examples
// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
args: { children: 'Save' },
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: { variant: 'primary' },
};
export const Disabled: Story = {
args: { disabled: true },
};
Each story is a known state: empty, loading, error, long text, RTL — the same states you’d unit-test.
Interaction tests (play functions)
import { expect, fn, userEvent, within } from 'storybook/test';
export const Submits: Story = {
args: { onClick: fn() },
play: async ({ canvasElement, args }) => {
const canvas = within(canvasElement);
await userEvent.click(canvas.getByRole('button', { name: /save/i }));
await expect(args.onClick).toHaveBeenCalled();
},
};
These run in a real browser via Storybook test runner or Vitest browser mode integrations — closer to user behavior than shallow unit tests.
What Storybook is good at
| Strength | Why |
|---|---|
| Hard-to-reach states | Force error props without backend |
| Design system QA | Matrix of variants |
| A11y addon | axe on stories |
| Visual regression | Chromatic / Loki / Playwright screenshots |
| Docs | Args table + MDX |
What it is not
- Full routing, auth, and multi-page flows — use E2E.
- Business logic pure functions — unit test without Storybook overhead.
- A substitute for Testing Library in package unit tests when you don’t want SB tooling.
Many teams use both: Testing Library for CI-fast logic/UI, Storybook for catalog + visual + some interactions.
Composition with MSW
// preview or story parameters
parameters: {
msw: {
handlers: [http.get('/api/user', () => HttpResponse.json(user))],
},
}
Stories that fetch can stay deterministic — MSW.
CI sketch
# build static storybook + run test-runner
npm run build-storybook
npx test-storybook --url http://127.0.0.1:6006
Or Storybook’s Vitest integration depending on version.
Footguns
- Stories that only render happy path.
- Heavy app providers required for every story — extract light decorators.
- Snapshotting entire DOM of stories as the only test.
- Ignoring a11y addon failures.
Interview out-loud answer
“Storybook documents component states and can run interaction tests in a browser. I use it for design-system matrices and visual/a11y checks; I still unit-test pure logic and E2E critical journeys. Stories should include empty/error/long-content states.”
Story naming and matrix
Name stories by state, not by ticket (Loading, Empty, Error, LongNameTruncation). For design systems, a matrix of variant × size × disabled is worth the story count; for app pages, prefer a handful of high-value states.
Extra practice
Write a minimal demo in a scratch file or the playground: one happy path, one failure path, and one boundary input. If you cannot exhibit a bug that the pattern prevents, you do not own the concept yet — re-read the primary docs linked below and tighten the example until the failure is obvious.
Related on this site
- Testing Library
- Visual regression testing
- MSW mock service worker
- Testing pyramid for frontend
- Accessibility testing in CI
Further reading
Related guides
- Accessibility Testing in CIWire axe and lint rules into CI without false confidence — what automation catches, what it misses, and a practical pipeline.
- Contract Testing APIsKeep frontend and backend agreements honest — schema contracts, Pact-style consumer tests, and OpenAPI-driven checks without brittle E2E.
- Coverage Metrics PitfallsWhy 100% line coverage can still ship bugs — gaming metrics, useless tests, and what coverage is actually good for.
- End-to-End Testing TradeoffsWhen E2E tests earn their keep, why they flake, and how to keep a small critical-path suite instead of a slow second frontend.
- Fake Timers for DebounceTest debounced and throttled UI with Vitest/Jest fake timers — advance time deterministically without real sleeps.