本文へ移動

Web Extension テスト

WebdriverIO はブラウザを自動化するのに最適なツールです。Web Extensions はブラウザの一部であり、同じ方法で自動化できます。Web Extension がコンテンツスクリプトを使用してウェブサイトで JavaScript を実行したり、ポップアップモーダルを提供したりする場合、WebdriverIO を使用して e2e テストを実行できます。

ブラウザへの Web Extension の読み込み

最初のステップとして、テスト対象の拡張機能をセッションの一部としてブラウザに読み込む必要があります。これは Chrome と Firefox で異なります。

情報

これらのドキュメントでは、Safari Web Extensions はサポートが遅れており、ユーザーからの需要も高くないため省略しています。Safari 用の Web Extension を構築している場合は、問題を提起し、ここに含めることについて共同作業してください。

Chrome

Chrome で Web Extension を読み込むには、crx ファイルの base64 エンコードされた文字列を提供するか、Web Extension フォルダーへのパスを提供します。後者の方法が最も簡単で、Chrome の機能を次のように定義します。

import path from 'node:path'
import url from 'node:url'

const __dirname = url.fileURLToPath(new URL('.', import.meta.url))

export const config = {
// ...
capabilities: [{
browserName,
'goog:chromeOptions': {
// given your wdio.conf.js is in the root directory and your compiled
// web extension files are located in the `./dist` folder
args: [`--load-extension=${path.join(__dirname, '..', '..', 'dist')}`]
}
}]
}
情報

Chrome 以外のブラウザ(例:Brave、Edge、Opera)を自動化する場合は、ブラウザオプションが上記の例と一致する可能性が高く、異なる機能名(例:ms:edgeOptions)を使用するだけです。

例として crx NPM パッケージを使用して拡張機能を .crx ファイルとしてコンパイルする場合は、次のようにバンドルされた拡張機能を挿入することもできます。

import path from 'node:path'
import url from 'node:url'

const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const extPath = path.join(__dirname, `web-extension-chrome.crx`)
const chromeExtension = (await fs.readFile(extPath)).toString('base64')

export const config = {
// ...
capabilities: [{
browserName,
'goog:chromeOptions': {
extensions: [chromeExtension]
}
}]
}

Firefox

拡張機能を含む Firefox プロファイルを作成するには、Firefox プロファイルサービス を使用してセッションを適切に設定します。ただし、署名に関する問題により、ローカルで開発した拡張機能を読み込めなくなる場合があります。この場合、installAddOn コマンドを使用して before フックで拡張機能を読み込むこともできます。例:

import path from 'node:path'
import url from 'node:url'

const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const extensionPath = path.resolve(__dirname, `web-extension.xpi`)

export const config = {
// ...
before: async (capabilities) => {
const browserName = (capabilities as WebdriverIO.Capabilities).browserName
if (browserName === 'firefox') {
const extension = await fs.readFile(extensionPath)
await browser.installAddOn(extension.toString('base64'), true)
}
}
}

.xpi ファイルを生成するには、web-ext NPM パッケージの使用をお勧めします。次のコマンド例を使用して拡張機能をバンドルできます。

npx web-ext build -s dist/ -a . -n web-extension-firefox.xpi

ヒントとコツ

次のセクションには、Web Extension のテストに役立つ便利なヒントとコツが記載されています。

Chrome でのポップアップモーダルのテスト

拡張機能マニフェストdefault_popup ブラウザアクションエントリを定義した場合、ブラウザの上部バーの拡張機能アイコンをクリックしても機能しないため、その HTML ページを直接テストできます。代わりに、ポップアップの HTML ファイルを直接開く必要があります。

Chrome では、拡張機能 ID を取得し、browser.url('...') を使用してポップアップページを開くことで機能します。そのページでの動作は、ポップアップ内と同じになります。そのためには、次のカスタムコマンドを作成することをお勧めします。

export async function openExtensionPopup (this: WebdriverIO.Browser, extensionName: string, popupUrl = 'index.html') {
if ((this.capabilities as WebdriverIO.Capabilities).browserName !== 'chrome') {
throw new Error('This command only works with Chrome')
}
await this.url('chrome://extensions/')

const extensions = await this.$$('extensions-item')
const extension = await extensions.find(async (ext) => (
await ext.$('#name').getText()) === extensionName
)

if (!extension) {
const installedExtensions = await extensions.map((ext) => ext.$('#name').getText())
throw new Error(`Couldn't find extension "${extensionName}", available installed extensions are "${installedExtensions.join('", "')}"`)
}

const extId = await extension.getAttribute('id')
await this.url(`chrome-extension://${extId}/popup/${popupUrl}`)
}

declare global {
namespace WebdriverIO {
interface Browser {
openExtensionPopup: typeof openExtensionPopup
}
}
}

wdio.conf.js でこのファイルを読み込み、before フックでカスタムコマンドを登録できます。例:

import { browser } from '@wdio/globals'

import { openExtensionPopup } from './support/customCommands'

export const config: WebdriverIO.Config = {
// ...
before: () => {
browser.addCommand('openExtensionPopup', openExtensionPopup)
}
}

これで、テストで次のようにポップアップページにアクセスできます。

await browser.openExtensionPopup('My Web Extension')

ようこそ!お手伝いできることはありますか?

WebdriverIO AI Copilot