Modern QA2026Automated Storybook Testing in CI — tiles
Log inJoin
61 / 74 · 10 Visual & Accessibility Testing · Component-Level Visual Testing in Storybook← prev⊞ allnext →☰ Read as one page

11.5Automated Storybook Testing in CI

With Chromatic

- name: Build and test Storybook
  run: |
    npx storybook build -o storybook-static
    npx chromatic --project-token=${{ secrets.CHROMATIC_TOKEN }} \
      --exit-once-uploaded \
      --only-changed

With Playwright

// tests/storybook/visual.spec.ts
import { test, expect } from '@playwright/test';

const STORYBOOK_URL = 'http://localhost:6006';

// Generate tests for each story
const stories = [
    'components-button--primary',
    'components-button--disabled',
    'components-button--loading',
    'components-datatable--with-data',
    'components-datatable--empty',
    'components-textfield--with-error',
];

for (const story of stories) {
    test(`visual: ${story}`, async ({ page }) => {
        await page.goto(`${STORYBOOK_URL}/iframe.html?id=${story}`);
        await page.waitForLoadState('networkidle');

        await expect(page).toHaveScreenshot(`${story}.png`, {
            maxDiffPixelRatio: 0.01,
            animations: 'disabled',
        });
    });

    test(`a11y: ${story}`, async ({ page }) => {
        await page.goto(`${STORYBOOK_URL}/iframe.html?id=${story}`);
        await page.waitForLoadState('networkidle');

        const AxeBuilder = (await import('@axe-core/playwright')).default;
        const results = await new AxeBuilder({ page }).analyze();
        expect(results.violations).toEqual([]);
    });
}