加入直播:周四东部时间上午 11 点,Storybook 9 发布与 AMA
文档
Storybook Docs

端到端测试中的故事

Storybook 与 CypressPlaywright 等其他测试框架无缝集成,提供全面的测试解决方案。通过利用组件故事格式(CSF),开发者可以编写模拟用户交互并验证 Storybook 环境中单个组件行为的测试用例。这种方法使开发者能够在不同场景下彻底测试其组件的功能、响应性以及视觉外观,从而创建更健壮、更可靠的应用程序。

使用 Cypress

Cypress 是一个端到端测试框架。它可以通过模拟用户行为来测试你的应用程序的完整实例。通过组件故事格式(CSF),你的故事可以与 Cypress 重复使用。每个具名导出(换句话说,就是一个故事)都可以在你的测试设置中渲染。

一个使用 Cypress 和 Storybook 进行端到端测试的例子是测试登录组件的输入是否正确。例如,如果你有以下故事

LoginForm.stories.ts|tsx
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { expect } from 'storybook/test';
 
import { LoginForm } from './LoginForm';
 
const meta = {
  component: LoginForm,
} satisfies Meta<typeof LoginForm>;
export default meta;
 
type Story = StoryObj<typeof meta>;
 
export const EmptyForm: Story = {};
 
export const FilledForm: Story = {
  play: async ({ canvas, userEvent }) => {
    // 👇 Simulate interactions with the component
    await userEvent.type(canvas.getByTestId('email'), 'email@provider.com');
 
    await userEvent.type(canvas.getByTestId('password'), 'a-random-password');
 
    // See https://storybook.org.cn/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel
    await userEvent.click(canvas.getByRole('button'));
 
    // 👇 Assert DOM structure
    await expect(
      canvas.getByText(
        'Everything is perfect. Your account is ready and we should probably get you started!'
      )
    ).toBeInTheDocument();
  },
};

Play 函数包含在故事渲染后运行的小段代码。它允许你在故事中按顺序进行交互。

使用 Cypress,你可以编写以下测试

/cypress/integration/Login.spec.js
/// <reference types="cypress" />
 
describe('Login Form', () => {
  it('Should contain valid login information', () => {
    cy.visit('/iframe.html?id=components-login-form--example');
    cy.get('#login-form').within(() => {
      cy.log('**enter the email**');
      cy.get('#email').should('have.value', 'email@provider.com');
      cy.log('**enter password**');
      cy.get('#password').should('have.value', 'a-random-password');
    });
  });
});

当 Cypress 运行你的测试时,它会加载 Storybook 的隔离 iframe,并检查输入是否与测试值匹配。

使用 Playwright

Playwright 是微软提供的浏览器自动化工具和端到端测试框架。它提供跨浏览器自动化、设备模拟的移动端测试以及无头测试。通过组件故事格式(CSF),你的故事可以与 Playwright 重复使用。每个具名导出(换句话说,就是一个故事)都可以在你的测试设置中渲染。

使用 Playwright 进行用户流程测试的一个实际场景是如何测试登录表单的有效性。例如,如果你已经创建了以下故事

LoginForm.stories.ts|tsx
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { expect } from 'storybook/test';
 
import { LoginForm } from './LoginForm';
 
const meta = {
  component: LoginForm,
} satisfies Meta<typeof LoginForm>;
export default meta;
 
type Story = StoryObj<typeof meta>;
 
export const EmptyForm: Story = {};
 
export const FilledForm: Story = {
  play: async ({ canvas, userEvent }) => {
    // 👇 Simulate interactions with the component
    await userEvent.type(canvas.getByTestId('email'), 'email@provider.com');
 
    await userEvent.type(canvas.getByTestId('password'), 'a-random-password');
 
    // See https://storybook.org.cn/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel
    await userEvent.click(canvas.getByRole('button'));
 
    // 👇 Assert DOM structure
    await expect(
      canvas.getByText(
        'Everything is perfect. Your account is ready and we should probably get you started!'
      )
    ).toBeInTheDocument();
  },
};

Play 函数包含在故事渲染后运行的小段代码。它允许你在故事中按顺序进行交互。

使用 Playwright,你可以编写一个测试来检查输入是否已填写并与故事匹配

tests/login-form/login.spec.js
const { test, expect } = require('@playwright/test');
 
test('Login Form inputs', async ({ page }) => {
  await page.goto('http://localhost:6006/iframe.html?id=components-login-form--example');
  const email = await page.inputValue('#email');
  const password = await page.inputValue('#password');
  await expect(email).toBe('email@provider.com');
  await expect(password).toBe('a-random-password');
});

执行 Playwright 后,它会打开一个新的浏览器窗口,加载 Storybook 的隔离 iframe,断言输入是否包含指定的值,并在终端中显示测试结果。

更多测试资源