インターセプトサービス
wdio-intercept-serviceはサードパーティのパッケージです。詳細については、GitHub | npmをご覧ください。
🕸 webdriver.ioでHTTP AJAXコールをキャプチャしてアサートします。
これはwebdriver.ioのプラグインです。まだご存知ない場合は、チェックしてみてください。かなりクールです。
seleniumとwebdriverは主にe2eとUIテストに使用されますが、クライアントコードによって行われたHTTPリクエストを評価したい場合があります(例:メトリックやトラッキングコールのように、UIフィードバックがすぐに得られない場合)。wdio-intercept-serviceを使用すると、ユーザーのアクション(ボタンのクリックなど)によって開始されたajax HTTPコールをインターセプトし、リクエストとそれに対応するレスポンスについて後でアサーションを実行できます。
ただし、1つ注意点があります。ページロード時に開始されるHTTPコール(ほとんどのSPAのように)をインターセプトすることはできません。これは、ページがロードされた後にのみ実行できるいくつかのセットアップ作業が必要になるためです(seleniumの制限のため)。つまり、テスト内で開始されたリクエストのみをキャプチャできます。それでも問題ない場合は、このプラグインが役立つ可能性があるため、読み進めてください。
前提条件
- webdriver.io v5.x以降。
ご注意ください!webdriver.io v4をまだ使用している場合は、このプラグインのv2.xブランチを使用してください!
インストール
npm install wdio-intercept-service -D
使用法
WebDriver CLIでの使用法
wdio.conf.jsにwdio-intercept-serviceを追加するだけで簡単です。
exports.config = {
  // ...
  services: ['intercept']
  // ...
};
これで完了です。
WebDriver Standaloneでの使用法
WebdriverIO Standaloneを使用する場合、beforeおよびbeforeTest / beforeScenario関数を手動で呼び出す必要があります。
import { remote } from 'webdriverio';
import WebdriverAjax from 'wdio-intercept-service'
const WDIO_OPTIONS = {
  port: 9515,
  path: '/',
  capabilities: {
    browserName: 'chrome'
  },
}
let browser;
const interceptServiceLauncher = WebdriverAjax();
beforeAll(async () => {
  browser = await remote(WDIO_OPTIONS)
  interceptServiceLauncher.before(null, null, browser)
})
beforeEach(async () => {
  interceptServiceLauncher.beforeTest()
})
afterAll(async () => {
  await client.deleteSession()
});
describe('', async () => {
  ... // See example usage
});
初期化されると、ブラウザコマンドチェーンにいくつかの関連関数が追加されます(APIを参照)。
クイックスタート
使用例
browser.url('http://foo.bar');
browser.setupInterceptor(); // capture ajax calls
browser.expectRequest('GET', '/api/foo', 200); // expect GET request to /api/foo with 200 statusCode
browser.expectRequest('POST', '/api/foo', 400); // expect POST request to /api/foo with 400 statusCode
browser.expectRequest('GET', /\/api\/foo/, 200); // can validate a URL with regex, too
browser.click('#button'); // button that initiates ajax request
browser.pause(1000); // maybe wait a bit until request is finished
browser.assertRequests(); // validate the requests
リクエストの詳細を取得する
browser.url('http://foo.bar')
browser.setupInterceptor();
browser.click('#button')
browser.pause(1000);
var request = browser.getRequest(0);
assert.equal(request.method, 'GET');
assert.equal(request.response.headers['content-length'], '42');
サポートされているブラウザ
比較的新しいバージョンのすべてのブラウザで動作するはずです。お使いのブラウザで動作しない場合は、問題を報告してください。
API
WebdriverIOブラウザオブジェクトに追加されたカスタムコマンドの完全な構文については、TypeScript宣言ファイルを参照してください。一般的に、「options」オブジェクトをパラメータとして取るメソッドは、デフォルトの動作を取得するためにそのパラメータなしで呼び出すことができます。これらの「オプションのオプション」オブジェクトには?: = {}が続き、推測されるデフォルト値は各メソッドで説明されています。
オプションの説明
このライブラリは、コマンド発行時にわずかな構成を提供します。複数のメソッドで使用される構成オプションを以下に説明します(具体的なサポートを判断するには、各メソッドの定義を参照してください)。
- orderBy(- 'START' | 'END'): このオプションは、テストに返されるときにインターセプターによってキャプチャされたリクエストの順序を制御します。このライブラリの既存のバージョンとの下位互換性のため、デフォルトの順序は- 'END'で、リクエストが完了した時点に対応します。- orderByオプションを- 'START'に設定すると、リクエストは開始された時間に従って順序付けられます。
- includePending(- boolean): このオプションは、まだ完了していないリクエストを返すかどうかを制御します。このライブラリの既存のバージョンとの下位互換性のため、デフォルト値は- falseであり、完了したリクエストのみが返されます。
browser.setupInterceptor()
ブラウザでajaxコールをキャプチャします。後でリクエストを評価するために、常にセットアップ関数を呼び出す必要があります。
browser.disableInterceptor()
ブラウザでのajaxコールのそれ以上のキャプチャを防ぎます。キャプチャされたすべてのリクエスト情報は削除されます。ほとんどのユーザーはインターセプターを無効にする必要はありませんが、テストが特に長時間実行されている場合や、セッションストレージ容量を超えている場合は、インターセプターを無効にすると役立ちます。
browser.excludeUrls(urlRegexes: (string | RegExp)[])
特定のURLからのリクエストが記録されないように除外します。文字列または正規表現の配列を受け取ります。ストレージに書き込む前に、リクエストのURLを各文字列または正規表現に対してテストします。一致した場合、リクエストはストレージに書き込まれません。disableInterceptorと同様に、セッションストレージが容量を超えている問題が発生した場合に役立ちます。
browser.expectRequest(method: string, url: string, statusCode: number)
テスト中に開始されるajaxリクエストについて期待を設定します。チェーン可能(およびそうすべき)です。期待の順序は、実行されるリクエストの順序に対応する必要があります。
- method(- String): 期待されるHTTPメソッド。- xhr.open()が最初の引数として受け入れるものなら何でも使用できます。
- url(- String|- RegExp): リクエストで呼び出される正確なURL。文字列または一致させる正規表現として指定します
- statusCode(- Number): レスポンスの期待されるステータスコード
browser.getExpectations()
ヘルパーメソッド。その時点までに設定したすべての期待を返します。
browser.resetExpectations()
ヘルパーメソッド。その時点までに設定したすべての期待をリセットします。
browser.assertRequests({ orderBy?: 'START' | 'END' }?: = {})
期待されるすべてのajaxリクエストが完了したときに、このメソッドを呼び出します。期待と実際のリクエストを比較し、以下をアサートします。
- 実行されたリクエストの数
- リクエストの順序
- すべてのリクエストに対して、メソッド、URL、およびステータスコードが一致する必要があります。
- オプションオブジェクトのデフォルトは{ orderBy: 'END' }です。つまり、v4.1.10以前の動作と一貫性を保つために、リクエストが完了した時点です。orderByオプションが'START'に設定されている場合、リクエストはページによって開始された順序で並べられます。
browser.assertExpectedRequestsOnly({ inOrder?: boolean, orderBy?: 'START' | 'END' }?: = {})
browser.assertRequests と似ていますが、expectRequest ディレクティブで指定したリクエストのみを検証し、その周辺で発生する可能性のあるすべてのネットワークリクエストをマッピングする必要はありません。inOrder オプションが true (デフォルト) の場合、リクエストは expectRequest で設定された順序と同じ順序で見つかることが期待されます。
browser.getRequest(index: number, { includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})
特定のリクエストについてより高度なアサーションを行うには、特定のリクエストの詳細を取得できます。アクセスしたいリクエストの 0 から始まるインデックスを、リクエストが完了した順序 (デフォルト) または開始された順序 (orderBy: 'START' オプションを渡す) で指定する必要があります。
- index(- number): アクセスしたいリクエストの番号
- options(- object): 設定オプション
- options.includePending(- boolean): 未完了のリクエストを返すかどうか。デフォルトでは、v4.1.10 以前のライブラリの動作に合わせて、false に設定されています。
- options.orderBy(- 'START' | 'END'): リクエストをどのように順序付けするか。デフォルトでは、v4.1.10 以前のライブラリの動作に合わせて、- 'END'に設定されています。- 'START'の場合、リクエストはリクエスト完了時間ではなく、開始時間で順序付けられます。(保留中のリクエストはまだ完了していないため、- 'END'で順序付けすると、保留中のリクエストはすべて完了したリクエストの後に来ます。)
戻り値 request オブジェクト
- request.url: リクエストされた URL
- request.method: 使用された HTTP メソッド
- request.body: リクエストで使用されたペイロード/ボディデータ
- request.headers: リクエストの HTTP ヘッダー (JS オブジェクトとして)
- request.pending: このリクエストが完了している (つまり、- responseプロパティを持っている) か、処理中であるかを示す boolean フラグ。
- request.response: リクエストが完了した場合にのみ存在する JS オブジェクト (つまり、- request.pending === false)、レスポンスに関するデータが含まれています。
- request.response?.headers: レスポンスの HTTP ヘッダー (JS オブジェクトとして)
- request.response?.body: レスポンスボディ (可能な場合は JSON として解析されます)
- request.response?.statusCode: レスポンスステータスコード
request.body に関する注意: wdio-intercept-service は、次のようにリクエストボディを解析しようとします。
- string: 文字列をそのまま返す ('value')
- JSON: JSON.parse()を使用して JSON オブジェクトを解析する (({ key: value }))
- FormData: { key: [value1, value2, ...] }の形式で FormData を出力する
- ArrayBuffer: バッファを文字列に変換しようとする (実験的)
- その他: データに対して強引に JSON.stringify()を使用する。幸運を祈ります!
fetch API の場合、文字列と JSON データのみをサポートしています!
browser.getRequests({ includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})
キャプチャされたすべてのリクエストを配列として取得します。getRequest と同じオプションのオプションをサポートしています。
戻り値 request オブジェクトの配列。
browser.hasPendingRequests()
まだ保留中の HTTP リクエストがあるかどうかを確認するユーティリティメソッド。テストで、すべてのリクエストが妥当な時間内に完了したことを確認したり、getRequests() または assertRequests() の呼び出しに、目的のすべての HTTP リクエストが含まれることを検証するために使用できます。
戻り値 boolean
TypeScript のサポート
このプラグインは独自の TS 型を提供します。ここに記載されているように、tsconfig を型拡張に向けるだけです こちら
"compilerOptions": {
    // ..
    "types": ["node", "webdriverio", "wdio-intercept-service"]
},
テストの実行
ローカルでテストを実行するには、Chrome と Firefox の最新バージョンが必要です。システムにインストールされているバージョンに合わせて、chromedriver および geckodriver の依存関係を更新する必要がある場合があります。
npm test
貢献
すべての貢献を歓迎します。Issue をオープンするか、直接 PR を提出してください。
このインターセプターライブラリは、Internet Explorer などのレガシーブラウザーで動作するように作成されていることに注意してください。そのため、lib/interceptor.js で使用されるコードは、少なくとも Internet Explorer の JavaScript ランタイムで解析可能である必要があります。
ライセンス
MIT