跳至主要內容

OCR 測試服務

@wdio/ocr-service 是一個第三方套件,如需更多資訊,請參閱 GitHub | npm

如需 WebdriverIO 視覺測試的文件,請參閱文件。此專案包含使用 WebdriverIO 執行視覺測試的所有相關模組。在 ./packages 目錄中,您會找到

  • @wdio/visual-testing:用於整合視覺測試的 WebdriverIO 服務
  • webdriver-image-comparison:一個影像比較模組,可用於支援 WebDriver 通訊協定的不同 NodeJS 測試自動化框架

Storybook Runner (BETA)

按一下以尋找關於 Storybook Runner BETA 的更多文件

Storybook Runner 仍在 BETA 版中,文件稍後將移至 WebdriverIO 文件頁面。

此模組現在透過新的 Visual Runner 支援 Storybook。此執行器會自動掃描本機/遠端 Storybook 執行個體,並建立每個組件的元素螢幕截圖。這可以透過新增

export const config: WebdriverIO.Config = {
// ...
services: ["visual"],
// ....
};

至您的 services 並透過命令列執行 npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook 來完成。它將使用 Chrome 在無頭模式下作為預設瀏覽器。

[!NOTE]

  • 大多數視覺測試選項也適用於 Storybook Runner,請參閱 WebdriverIO 文件。
  • Storybook Runner 將覆寫您所有的功能,且只能在它支援的瀏覽器上執行,請參閱 --browsers
  • Storybook Runner 不支援使用 Multiremote 功能的現有設定,並且會拋出錯誤。
  • Storybook Runner 僅支援桌面網路,不支援行動網路。

Storybook Runner 服務選項

可以這樣提供服務選項

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 Runner 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

它將使用提供的瀏覽器來擷取元件螢幕截圖

[!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 Runner 預設會建立元素快照,如果您想要查看完整的行動裝置模擬螢幕截圖,請透過命令列提供 --clip=false
  • 檔案名稱範例將類似於 __snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
  • SRC: 使用行動裝置模擬在桌上型電腦上測試行動網站可能很有用,但測試人員應注意,存在許多細微差異,例如
    • 完全不同的 GPU,這可能會導致效能發生重大變化;
    • 不會模擬行動裝置 UI(尤其是,隱藏網址列會影響頁面高度);
    • 不支援消除歧義的快顯視窗(您可以在其中選取幾個觸控目標之一);
    • 許多硬體 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
  • 或 regex ("/.*button.*/gm")

跳過某些故事。使用故事 URL 中可找到的故事 id。例如,在此 URL https://127.0.0.1:6006/?path=/story/example-page--logged-out 中的 idexample-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 執行個體所在網址。

--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`
);
});
});

在兩個不同的元件上執行了兩個測試。每個測試都會先設定一個狀態,然後截取螢幕快照。您也會注意到已引入一個新的自訂命令,可以在這裡找到。

上述的 spec 檔案可以儲存到一個資料夾中,並使用以下命令加入命令列

npm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'

Storybook 執行器會先自動掃描您的 Storybook 執行個體,然後將您的測試新增至需要比較的 stories。如果您不希望用於互動測試的元件被比較兩次,可以新增篩選器,藉由提供 --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' })

使用故事 URL 中可找到的故事 id。例如,在此 URL https://127.0.0.1:6006/?path=/story/example-page--logged-out 中的 idexample-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 執行個體所在網址。

貢獻

更新套件

您可以使用簡單的 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 此專案。

  • 在您電腦的某處 Clone 此專案

    $ git clone https://github.com/webdriverio/visual-testing.git
  • 前往該目錄並設定專案

    $ cd visual-testing
    $ corepack enable
    $ corepack use pnpm@8.x
    $ pnpm pnpm.install.workaround
  • 執行 watch 模式,它會自動轉換程式碼

    $ 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

[!NOTE] 請確保您在本機上已安裝要執行的瀏覽器

使用 Sauce Labs 進行 CI 測試(PR 不需要)

以下命令用於在 GitHub Actions 上測試建置,它只能在那裡使用,而不能用於本機開發。

$ npm run test.saucelabs

它將會針對許多組態進行測試,這些組態可以在 這裡找到。所有 PR 都會自動針對 Sauce Labs 檢查。

發佈

若要發佈上面列出的任何套件版本,請執行以下操作

  • 觸發發佈管道
  • 會產生一個發佈 PR,讓另一個 WebdriverIO 成員檢閱並核准它
  • 合併 PR
  • 再次觸發發佈管道
  • 應該會發佈新版本🎉

鳴謝

@wdio/visual-testing 使用 Sauce Labs 的開放原始碼授權。

歡迎!我能如何協助您?

WebdriverIO AI Copilot