文件
Storybook 文件

互動

Storybook 中的 play 函式可讓您在 story 渲染後模擬使用者互動。透過 Interactions 擴充功能,您可以視覺化並偵錯這些互動。

互動的 Play 函式

Stories 以結構化的方式隔離和擷取元件狀態。在開發元件時,您可以快速循環瀏覽 stories 來驗證外觀和風格。每個 story 都會指定重現特定狀態所需的所有輸入。您甚至可以模擬內容和 API 呼叫,讓您處理元件的大部分使用案例。但是,需要使用者互動的狀態呢?

例如,按一下按鈕以開啟/關閉對話方塊、拖曳清單項目以重新排序,或填寫表單以檢查驗證錯誤。若要測試這些行為,您必須像使用者一樣與元件互動。互動式 stories 可讓您使用 play 函式自動化這些互動。它們是程式碼的小片段,會在 story 完成渲染後執行,模擬使用者與元件互動的確切步驟。

由 Testing Library 和 Vitest 提供支援

互動是使用名為 @storybook/test 的套件撰寫的。它提供 Storybook 儀器版本的 Testing LibraryVitest。這讓您有熟悉的開發人員友善語法來與 DOM 互動並進行判斷提示,但具有額外的遙測功能以協助偵錯。

設定互動擴充功能

依預設,如果您要為新專案新增 Storybook,則已安裝並設定 @storybook/addon-interactions。如果您要從先前版本的 Storybook 移轉,則需要手動安裝。

執行下列命令以安裝互動擴充功能和相關的相依性。

npm install @storybook/test @storybook/addon-interactions --save-dev

接下來,將 .storybook/main.js|ts 更新為下列內容

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    // Other Storybook addons
    '@storybook/addon-interactions', // 👈 Register the addon
  ],
};
 
export default config;

請務必在 @storybook/addon-essentials 擴充功能(或您個別安裝的 @storybook/addon-actions之後列出 @storybook/addon-interactions

現在,當您執行 Storybook 時,就會啟用互動擴充功能。

Storybook Interactions installed and registered

撰寫元件測試

互動會在 stories 的 play 函式中執行。我們依賴 Testing Library 來執行繁重的工作。

請務必透過 @storybook/test 匯入 Vitest 和 Testing Library 的 Storybook 包裝函式,而不是直接匯入原始套件。

Form.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { userEvent, waitFor, within, expect, fn } from '@storybook/test';
 
import { Form } from './Form';
 
const meta: Meta<typeof Form> = {
  component: Form,
  args: {
    // 👇 Use `fn` to spy on the onSubmit arg
    onSubmit: fn(),
  },
};
 
export default meta;
type Story = StoryObj<typeof Form>;
 
/*
 * See https://storybook.dev.org.tw/docs/writing-stories/play-function#working-with-the-canvas
 * to learn more about using the canvasElement to query the DOM
 */
export const Submitted: Story = {
  play: async ({ args, canvasElement, step }) => {
    const canvas = within(canvasElement);
 
    await step('Enter credentials', async () => {
      await userEvent.type(canvas.getByTestId('email'), 'hi@example.com');
      await userEvent.type(canvas.getByTestId('password'), 'supersecret');
    });
 
    await step('Submit form', async () => {
      await userEvent.click(canvas.getByRole('button'));
    });
 
    // 👇 Now we can assert that the onSubmit arg was called
    await waitFor(() => expect(args.onSubmit).toHaveBeenCalled());
  },
};

以上範例使用 canvasElement 將您的元素查詢範圍設定為目前的 story。如果您希望您的 play 函式最終與 Storybook 文件相容(會在同一頁面上渲染多個元件),這非常重要。此外,step 函式可用於建立加上標籤的互動群組。

雖然您可以參考 Testing Library 文件,以取得有關如何使用它的詳細資訊,但在使用 Storybook 包裝函式時,有一個重要的細節不同:方法呼叫必須使用 await。它可讓您使用偵錯工具來回逐步執行互動。

任何已標示為動作的 args,無論是使用 argTypes 註解argTypesRegex,都會自動轉換為 Jest 模擬函式 (spy)。這可讓您判斷對這些函式的呼叫。

若要在 Storybook stories 中模擬函式,以進行可靠且隔離的元件測試,請使用來自 @storybook/test 的具名 fn 匯入。

API

參數

此附加元件在 Storybook 的 interactions 命名空間下,貢獻了以下參數

disable

類型:boolean

停用此附加元件的行為。如果您希望為整個 Storybook 停用此附加元件,您應該在註冊 addon-essentials 時執行此操作。有關更多資訊,請參閱基本附加元件的文件

此參數在更具體的層級上允許覆寫時最有用。例如,如果此參數在專案層級設定為 true,則可以透過在 meta(元件)或 story 層級將其設定為 false 來重新啟用。