リクエストモックとスパイ
WebdriverIOには、バックエンドやモックサーバーをセットアップすることなく、フロントエンドアプリケーションのテストに集中できるようにするネットワークレスポンスを変更するための組み込みサポートがあります。テスト内でREST APIリクエストなどのウェブリソースに対するカスタムレスポンスを定義し、動的に変更することができます。
mock
コマンドを使用するにはChrome DevToolsプロトコルのサポートが必要であることに注意してください。このサポートは、Chromiumベースのブラウザでローカルにテストを実行する場合、Selenium Grid v4以上を介して、またはChrome DevToolsプロトコルをサポートするクラウドベンダー(SauceLabs、BrowserStack、LambdaTestなど)を通じて提供されます。完全なクロスブラウザサポートは、必要なプリミティブがWebdriver Bidiで利用可能になり、それぞれのブラウザで実装された時点で提供されます。
モックの作成
レスポンスを変更する前に、まずモックを定義する必要があります。このモックはリソースURLによって記述され、リクエストメソッドやヘッダーによってフィルタリングできます。リソースはminimatchによるグロブ式をサポートしています:
// "/users/list"で終わるすべてのリソースをモック
const userListMock = await browser.mock('**/users/list')
// またはヘッダーやステータスコードでリソースをフィルタリングしてモックを指定できます
// JSONリソースへの成功したリクエストだけをモック
const strictMock = await browser.mock('**', {
// すべてのJSONレスポンスをモック
requestHeaders: { 'Content-Type': 'application/json' },
// 成功したものだけ
statusCode: 200
})
カスタムレスポンスの指定
モックを定義したら、そのモックに対してカスタムレスポンスを定義できます。これらのカスタムレスポンスは、JSONを返すオブジェクト、カスタムフィクスチャで応答するローカルファイル、またはインターネットからのリソースでレスポンスを置き換えるウェブリソ ースのいずれかです。
APIリクエストのモック
JSONレスポンスを期待するAPIリクエストをモックするには、モックオブジェクトに対してrespond
を呼び出し、返したい任意のオブジェクトを渡すだけです:
const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/')
mock.respond([{
title: 'Injected (non) completed Todo',
order: null,
completed: false
}, {
title: 'Injected completed Todo',
order: null,
completed: true
}], {
headers: {
'Access-Control-Allow-Origin': '*'
},
fetchResponse: false
})
await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')
await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li').map(el => el.getText()))
// 出力: "[ 'Injected (non) completed Todo', 'Injected completed Todo' ]"
また、以下のようにモックレスポンスパラメータを渡すことで、レスポンスヘッダーとステータスコードも変更できます:
mock.respond({ ... }, {
// ステータスコード404で応答
statusCode: 404,
// 以下のヘッダーでレスポンスヘッダーをマージ
headers: { 'x-custom-header': 'foobar' }
})
モックがバックエンドを呼び出さないようにするには、fetchResponse
フラグにfalse
を渡すことができます。
mock.respond({ ... }, {
// 実際のバックエンドを呼び出さない
fetchResponse: false
})
カスタムレスポンスはフィクスチャファイルに保存し、テスト内で以下のように要求することをお勧めします:
// JSON importアサーションをサポートするにはNode.js v16.14.0以上が必要
import responseFixture from './__fixtures__/apiResponse.json' assert { type: 'json' }
mock.respond(responseFixture)
テキストリソースのモック
JavaScript、CSSファイルなどのテキストベースのリソースを変更したい場合は、ファイルパスを渡すだけでWebdriverIOが元のリソースを置き換えます:
const scriptMock = await browser.mock('**/script.min.js')
scriptMock.respond('./tests/fixtures/script.js')
// または独自のJSで応答
scriptMock.respond('alert("I am a mocked resource")')