在 Playwright CT 中的可移植 stories
(⚠️ 实验性功能)
Playwright CT 的可移植 stories API 是实验性的。Playwright CT 本身也是实验性的。未来版本中,这两个库都可能发生重大变更。
可移植 stories 是 Storybook stories,它们可以在外部环境中使用,例如 Playwright 组件测试 (CT)。
通常,Storybook 会自动组合 story 及其 annotations,作为 story pipeline 的一部分。在 Playwright CT 中使用 stories 时,你可以使用 createTest
函数,它扩展了 Playwright 的测试功能,增加了一个自定义的 mount
机制,为你处理 story pipeline。
你的项目必须使用 React 18+ 才能在 Playwright CT 中使用可移植 stories API。
正在使用 Next.js
? Playwright CT 中的可移植 stories API 尚未支持 Next.js。
createTest
(⚠️ 实验性功能)
你可以使用 Storybook 特定的 createTest
函数来替代 Playwright 自己的 test
函数,该函数可以扩展 Playwright 的基础 fixture 并覆盖 mount
函数来加载、渲染和播放 story。此函数是实验性的,可能会发生变化。
import { createTest } from '@storybook/react/experimental-playwright';
import { test as base } from '@playwright/experimental-ct-react';
// See explanation below for `.portable` stories file
import stories from './Button.stories.portable';
const test = createTest(base);
test('renders primary button', async ({ mount }) => {
// The mount function will execute all the necessary steps in the story,
// such as loaders, render, and play function
await mount(<stories.Primary />);
});
test('renders primary button with overridden props', async ({ mount }) => {
// You can pass custom props to your component via JSX
const component = await mount(<stories.Primary label="label from test" />);
await expect(component).toContainText('label from test');
await expect(component.getByRole('button')).toHaveClass(/storybook-button--primary/);
});
你在 Playwright 测试文件中编写的代码由 Playwright 进行转换和编排,其中一部分代码在 Node 中执行,而另一部分代码在浏览器中执行。
因此,你必须将 stories 组合到一个与你的测试文件不同的单独文件中
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import { composeStories } from '@storybook/your-framework';
import * as stories from './Button.stories';
// This function will be executed in the browser
// and compose all stories, exporting them in a single object
export default composeStories(stories);
然后,你可以在 Playwright 测试文件中导入组合后的 stories,如上面的示例所示。
类型
createTest(
baseTest: PlaywrightFixture
) => PlaywrightFixture
参数
baseTest
(必需)
类型: PlaywrightFixture
要使用的基础测试函数,例如 Playwright 中的 test
。
返回
类型: PlaywrightFixture
一个带有自定义 mount
机制的 Storybook 特定测试函数。
setProjectAnnotations
此 API 应在测试运行前,在 playwright/index.ts
中调用一次。这将确保在调用 mount
时,也会考虑项目 annotations。
以下是设置文件中所需的配置:
- preview annotations:在
.storybook/preview.ts
中定义的那些 - 插件 annotations(可选):插件导出的那些
- beforeAll:在所有测试运行之前运行的代码(更多信息)
import { test } from '@playwright/experimental-ct-react';
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import { setProjectAnnotations } from '@storybook/your-framework';
// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
import * as previewAnnotations from './.storybook/preview';
const annotations = setProjectAnnotations([previewAnnotations, addonAnnotations]);
// Supports beforeAll hook from Storybook
test.beforeAll(annotations.beforeAll);
有时,story 可能需要插件的 装饰器 或 加载器 才能正确渲染。例如,插件可以应用一个装饰器,将你的 story 包装在必要的路由器上下文中。在这种情况下,你必须在项目 annotations 设置中包含该插件的 preview
导出。参见上面示例中的 addonAnnotations
。
注意:如果插件没有自动应用装饰器或加载器,而是将它们导出供你在 .storybook/preview.js|ts
中手动应用(例如使用 @storybook/addon-themes 中的 withThemeFromJSXProvider
),则无需做任何其他事情。它们已经包含在上面示例的 previewAnnotations
中。
类型
(projectAnnotations: ProjectAnnotation | ProjectAnnotation[]) => ProjectAnnotation
参数
projectAnnotations
(必需)
类型: ProjectAnnotation | ProjectAnnotation[]
一组项目 annotations(在 .storybook/preview.js|ts
中定义的那些),或者一组项目 annotations 的数组,它们将应用于所有组合的 stories。
Annotations
Annotations 是应用于 story 的元数据,例如 args、装饰器、加载器 和 play 函数。它们可以为一个特定的 story、一个组件的所有 stories 或项目中的所有 stories 定义。
Story pipeline
为了预览你的 stories,Storybook 会运行一个 story pipeline,其中包括应用项目 annotations、加载数据、渲染 story 和执行交互。这是一个简化版的 pipeline
然而,当你想在不同的环境中复用 story 时,理解所有这些步骤构成了 story 是至关重要的。可移植 stories API 为你提供了在外部环境中重现该 story pipeline 的机制
1. 应用项目级 annotations
Annotations 来自 story 本身、该 story 的组件以及项目。项目级 annotations 是在你的 .storybook/preview.js
文件中定义的,以及你使用的插件定义的。在可移植 stories 中,这些 annotations 不会自动应用——你必须自己应用它们。
👉 为此,请使用 setProjectAnnotations
API。
2. 准备、加载、渲染和播放
story pipeline 包括准备 story、加载数据、渲染 story 以及执行交互。在 Playwright CT 中的可移植 stories 中,mount
函数会为你处理这些步骤。
👉 为此,请使用 createTest
API。
如果你的 play 函数包含断言(例如 expect
调用),那么当这些断言失败时,你的测试也会失败。
覆盖全局变量
如果你的 stories 根据全局变量表现不同(例如以英语或西班牙语渲染文本),你可以在组合 story 时通过覆盖项目 annotations 来在可移植 stories 中定义这些全局变量
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import { composeStory } from '@storybook/your-framework';
import meta, { Primary } from './Button.stories';
export const PrimaryEnglish = composeStory(
Primary,
meta,
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
);
export const PrimarySpanish = composeStory(Primary, meta, { globals: { locale: 'es' } });
然后,你可以在 Playwright 测试文件中使用 createTest
函数来使用这些组合后的 stories。