メインコンテンツにスキップ

OCRテストサービス

@wdio/ocr-serviceはサードパーティ製のパッケージです。詳細については、GitHub | npmを参照してください。

WebdriverIOでのビジュアルテストに関するドキュメントについては、ドキュメントを参照してください。このプロジェクトには、WebdriverIOでビジュアルテストを実行するためのすべての関連モジュールが含まれています。./packagesディレクトリ内には以下があります。

  • @wdio/visual-testing:ビジュアルテストを統合するためのWebdriverIOサービス
  • webdriver-image-comparison:WebDriverプロトコルをサポートするさまざまなNodeJSテスト自動化フレームワークで使用できる画像比較モジュール

Storybookランナー(ベータ版)

Storybookランナー(ベータ版)に関する詳細なドキュメントについては、こちらをクリックしてください。

Storybookランナーはまだベータ版です。ドキュメントは後でWebdriverIOドキュメントページに移動します。

このモジュールは、新しいビジュアルランナーでStorybookをサポートするようになりました。このランナーは、ローカル/リモートのStorybookインスタンスを自動的にスキャンし、各コンポーネントの要素スクリーンショットを作成します。これは、以下を追加することで実行できます。

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

servicesに、コマンドラインからnpx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybookを実行します。デフォルトのブラウザとしてヘッドレスモードでChromeを使用します。

[!NOTE]

  • ほとんどのビジュアルテストオプションは、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
  • 必須: いいえ
  • デフォルト: chromechrome|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以外のブラウザも指定すると、モバイルエミュレーションモードでChromeが自動的に追加されます
  • Storybookランナーはデフォルトで要素のスナップショットを作成します。モバイルエミュレートされたスクリーンショット全体を表示したい場合は、コマンドラインから--clip=falseを指定してください
  • ファイル名は、たとえば__snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.pngのようになります
  • SRC: モバイルエミュレーションを使用してデスクトップでモバイルWebサイトをテストすることは便利ですが、テスターは次のような多くの微妙な違いがあることを認識しておく必要があります。
    • パフォーマンスに大きな変化をもたらす可能性のある、まったく異なるGPU。
    • モバイルUIはエミュレートされていません(特に、URLバーの非表示はページの高​​さに影響します)。
    • あいまいさのポップアップ(いくつかのタッチターゲットの1つを選択する場合)はサポートされていません。
    • 多くのハードウェア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-outidexample-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`
);
});
});

2つの異なるコンポーネントで2つのテストが実行されます。各テストは最初に状態を設定し、次にスクリーンショットを撮ります。また、新しいカスタムコマンドが導入されていることにも気付くでしょう。これはこちらにあります。

上記のスペックファイルをフォルダーに保存し、次のコマンドでコマンドラインに追加できます。

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

Storybookランナーは最初にStorybookインスタンスを自動的にスキャンし、比較する必要のあるストーリーにテストを追加します。インタラクションテストに使用するコンポーネントを2回比較したくない場合は、--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 http://localhost:6006/?path=/story/example-page--logged-outidexample-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チャンネルで捕まえてください。

問題

質問、バグ、または機能のリクエストがある場合は、問題を提出してください。問題を提出する前に、重複を減らすために問題アーカイブを検索し、FAQをお読みください。

そこに見つからない場合は、問題を提出することができます。そこでは、次を提出できます。

  • 🐛バグレポート:改善に役立つレポートを作成してください
  • 📖ドキュメント:改善を提案するか、欠落/不明確なドキュメントを報告してください。
  • 💡機能リクエスト:このモジュールのアイデアを提案してください。
  • 💬質問:質問をしてください。

開発ワークフロー

このプロジェクトのPRを作成し、貢献を開始するには、次のステップバイステップガイドに従ってください。

  • プロジェクトをフォークします。

  • コンピューターのどこかにプロジェクトをクローンします。

    $ git clone https://github.com/webdriverio/visual-testing.git
  • ディレクトリに移動して、プロジェクトをセットアップします。

    $ cd visual-testing
    $ corepack enable
    $ corepack use pnpm@8.x
    $ 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ランナーテスト(ベータ版)

まず、ローカルベースラインを作成する必要があります。これは次のようにして行うことができます。

npm run test.local.desktop.storybook

これにより、https://govuk-react.github.io/govuk-react/にあるデモStorybookリポジトリに対して、ヘッドレスモードのChromeで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