Mock 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
page.route("https://fruit.ceo/api/breeds/image/random", route -> {
List<Dictionary<String, Object>> data = new ArrayList<Dictionary<String, Object>>();
Hashtable<String, Object> dict = new Hashtable<String, Object>();
dict.put("name", "Strawberry");
dict.put("id", 21);
data.add(dict);
// fulfill the route with the mock data
route.fulfill(RequestOptions.create().setData(data));
});
// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");
// Assert that the Strawberry fruit is visible
assertThat(page.getByText("Strawberry")).isVisible();
テスト例のトレースから、API が一度も呼び出されず、モックデータで処理されたことがわかります。
高度なネットワーキングの詳細をご覧ください。
API レスポンスの変更
場合によっては、API リクエストを行うことが不可欠ですが、再現性のあるテストを可能にするためにレスポンスを修正する必要があります。その場合、リクエストをモックする代わりに、リクエストを実行し、変更されたレスポンスで処理できます。
次の例では、フルーツ API への呼び出しをインターセプトし、'Loquat' という新しいフルーツをデータに追加します。次に、URL に移動し、このデータが存在することを確認します。
page.route("*/**/api/v1/fruits", route -> {
Response response = route.fetch();
byte[] json = response.body();
JsonObject parsed = new Gson().fromJson(new String(json), JsonObject.class);
parsed.add(new JsonObject().add("name", "Loquat").add("id", 100));
// Fulfill using the original response, while patching the response body
// with the given JSON object.
route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(parsed.toString()));
});
// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");
// Assert that the Loquat fruit is visible
assertThat(page.getByText("Loquat", new Page.GetByTextOptions().setExact(true))).isVisible();
テストのトレースでは、API が呼び出され、レスポンスが変更されたことがわかります。
レスポンスを調べると、新しいフルーツがリストに追加されたことがわかります。
高度なネットワーキングの詳細をご覧ください。
HAR ファイルを使用したモック
HAR ファイルは、ページがロードされたときに行われたすべてのネットワークリクエストの記録を含む HTTP Archive ファイルです。リクエストとレスポンスのヘッダー、Cookie、コンテンツ、タイミングなどに関する情報が含まれています。HAR ファイルを使用して、テストでネットワークリクエストをモックできます。次の手順が必要です。
- HAR ファイルを記録します。
- HAR ファイルをテストとともにコミットします。
- テストで保存された HAR ファイルを使用してリクエストをルーティングします。
HAR ファイルの記録
HAR ファイルを記録するには、Page.routeFromHAR() または BrowserContext.routeFromHAR() メソッドを使用します。このメソッドは、HAR ファイルへのパスとオプションのオプションオブジェクトを受け取ります。オプションオブジェクトには URL を含めることができ、指定されたグロブパターンに一致する URL を持つリクエストのみが HAR ファイルから提供されます。指定しない場合、すべてのリクエストは HAR ファイルから提供されます。
update
オプションを true に設定すると、リクエストを HAR ファイルから提供する代わりに、実際のネットワーク情報で HAR ファイルが作成または更新されます。テストを作成して、実際のデータで HAR を設定する場合に使用します。
// Get the response from the HAR file
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(true)
);
// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");
// Assert that the fruit is visible
assertThat(page.getByText("Strawberry")).isVisible();
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.
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(false)
);
// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");
// Assert that the Playwright fruit is visible
assertThat(page.getByText("Playwright", new Page.GetByTextOptions()
.setExact(true))).isVisible();
テストのトレースでは、ルートが 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.
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="open --save-har=example.har --save-har-glob='**/api/**' https://example.com"
高度なネットワーキングの詳細をご覧ください。
WebSocket のモック
次のコードは、WebSocket 接続をインターセプトし、サーバーに接続する代わりに、WebSocket 経由の通信全体をモックします。この例では、"request"
に "response"
で応答します。
page.routeWebSocket("wss://example.com/ws", ws -> {
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
ws.send("response");
});
});
または、実際のサーバーに接続したいが、メッセージを途中でインターセプトして変更またはブロックしたい場合があります。ページからサーバーに送信されたメッセージの一部を変更し、残りを変更しないままにする例を次に示します。
page.routeWebSocket("wss://example.com/ws", ws -> {
WebSocketRoute server = ws.connectToServer();
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
server.send("request2");
else
server.send(frame.text());
});
});
詳細については、WebSocketRoute を参照してください。