storycap-testrun 为 Story 提供类似于 storycap 内部稳定性检查的功能,从而可以准确地捕获 Story 的屏幕截图 :camera
为什么选择 storycap-testrun?
在使用 @storybook/test-runner
进行视觉回归测试时,会使用 waitForPageReady
函数在拍摄屏幕截图之前等待。这仅支持最基本的稳定性检查。因此,在实际用例中,需要设计方法来进行更准确的稳定性检查。
storycap 通过使用 CDP 监控 Story 在浏览器中渲染时的各种指标来实现稳定的拍摄。storycap-testrun 遵循 storycap 的策略,执行准确检查渲染内容稳定性的屏幕截图捕获。此外,它还提供了一种通过验证多个捕获的屏幕截图图像的哈希值是否相同来检查渲染内容稳定性的机制。
此外,它还提供了用于避免不稳定测试的启发式实用程序,例如蒙版和移除,这些实用程序可以在每个 Story 的参数中指定。
特性
- 对渲染内容进行高稳定性检查
- 准确等待 Play 函数
- 使用 Hook 自定义屏幕截图捕获前后的操作
- 屏蔽不稳定的元素
- 移除不稳定的元素
- 跳过不稳定的元素
限制
- 无法捕获多个视口
@storybook/test-runner
的一个限制。可以通过根据需要在多个视口中运行测试来解决。
- 不支持
:hover
、:focus
、点击等变体。- 虽然这是 storycap 支持的一个方便的功能,但为了避免影响在
postVisit
中执行的其他进程,它不被支持。
- 虽然这是 storycap 支持的一个方便的功能,但为了避免影响在
需求
- Node.js >= 18
@storybook/test-runner
>= 0.x
安装
通过 npm 安装
$ npm install --save-dev storycap-testrun
入门
请事先设置 @storybook/test-runner
。
您可以通过在 postVisit
中调用 screenshot
函数立即开始使用它。
// .storybook/tesr-runner.ts
import type { TestRunnerConfig } from '@storybook/test-runner';
import { screenshot } from 'storycap-testrun';
const config: TestRunnerConfig = {
async postVisit(page, context) {
await screenshot(page, context, {
/* options */
});
},
};
export default config;
[!重要] 由于
screenshot
函数会在内部自动执行稳定性检查,因此无需使用waitForPageReady
等等待函数。
$ test-storybook
然后,只需适当地运行 @storybook/test-runner
。
默认情况下,屏幕截图图像保存在 __screenshots__
目录中。
TypeScript 设置
通过导入 ScreenshotParameters
并合并您使用的框架的类型,您可以为每个 Story 中指定的参数启用类型检查。
import type { ScreenshotParameters } from 'storycap-testrun';
// Replace it with the framework you are using.
declare module '@storybook/react' {
interface Parameters {
screenshot?: ScreenshotParameters;
}
}
API
screenshot(page, context, options)
page: Page
- 在
postVisit
中传递的 Playwright 页面实例。
- 在
context: TestContext
- 在
postVisit
中传递的来自@storybook/test-runner
的测试上下文。
- 在
options: ScreenshotOptions
- 参见 选项部分。
- 返回:
Promise<Buffer | null>
- 捕获的屏幕截图图像的缓冲区。如果指定了
skip: true
,则返回null
。
- 捕获的屏幕截图图像的缓冲区。如果指定了
选项
可以在 screenshot
函数的第三个参数中指定的选项。
output.dry
类型: boolean
默认值: false
如果指定了 true
,则 screenshot
函数在执行时不会保存图像。这在处理返回的 Buffer 时很有用。
output.dir
类型: string
默认值: path.join(process.cwd(), '__screenshots__')
指定保存屏幕截图图像的根目录。
output.file
类型: string | ((context: TestContext) => string)
默认值: path.join('[title]', '[name].png')
指定每个 Story 的屏幕截图图像的文件名。
在指定 string
时,可以使用以下模板
[id]
:Story ID[title]
:Story 的标题[name]
:Story 的名称
flakiness.metrics.enabled
类型: boolean
默认值: true
当指定为 true
时,它会监控与 Story 渲染相关的多个指标并执行稳定性检查。
[!警告]
由于此过程依赖于 CDP,因此它仅在 Chromium 浏览器中有效。如果在 Chromium 以外的浏览器中启用,则会显示警告。
flakiness.metrics.retries
类型: number
默认值: 1000
指标监控期间的重试次数。它会持续监控指定数量的帧(1 帧 = 16 毫秒),并确保指标稳定。
flakiness.retake.enabled
类型: boolean
默认值: true
它计算屏幕截图图像的哈希值,并通过确保图像没有变化来检查渲染内容的稳定性。
[!提示]
在 Chromium 的情况下,仅使用flakiness.metrics.enabled
通常就足够了。启用此选项意味着至少捕获两次屏幕截图,因此如果它导致性能下降,建议将其禁用。
flakiness.retake.interval
类型: number
默认值: 100
再次尝试捕获屏幕截图之前的毫秒间隔。第二次捕获立即执行以进行哈希检查。
flakiness.retake.retries
类型: number
默认值: 10
重复捕获屏幕截图直到图像的哈希值相同为止的次数。建议使用 3 或更大的值来达到重试的效果。
hooks
类型: ScreenshotHook[]
默认值: []
用于中断屏幕截图捕获前后的进程的 Hook。请指定一个实现以下接口的对象。
export type ScreenshotHook = {
setup?: TestHook;
preCapture?: TestHook;
postCapture?: (
page: Page,
context: TestContext,
image: ScreenshotImage,
) => Promise<void>;
};
每个 Hook 都在以下生命周期中执行
方法 | 描述 |
---|---|
setup |
在执行 screenshot 函数后立即执行 |
preCapture |
在执行 waitForPageReady 后执行 |
postCapture |
在捕获屏幕截图后,保存图像之前执行 |
蒙版和移除等内置函数是使用 Hook 实现的。
fullPage
类型: boolean
默认值: true
omitBackground
类型: boolean
默认值: false
scale
类型: 'css' | 'device'
默认值: 'device'
参数
这些是可以在每个 Story 中指定的参数。
// Button.stories.tsx
const meta: Meta<typeof Button> = {
component: Button,
parameters: {
screenshot: {
/* parameters... */
},
},
};
export default meta;
skip
类型: boolean
默认值: false
跳过屏幕截图捕获。在您想使用 @storybook/test-runner
但禁用屏幕截图捕获的情况下很有用。
delay
类型: number
默认值: 无
捕获屏幕截图之前的毫秒延迟。在完成基本稳定性检查后等待。
mask
类型: string | { selector: string; color: string }
默认值: 无
使用矩形遮盖与 CSS 选择器对应的元素。用于隐藏在每次渲染时内容不可避免地不同的元素。
remove
类型: string
默认值: 无
移除与 CSS 选择器对应的元素。
更新日志
参见 CHANGELOG.md。