OCR 测试服务
有关使用 WebdriverIO 进行视觉测试的文档,请参阅文档。此项目包含使用 WebdriverIO 运行视觉测试的所有相关模块。在./packages
目录中,您将找到
@wdio/visual-testing
:用于集成视觉测试的 WebdriverIO 服务webdriver-image-comparison
:一个图像比较模块,可用于支持 WebDriver 协议的不同 NodeJS 测试自动化框架
Storybook 运行器 (BETA)
点击了解更多关于 Storybook 运行器 BETA 的文档
Storybook 运行器仍处于 BETA 阶段,文档稍后将移至WebdriverIO 文档页面。
此模块现在通过新的视觉运行器支持 Storybook。此运行器会自动扫描本地/远程 Storybook 实例,并创建每个组件的元素屏幕截图。这可以通过添加
export const config: WebdriverIO.Config = {
// ...
services: ["visual"],
// ....
};
到您的services
并通过命令行运行npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook
来完成。它将使用 Chrome 无头模式作为默认浏览器。
[!注意]
- 大多数视觉测试选项也适用于 Storybook 运行器,请参阅WebdriverIO 文档。
- Storybook 运行器将覆盖您所有的功能,并且只能在它支持的浏览器上运行,请参阅
--browsers
。- Storybook 运行器不支持使用 Multiremote 功能的现有配置,并将抛出错误。
- Storybook 运行器仅支持桌面 Web,不支持移动 Web。
Storybook 运行器服务选项
服务选项可以这样提供
export const config: WebdriverIO.Config = {
// ...
services: [
[
'visual',
{
// Some default options
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
// The storybook options, see cli options for the description
storybook: {
clip: false,
clipSelector: ''#some-id,
numShards: 4,
// `skipStories` can be a string ('example-button--secondary'),
// an array (['example-button--secondary', 'example-button--small'])
// or a regex which needs to be provided as as string ("/.*button.*/gm")
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
},
},
],
],
// ....
}
Storybook 运行器 CLI 选项
--browsers
- 类型:
string
- 必填:否
- 默认值:
chrome
,您可以从chrome|firefox|edge|safari
中选择 - 示例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
- 注意:仅通过 CLI 提供
它将使用提供的浏览器获取组件屏幕截图
[!注意] 确保您在本地机器上安装了要运行的浏览器
--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
匹配)来获取组件屏幕截图
[!注意]
- 如果您缺少设备配置,请随时提交功能请求
- 这仅适用于 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
- SRC: 在桌面设备上使用移动仿真测试移动网站可能很有用,但测试人员应注意,存在许多细微差别,例如
- 完全不同的 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
的限制。
[!重要] 在
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
。例如,此 URLhttps://127.0.0.1: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`
);
});
});
在两个不同的组件上执行两个测试。每个测试首先设置一个状态,然后截取屏幕截图。您还会注意到引入了一个新的自定义命令,可以在 此处 找到。
上述规范文件可以保存在一个文件夹中,并使用以下命令添加到命令行
npm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'
Storybook 运行器将首先自动扫描您的 Storybook 实例,然后将您的测试添加到需要比较的故事中。如果您不希望用于交互测试的组件被比较两次,您可以添加一个过滤器,通过提供 --skipStories
过滤器从扫描中删除“默认”故事。这将如下所示
npm 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`
);
});
});
选项如下:
clipSelector
- 类型:
string
- 必填:否
- 默认值:对于 Storybook V7 为
#storybook-root > :first-child
,对于 Storybook V6 为#root > :first-child:not(script):not(style)
- 示例
await browser.waitForStorybookComponentToBeLoaded({
clipSelector: "#your-selector",
id: "componentId",
});
这是将使用的选择器
- 用于选择要对其进行屏幕截图的元素
- 用于等待元素可见,然后才能进行屏幕截图
id
- 类型:
string
- 必填:是
- 示例
await browser.waitForStorybookComponentToBeLoaded({ '#your-selector', id: 'componentId' })
使用故事的 id
,可以在故事的 URL 中找到。例如,此 URL https://127.0.0.1:6006/?path=/story/example-page--logged-out
中的 id
为 example-page--logged-out
timeout
- 类型:
number
- 必填:否
- 默认值:1100 毫秒
- 示例
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
timeout: 20000,
});
我们希望在页面加载后等待组件可见的最大超时时间。
url
- 类型:
string
- 必填:否
- 默认值:
http://127.0.0.1:6006
- 示例
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
url: "https://your.url",
});
Storybook 实例所在的 URL。
贡献
更新包
您可以使用简单的 CLI 工具更新包。确保您已安装所有依赖项,然后您可以运行
pnpm update.packages
这将触发一个 CLI,它将询问您以下问题
==========================
🤖 Package update Wizard 🧙
==========================
? Which version target would you like to update to? (Minor|Latest)
? Do you want to update the package.json files? (Y/n)
? Do you want to remove all "node_modules" and reinstall dependencies? (Y/n)
? Would you like reinstall the dependencies? (Y/n)
这将导致以下日志
打开以查看日志示例
==========================
🤖 Package update Wizard 🧙
==========================
? Which version target would you like to update to? Minor
? Do you want to update the package.json files? yes
Updating root 'package.json' for minor updates...
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/package.json
[====================] 38/38 100%
@typescript-eslint/eslint-plugin ^8.7.0 → ^8.8.0
@typescript-eslint/parser ^8.7.0 → ^8.8.0
@typescript-eslint/utils ^8.7.0 → ^8.8.0
@vitest/coverage-v8 ^2.1.1 → ^2.1.2
vitest ^2.1.1 → ^2.1.2
Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service/package.json
[====================] 11/11 100%
All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter/package.json
[====================] 11/11 100%
eslint-config-next 14.2.13 → 14.2.14
next 14.2.13 → 14.2.14
Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service/package.json
[====================] 5/5 100%
All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison/package.json
[====================] 8/8 100%
All dependencies match the minor package versions :)
? Do you want to remove all "node_modules" and reinstall dependencies? yes
Removing root dependencies in /Users/wswebcreation/Git/wdio/visual-testing...
Removing dependencies in ocr-service...
Removing dependencies in visual-reporter...
Removing dependencies in visual-service...
Removing dependencies in webdriver-image-comparison...
? Would you like reinstall the dependencies? yes
Installing dependencies in /Users/wswebcreation/Git/wdio/visual-testing...
> @wdio/visual-testing-monorepo@ pnpm.install.workaround /Users/wswebcreation/Git/wdio/visual-testing
> pnpm install --shamefully-hoist
Scope: all 5 workspace projects
Lockfile is up to date, resolution step is skipped
Packages: +1274
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 1274, reused 1265, downloaded 0, added 1274, done
dependencies:
- @wdio/ocr-service 2.0.0 <- packages/ocr-service
- @wdio/visual-service 6.0.0 <- packages/visual-service
devDependencies:
- @changesets/cli 2.27.8
- @inquirer/prompts 5.5.0
- @tsconfig/node20 20.1.4
- @types/eslint 9.6.1
- @types/jsdom 21.1.7
- @types/node 20.16.4
- @types/react 18.3.5
- @types/react-dom 18.3.0
- @types/xml2js 0.4.14
- @typescript-eslint/eslint-plugin 8.8.0
- @typescript-eslint/parser 8.8.0
- @typescript-eslint/utils 8.8.0
- @vitest/coverage-v8 2.1.2
- @wdio/appium-service 9.1.2
- @wdio/cli 9.1.2
- @wdio/globals 9.1.2
- @wdio/local-runner 9.1.2
- @wdio/mocha-framework 9.1.2
- @wdio/sauce-service 9.1.2
- @wdio/shared-store-service 9.1.2
- @wdio/spec-reporter 9.1.2
- @wdio/types 9.1.2
- eslint 9.11.1
- eslint-plugin-import 2.30.0
- eslint-plugin-unicorn 55.0.0
- eslint-plugin-wdio 9.0.8
- husky 9.1.6
- jsdom 25.0.1
- npm-run-all2 6.2.3
- release-it 17.6.0
- rimraf 6.0.1
- saucelabs 8.0.0
- ts-node 10.9.2
- typescript 5.6.2
- vitest 2.1.2
- webdriverio 9.1.2
. prepare$ husky
└─ Done in 204ms
Done in 9.5s
All packages updated!
问题
如果您有任何问题或在为该项目做出贡献时遇到任何问题,请加入我们的 Discord 服务器。在 🙏-contributing
频道中与我们的贡献者联系。
问题
如果您有任何问题、错误或功能请求,请提交问题。在提交问题之前,请搜索问题存档以帮助减少重复,并阅读 常见问题解答。
如果您在那里找不到,您可以提交一个问题,您可以在其中提交
- 🐛错误报告:创建报告以帮助我们改进
- 📖文档:建议改进或报告缺少/不清楚的文档。
- 💡功能请求:为该模块提出一个想法。
- 💬问题:提问。
开发工作流程
要为该项目创建 PR 并开始贡献,请按照此分步指南操作
-
Fork 项目。
-
将项目克隆到您计算机上的某个位置
$ git clone https://github.com/webdriverio/visual-testing.git
-
转到目录并设置项目
$ cd visual-testing
$ corepack enable
$ corepack use [email protected]
$ pnpm pnpm.install.workaround -
运行监视模式,该模式将自动编译代码
$ pnpm watch
要构建项目,请运行
$ pnpm build
-
确保您的更改不会破坏任何测试,请运行
$ pnpm test
此项目使用 changesets 自动创建更改日志和版本。
测试
需要执行多个测试才能测试模块。添加 PR 时,所有测试至少必须通过本地测试。每个 PR 都会针对 Sauce Labs 自动进行测试,请参阅 我们的 GitHub Actions 管道。在批准 PR 之前,核心贡献者将针对模拟器/仿真器/真实设备测试 PR。
本地测试
首先,需要创建一个本地基线。这可以通过以下方式完成
// With the webdriver protocol
$ npm run test.local.init
此命令将创建一个名为 localBaseline
的文件夹,该文件夹将保存所有基线图像。
然后运行
// With the webdriver protocol
npm run test.local.desktop
这将在本地机器上的 Chrome 上运行所有测试。
本地 Storybook 运行器测试(Beta 版)
首先,需要创建一个本地基线。这可以通过以下方式完成
npm run test.local.desktop.storybook
这将在无头模式下使用 Chrome 对位于 https://govuk-react.github.io/govuk-react/ 的 Demo Storybook 存储库运行 Storybook 测试。
要使用更多浏览器运行测试,您可以运行
npm run test.local.desktop.storybook -- --browsers=chrome,firefox,edge,safari
[!注意] 确保您在本地机器上安装了要运行的浏览器
使用 Sauce Labs 进行 CI 测试(PR 不需要)
以下命令用于在 GitHub Actions 上测试构建,它只能在那里使用,不能用于本地开发。
$ npm run test.saucelabs
它将针对许多可以在 此处 找到的配置进行测试。所有 PR 都会自动针对 Sauce Labs 进行检查。
发布
要发布上面列出的任何包的版本,请执行以下操作
鸣谢
@wdio/visual-testing
使用 Sauce Labs 的开源许可证。