端到端测试中的故事
Storybook 与 Cypress 和 Playwright 等其他测试框架无缝集成,提供全面的测试解决方案。通过利用组件故事格式(CSF),开发者可以编写模拟用户交互并验证 Storybook 环境中单个组件行为的测试用例。这种方法使开发者能够在不同场景下彻底测试其组件的功能、响应性以及视觉外观,从而创建更健壮、更可靠的应用程序。
使用 Cypress
Cypress 是一个端到端测试框架。它可以通过模拟用户行为来测试你的应用程序的完整实例。通过组件故事格式(CSF),你的故事可以与 Cypress 重复使用。每个具名导出(换句话说,就是一个故事)都可以在你的测试设置中渲染。
一个使用 Cypress 和 Storybook 进行端到端测试的例子是测试登录组件的输入是否正确。例如,如果你有以下故事
// 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,你可以编写以下测试
/// <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 进行用户流程测试的一个实际场景是如何测试登录表单的有效性。例如,如果你已经创建了以下故事
// 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,你可以编写一个测试来检查输入是否已填写并与故事匹配
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,断言输入是否包含指定的值,并在终端中显示测试结果。
更多测试资源