モックAPI
はじめに
Web APIは通常、HTTPエンドポイントとして実装されています。Playwrightは、HTTPとHTTPSの両方のネットワークトラフィックを**モック**したり**変更**したりするためのAPIを提供します。ページが行うあらゆるリクエスト(XHRやfetchリクエストを含む)を追跡、変更、モックすることができます。Playwrightを使用すると、ページによって行われた複数のネットワークリクエストを含むHARファイルを使用してモックすることもできます。
APIリクエストのモック
以下のコードは、`*/**/api/v1/fruits`へのすべての呼び出しをインターセプトし、代わりにカスタムレスポンスを返します。APIへのリクエストは行われません。テストはモックされたルートを使用するURLに移動し、モックデータがページに存在することを確認します。
// Intercept the route to the fruit API
await page.RouteAsync("*/**/api/v1/fruits", async route => {
var json = new[] { new { name = "Strawberry", id = 21 } };
// fulfill the route with the mock data
await route.FulfillAsync(new()
{
Json = json
});
});
// Go to the page
await page.GotoAsync("https://demo.playwright.dev/api-mocking");
// Assert that the Strawberry fruit is visible
await Expect(page.GetByTextAsync("Strawberry")).ToBeVisibleAsync();
例のテストのトレースから、APIが呼び出されず、モックデータで応答されたことがわかります。
高度なネットワークについて詳しくはこちらをご覧ください。
APIレスポンスの変更
再現性のあるテストを行うには、APIリクエストを行うことが不可欠ですが、レスポンスをパッチ適用する必要がある場合があります。その場合、リクエストをモックする代わりに、実際にリクエストを実行し、変更されたレスポンスで応答させることができます。
以下の例では、フルーツAPIへの呼び出しをインターセプトし、データに「ビワ」という新しいフルーツを追加します。その後、URLに移動し、このデータが存在することを確認します。
await page.RouteAsync("*/**/api/v1/fruits", async (route) => {
var response = await route.FetchAsync();
var fruits = await response.JsonAsync<Fruit[]>();
fruits.Add(new Fruit() { Name = "Loquat", Id = 100 });
// Fulfill using the original response, while patching the response body
// with the given JSON object.
await route.FulfillAsync(new ()
{
Response = response,
Json = fruits
});
}
);
// Go to the page
await page.GotoAsync("https://demo.playwright.dev/api-mocking");
// Assert that the Loquat fruit is visible
await Expect(page.GetByTextAsync("Loquat", new () { Exact = true })).ToBeVisibleAsync();
テストのトレースでは、APIが呼び出され、レスポンスが変更されたことがわかります。
レスポンスを検査すると、新しいフルーツがリストに追加されたことがわかります。
高度なネットワークについて詳しくはこちらをご覧ください。
HARファイルを使用したモック
HARファイルは、ページが読み込まれたときに行われるすべてのネットワークリクエストの記録を含むHTTPアーカイブファイルです。これには、リクエストとレスポンスのヘッダー、Cookie、コンテンツ、タイミングなどの情報が含まれています。HARファイルを使用して、テストでネットワークリクエストをモックすることができます。次の手順を実行する必要があります。
- HARファイルを記録する。
- テストと一緒にHARファイルをコミットする。
- テストで保存されたHARファイルを使用してリクエストをルーティングする。
HARファイルの記録
HARファイルを記録するには、Page.RouteFromHARAsync()またはBrowserContext.RouteFromHARAsync()メソッドを使用します。このメソッドは、HARファイルへのパスとオプションのオブジェクトを受け取ります。オプションオブジェクトにはURLを含めることができ、指定されたグロブパターンに一致するURLを持つリクエストのみがHARファイルから提供されます。指定されていない場合、すべてのリクエストがHARファイルから提供されます。
`update`オプションをtrueに設定すると、HARファイルからリクエストを提供せずに、実際のネットワーク情報でHARファイルが作成または更新されます。テストを作成する際に、HARに実際のデータを投入するために使用します。
// Get the response from the HAR file
await page.RouteFromHARAsync("./hars/fruit.har", new () {
Url = "*/**/api/v1/fruits",
Update = true,
});
// Go to the page
await page.GotoAsync("https://demo.playwright.dev/api-mocking");
// Assert that the fruit is visible
await Expect(page.GetByText("Strawberry")).ToBeVisibleAsync();
HARファイルの変更
HARファイルを記録したら、「hars」フォルダ内のハッシュ化された.txtファイルを開いてJSONを編集することで変更できます。このファイルはソース管理にコミットする必要があります。`update: true`を指定してこのテストを実行するたびに、APIからのリクエストでHARファイルが更新されます。
[
{
"name": "Playwright",
"id": 100
},
// ... other fruits
]
HARからのリプレイ
HARファイルを記録し、モックデータを変更したので、テストで一致するレスポンスを提供するために使用できます。そのためには、`update`オプションをオフにするか、単に削除します。これにより、APIにアクセスする代わりにHARファイルに対してテストが実行されます。
// Replay API requests from HAR.
// Either use a matching response from the HAR,
// or abort the request if nothing matches.
await page.RouteFromHARAsync("./hars/fruit.har", new ()
{
Url = "*/**/api/v1/fruits",
Update = false,
}
);
// Go to the page
await page.GotoAsync("https://demo.playwright.dev/api-mocking");
// Assert that the Playwright fruit is visible
await page.ExpectByTextAsync("Playwright", new() { Exact = true }).ToBeVisibleAsync();
テストのトレースでは、ルートがHARファイルから応答され、APIが呼び出されなかったことがわかります。
レスポンスを検査すると、新しいフルーツがJSONに追加されたことがわかります。これは、`hars`フォルダ内のハッシュ化された`.txt`ファイルを手動で更新することで行われました。
HARのリプレイは、URLとHTTPメソッドに厳密に一致します。POSTリクエストの場合、POSTペイロードも厳密に一致させます。複数の記録がリクエストに一致する場合、最も多くのヘッダーが一致するものが選択されます。リダイレクトが発生するエントリは自動的に追跡されます。
記録時と同様に、指定されたHARファイル名が`.zip`で終わる場合、HARファイルと個別のエントリとして保存されたネットワークペイロードを含むアーカイブと見なされます。このアーカイブを解凍し、ペイロードまたはHARログを手動で編集して、解凍されたHARファイルを指すこともできます。すべてのペイロードは、ファイルシステム上の解凍されたHARファイルからの相対パスで解決されます。
CLIでのHARの記録
テスト用のHARファイルを記録するには、`update`オプションを推奨します。ただし、Playwright CLIを使用してHARを記録することもできます。
Playwright CLIでブラウザを開き、`--save-har`オプションを渡してHARファイルを生成します。オプションとして、`--save-har-glob`を使用して、APIエンドポイントなど、関心のあるリクエストのみを保存できます。HARファイル名が`.zip`で終わる場合、アーティファクトは個別のファイルとして書き込まれ、すべて単一の`zip`に圧縮されます。
# Save API requests from example.com as "example.har" archive.
pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com
高度なネットワークについて詳しくはこちらをご覧ください。
WebSocketのモック
以下のコードは、WebSocket接続をインターセプトし、サーバーに接続する代わりにWebSocket上の通信全体をモックします。この例では、`"request"`に対して`"response"`で応答します。
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
ws.OnMessage(frame => {
if (frame.Text == "request")
ws.Send("response");
});
});
あるいは、実際のサーバーに接続しつつ、その途中でメッセージをインターセプトして変更したりブロックしたりしたい場合もあるでしょう。以下は、ページからサーバーに送信されたメッセージの一部を変更し、残りを未変更のままにする例です。
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
var server = ws.ConnectToServer();
ws.OnMessage(frame => {
if (frame.Text == "request")
server.Send("request2");
else
server.Send(frame.Text);
});
});
詳細については、WebSocketRouteを参照してください。