Storybook元件測試元件庫Vitest前端工程師前端教學

Storybook 教學:建立可測試的元件文件指南

如何建立可測試的元件文件?Storybook 教學含 Story 撰寫、Play 函式、CI 整合。讓元件文件同時成為測試案例。

· 4 分鐘閱讀

元件庫最常見的問題:工程師辛苦寫了一堆元件,卻沒有人知道怎麼用——沒有文件、沒有互動預覽、不知道有哪些變體可以調整。Storybook 把元件庫變成一本可以即時互動的目錄,每個元件都有視覺化的預覽、操作說明和測試覆蓋率。


前言:為什麼 Storybook 是元件庫標配?

元件庫建立之後,最大挑戰不是「怎麼寫元件」,而是「別人怎麼知道怎麼用」。

沒有 Storybook 時,團隊成員想看某個元件長什麼樣:

  • 必須把專案跑起來
  • 必須找到那個元件的實際使用頁面
  • 必須具備該頁面的上下文才能測試

有 Storybook 時:

  • 打開瀏覽器,瀏覽所有元件目錄
  • 每個元件都有獨立的展示環境
  • 可以切換所有變體(variant、size、theme)
  • 還能直接跑測試

Storybook 安裝

# 在現有專案加入 Storybook
npx storybook@latest init

# Storybook 會自動偵測框架(React / Vue)
# 安裝完成後啟動
npm run storybook

Storybook 預設會在 http://localhost:6006 啟動。


建立你的第一個 Story

基本 Story

// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'Form/Button',           // 在 Storybook 左側選單中的路徑
  component: Button,
  tags: ['autodocs'],            // 自動產生文件頁
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'ghost', 'danger'],
    },
    size: {
      control: 'select',
      options: ['sm', 'md', 'lg'],
    },
    isLoading: { control: 'boolean' },
    disabled: { control: 'boolean' },
  },
};

export default meta;
type Story = StoryObj<typeof meta>;

// 每個 Story 是一個變體
export const Primary: Story = {
  args: {
    variant: 'primary',
    size: 'md',
    children: '主要按鈕',
  },
};

export const Secondary: Story = {
  args: {
    variant: 'secondary',
    size: 'md',
    children: '次要按鈕',
  },
};

export const Loading: Story = {
  args: {
    variant: 'primary',
    isLoading: true,
    children: '載入中',
  },
};

export const Disabled: Story = {
  args: {
    variant: 'primary',
    disabled: true,
    children: '無法點擊',
  },
};

title 決定了左側目錄的位置:Form/Button 會出現在 Form 資料夾下的 Button

argTypes 讓 Storybook 的 Controls panel 自動出現,團隊成員可以即時切換 props,不需要動 code 就能看到不同組合的結果。


Storybook 與 Vitest 測試整合

Storybook 可以與 Vitest 直接整合,在 Storybook 環境中跑測試:

安裝整合

npm install -D @storybook/test

把 Component Testing 加到 Story 裡

Storybook 8.x 支援在 .stories.tsx 檔案裡直接寫 Playwright 或 Vitest 測試:

// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
import { within, userEvent, expect } from '@storybook/test';

const meta: Meta<typeof Button> = {
  title: 'Form/Button',
  component: Button,
  tags: ['autodocs'],
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {
    variant: 'primary',
    size: 'md',
    children: '主要按鈕',
  },
};

// 在 Story 裡直接寫 Playwright 測試
export const PrimaryClick: Story = {
  args: {
    variant: 'primary',
    size: 'md',
    children: '點擊我',
  },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const button = canvas.getByRole('button');
    await userEvent.click(button);
    // 這個 Story 除了展示之外,同時也是一個 Playwright 測試
    await expect(button).toHaveAttribute('data-clicked', 'true');
  },
};

play 函式讓 Storybook 在 render 元件的同時執行 Playwright 測試。點擊左側的 Play 按鈕就能觸發。

在 CI 中執行 Storybook 測試

# .github/workflows/storybook.yml

name: Storybook Tests

on: [push, pull_request]

jobs:
  storybook-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - run: npm ci

      - name: Install Playwright
        run: npx playwright install --with-deps

      - name: Build Storybook
        run: npm run build-storybook

      - name: Run Storybook tests
        run: npm run test-storybook

Storybook 的文档功能

Storybook 會根據你的 Story 自動產生文件:

// 加入文件說明
export const Primary: Story = {
  args: {
    variant: 'primary',
    size: 'md',
    children: '主要按鈕',
  },
  parameters: {
    docs: {
      description: {
        component: '主要按鈕用於主要操作,例如送出表單、確認刪除等。<br/>**使用時機**:非最後行動作時使用。',
      },
    },
  },
};

加上 autodocs tag 後,Storybook 會自動產生文件頁,包含:

  • 元件說明
  • 所有 Story 列表
  • Props 表格(從 TypeScript 型別自動推斷)
  • 每個 Story 的截圖

Storybook 的常見問題

Q:Storybook 和 Styleguidist 有什麼不同?

A:兩者目標類似,但 Styleguidist 已經停止維護,Storybook 是目前唯一活跃的選擇。另一個新選擇是 Ladle,比 Storybook 更輕量,構建速度更快,適合簡單的元件文件需求。

Q:Storybook 會拖慢 CI 嗎?

A:會。Storybook build 本身比較慢,建議只在 main 分支和 PR 時執行 Storybook 測試,不在每次 commit 時跑。也不要對所有元件都寫 play 測試——只針對需要互動驗證的關鍵元件。

Q:Storybook 需要對所有元件都寫 Story 嗎?

A:不需要。優先針對公開元件(要給其他團隊或其他人用的)複雜的互動邏輯有多個變體的元件寫 Story。內部使用的小元件不需要。


總結:元件庫的核心是文件

Storybook 的核心價值:讓元件庫從「一堆程式碼」變成「一本可以翻閱的書」

這篇文章涵蓋:

  • Storybook 的安裝與基本設定
  • 建立第一個 Story(argTypes + Controls)
  • Storybook + Playwright 測試整合(play 函式)
  • CI 中的 Storybook 測試執行
  • 文件自動產生(autodocs + parameters)

下一步:在你的元件庫執行 npx storybook@latest init,選擇一個核心元件建立 Story。從 Button 或 Input 開始,看見第一個能在瀏覽器裡即時操作的文件。


想了解 Design System 的建立方式,可參考 《Design System 入門:從零開始建立你的元件庫》