OCR 测试服务
关于 WebdriverIO 的视觉测试文档,请参考文档。该项目包含了使用 WebdriverIO 运行视觉测试的所有相关模块。在 ./packages
目录中,您将找到:
@wdio/visual-testing
:WebdriverIO 的视觉测试集成服务webdriver-image-comparison
:一个图像比较模块,可用于支持 WebDriver 协议的不同 NodeJS 测试自动化框架
Storybook 运行器 (测试版)
点击查看更多关于 Storybook 运行器测试版的文档
Storybook 运行器仍处于测试阶段,文档稍后将移至 WebdriverIO 文档页面。
本模块现在支持 Storybook,并提供了一个新的视觉运行器。这个运行器会自动扫描本地/远程 Storybook 实例,并为每个组件创建元素截图。只需在 services
中添加
export const config: WebdriverIO.Config = {
// ...
services: ["visual"],
// ....
};
并通过命令行运行 npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook
。
它将默认使用 Chrome 的无头模式作为浏览器。
[!NOTE]
- 大多数视觉测试选项也适用于 Storybook 运行器,请参阅 WebdriverIO 文档。
- Storybook 运行器将覆盖所有您的功能配置,并且只能在其支持的浏览器上运行,参见
--browsers
。- Storybook 运行器不支持使用 Multiremote 功能的现有配置,并会抛出错误。
- Storybook 运行器只支持桌面网页,不支持移动网页。
Storybook 运行器服务选项
服务选项可以像这样提供
export const config: WebdriverIO.Config = {
// ...
services: [
[
'visual',
{
// 一些默认选项
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
// Storybook 选项,参见 cli 选项的描述
storybook: {
additionalSearchParams: new URLSearchParams({foo: 'bar', abc: 'def'}),
clip: false,
clipSelector: ''#some-id,
numShards: 4,
// `skipStories` 可以是一个字符串 ('example-button--secondary'),
// 一个数组 (['example-button--secondary', 'example-button--small'])
// 或一个正则表达式,需要以字符串形式提供 ("/.*button.*/gm")
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
// 可选 - 允许覆盖基线路径。默认情况下,它会按类别和组件分组基线(例如 forms/input/baseline.png)
getStoriesBaselinePath: (category, component) => `path__${category}__${component}`,
},
},
],
],
// ....
}
Storybook 运行器 CLI 选项
--additionalSearchParams
- 类型:
string
- 必填: 否
- 默认值: ''
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --additionalSearchParams="foo=bar&abc=def"
它将为 Storybook URL 添加额外的搜索参数。 查看 URLSearchParams 文档获取更多信息。字符串必须是 有效的 URLSearchParams 字符串。
[!NOTE] 需要双引号以防止
&
被解释为命令分隔符。 例如,使用--additionalSearchParams="foo=bar&abc=def"
会为故事测试生成以下 Storybook URL:http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def
。
--browsers
- 类型:
string
- 必填: 否
- 默认值:
chrome
,您可以从chrome|firefox|edge|safari
中选择 - 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
- 注意: 仅通过 CLI 可用
它将使用提供的浏览器来进行组件截图
[!NOTE] 确保您的本地机器上已安装了您想要运行的浏览器
--clip
- 类型:
boolean
- 必填: 否
- 默认值:
true
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clip=false
禁用时将创建视口截图。启用时将基于 --clipSelector
创建元素截图,这将减少组件截图周围的空白区域并减小截图尺寸。
--clipSelector
- 类型:
string
- 必填: 否
- 默认值: Storybook V7 为
#storybook-root > :first-child
,Storybook V6 为#root > :first-child:not(script):not(style)
,另见--version
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clipSelector="#some-id"
这是将用于以下目的的选择器:
- 选择要截图的元素
- 等待元素可见后再进行截图
--devices
- 类型:
string
- 必填: 否
- 默认值: 您可以从
deviceDescriptors.ts
中选择 - 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
- 注意: 仅通过 CLI 可用
它将使用与 deviceDescriptors.ts
匹配的提供的设备来进行组件截图
[!NOTE]
- 如果您缺少设备配置,请随时提交功能请求
- 这只适用于 Chrome:
- 如果您提供
--devices
,则所有 Chrome 实例将以移动模拟模式运行- 如果您还提供其他浏览器,如
--devices --browsers=firefox,safari,edge
,它会自动添加移动模拟模式的 Chrome- Storybook 运行器默认创建元素快照,如果您想查看完整的移动模拟截图,请通过命令行提供
--clip=false
- 文件名将如
__snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
- 来源: 在桌面上使用移动模拟测试移动网站可能很有用,但测试人员应该意识到存在许多细微差别,如:
- 完全不同的 GPU,可能导致性能变化很大;
- 不模拟移动 UI(特别是隐藏 url 栏会影响页面高度);
- 不支持消歧弹出窗口(您在其中选择几个触摸目标之一);
- 许多硬件 API(例如 orientationchange 事件)不可用。
--headless
- 类型:
boolean
- 必填: 否
- 默认值:
true
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --headless=false
- 注意: 仅通过 CLI 可用
这将默认在无头模式下运行测试(当浏览器支持时),或者可以禁用
--numShards
- 类型:
number
- 必填: 否
- 默认值:
true
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --numShards=10
这将是用于运行故事的并行实例数。这将受到 wdio.conf
文件中 maxInstances
的限制。
[!IMPORTANT] 以
headless
模式运行时,请勿将数量增加到超过 20,以防止由于资源限制而导致不稳定
--skipStories
- 类型:
string|regex
- 必填: 否
- 默认值: null
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --skipStories="/.*button.*/gm"
这可以是:
- 字符串 (
example-button--secondary,example-button--small
) - 或正则表达式 (
"/.*button.*/gm"
)
用于跳过某些故事。使用可以在故事 URL 中找到的 id
。例如,在此 URL http://localhost:6006/?path=/story/example-page--logged-out
中的 id
是 example-page--logged-out
--url
- 类型:
string
- 必填: 否
- 默认值:
http://127.0.0.1:6006
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --url="https://example.com"
您的 Storybook 实例托管的 URL。
--version
- 类型:
number
- 必填: 否
- 默认值: 7
- 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --version=6
这是 Storybook 的版本,默认为 7
。这是为了知道是否需要使用 V6 clipSelector
。
Storybook 交互测试
Storybook 交互测试允许您通过创建带有 WDIO 命令的自定义脚本与组件交互,将组件设置为特定状态。例如,请参阅下面的代码片段:
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});
对两个不同组件执行了两个测试。每个测试首先设置状态,然后进行截图。您还会注意到引入了一个新的自定义命令,可在此处找到。
上述规范文件可以保存在文件夹中,并通过以下命令添加到命令行:
pnpm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'
Storybook 运行器将首先自动扫描您的 Storybook 实例,然后将您的测试添加到需要比较的故事中。如果您不希望用于交互测试的组件被比较两次,可以通过提供 --skipStories
过滤器来从扫描中删除"默认"故事。这看起来像这样:
pnpm run test.local.desktop.storybook.localhost -- --skipStories="/example-page.*/gm" --spec='tests/specs/storybook-interaction/*.ts'
新的自定义命令
将添加一个名为 browser.waitForStorybookComponentToBeLoaded({ id: 'componentId' })
的新自定义命令到 browser/driver
对象,该命令将自动加载组件并等待其完成,因此您不需要使用 browser.url('url.com')
方法。可以这样使用:
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});