加入直播会话:周四 EDT 上午 11 点,Storybook 9 发布及 AMA 问答

一个使用 `@storybook/test-runner` 提供稳定截图功能的工具。

在 Github 上查看

storycap-testrun 具有类似于 storycap 内部的 Stories 稳定性检查功能,可以准确地截取 Stories 的屏幕截图 :camera

为什么选择 storycap-testrun?

使用 @storybook/test-runner 进行视觉回归测试时,在截取屏幕截图之前使用 waitForPageReady 进行等待。这仅支持最低限度的稳定性检查。因此,在实际用例中,需要设计更准确的稳定性检查方法。

storycap 通过使用 CDP 监控 Stories 在浏览器中渲染时的各种指标来实现稳定拍照。storycap-testrun 遵循 storycap 的策略,执行准确检查渲染内容稳定性的屏幕截图捕获。此外,它还提供了一种机制,通过验证多个捕获的屏幕截图图像的哈希值是否相同来检查渲染内容的稳定性。

此外,它还提供了用于避免不稳定测试的启发式工具,例如 Masking 和 Removal,这些可以在每个 Story 的 Parameters 中指定。

特性

  • 对渲染内容进行高稳定性检查
  • 精确等待 Play Function
  • 使用 Hooks 在截图前后进行自定义
  • 遮罩不稳定元素
  • 移除不稳定元素
  • 跳过不稳定元素

局限性

  • 无法捕获多个视口
    • 这是 @storybook/test-runner 的一个局限性。可以根据需要通过在多个视口中运行测试来解决。
  • 不支持 :hover:focus、点击等变体状态。
    • 虽然这是 storycap 支持的一个方便的功能,但为了避免影响在 postVisit 中执行的其他进程,此处不支持此功能。

要求

安装

通过 npm 安装

$ npm install --save-dev storycap-testrun

入门

请事先设置好 @storybook/test-runner

通过在 postVisit 中调用 screenshot 函数,您可以立即开始使用它。

// .storybook/test-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;

[!IMPORTANT] 由于 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 page 实例。
  • context: TestContext
  • 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[]
默认值: []

用于在屏幕截图捕获前后中断进程的 Hooks。请指定一个实现了以下接口的对象。

export type ScreenshotHook = {
  setup?: TestHook;
  preCapture?: TestHook;
  postCapture?: (
    page: Page,
    context: TestContext,
    image: ScreenshotImage,
  ) => Promise<void>;
};

每个 Hook 在以下生命周期中执行

方法 描述
setup screenshot 函数执行后立即执行
preCapture waitForPageReady 执行后
postCapture 捕获屏幕截图后,保存图像之前

Masking 和 Removal 等内置功能是使用 Hooks 实现的。

fullPage

类型: boolean
默认值: true

请参阅 Page | Playwright

omitBackground

类型: boolean
默认值: false

请参阅 Page | Playwright

scale

类型: 'css' | 'device'
默认值: 'device'

请参阅 Page | Playwright

参数

这些是每个 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

许可证

MIT © reg-viz

reg-viz