メインコンテンツへスキップ

モック API

はじめに

Web API は通常、HTTP エンドポイントとして実装されます。Playwright は、HTTP および HTTPS の両方のネットワークトラフィックをモックおよび変更するための API を提供します。ページが行うリクエスト(XHRfetch リクエストなど)は、追跡、変更、およびモックが可能です。Playwright では、ページによって行われた複数のネットワークリクエストを含む HAR ファイルを使用してモックすることもできます。

API リクエストのモック

次のコードは、*/**/api/v1/fruits へのすべての呼び出しをインターセプトし、代わりにカスタムレスポンスを返します。API へのリクエストは行われません。テストは、モックされたルートを使用する URL にアクセスし、モックデータがページに存在することを確認します。

def test_mock_the_fruit_api(page: Page):
def handle(route: Route):
json = [{"name": "Strawberry", "id": 21}]
# fulfill the route with the mock data
route.fulfill(json=json)

# Intercept the route to the fruit API
page.route("*/**/api/v1/fruits", handle)

# Go to the page
page.goto("https://demo.playwright.dev/api-mocking")

# Assert that the Strawberry fruit is visible
expect(page.get_by_text("Strawberry")).to_be_visible()

サンプルテストのトレースから、API が一度も呼び出されず、モックデータで fulfilled されたことがわかります。api mocking trace

高度なネットワークの詳細はこちらをご覧ください。

API レスポンスの変更

再現性のあるテストを可能にするために、API リクエストを行う必要があるものの、レスポンスを修正する必要がある場合があります。その場合、リクエストをモックする代わりに、リクエストを実行し、変更されたレスポンスで fulfill することができます。

以下の例では、fruit API への呼び出しをインターセプトし、'Loquat' という新しいフルーツをデータに追加します。その後、URL にアクセスし、このデータがあることを確認します

def test_gets_the_json_from_api_and_adds_a_new_fruit(page: Page):
def handle(route: Route):
response = route.fetch()
json = response.json()
json.append({ "name": "Loquat", "id": 100})
# Fulfill using the original response, while patching the response body
# with the given JSON object.
route.fulfill(response=response, json=json)

page.route("https://demo.playwright.dev/api-mocking/api/v1/fruits", handle)

# Go to the page
page.goto("https://demo.playwright.dev/api-mocking")

# Assert that the new fruit is visible
expect(page.get_by_text("Loquat", exact=True)).to_be_visible()

テストのトレースでは、API が呼び出され、レスポンスが変更されたことがわかります。trace of test showing api being called and fulfilled

レスポンスを検査すると、新しいフルーツがリストに追加されたことがわかります。trace of test showing the mock response

高度なネットワークの詳細はこちらをご覧ください。

HAR ファイルを使用したモック

HAR ファイルは、ページがロードされたときに行われたすべてのネットワークリクエストの記録を含む HTTP Archive ファイルです。リクエストとレスポンスのヘッダー、クッキー、コンテンツ、タイミングなどの情報が含まれています。テストで HAR ファイルを使用してネットワークリクエストをモックできます。以下の手順が必要です。

  1. HAR ファイルを記録する。
  2. HAR ファイルをテストとともにコミットする。
  3. テストで保存された HAR ファイルを使用してリクエストをルーティングする。

HAR ファイルの記録

HAR ファイルを記録するには、page.route_from_har() または browser_context.route_from_har() メソッドを使用します。このメソッドは、HAR ファイルへのパスとオプションのオブジェクトを受け取ります。オプションオブジェクトには、URL を含めることができ、指定された glob パターンに一致する URL を持つリクエストのみが HAR ファイルから提供されます。指定しない場合、すべてのリクエストは HAR ファイルから提供されます。

update オプションを true に設定すると、リクエストを HAR ファイルから提供する代わりに、実際のネットワーク情報で HAR ファイルを作成または更新します。実際のデータで HAR を作成するテストを作成するときに使用します。

def test_records_or_updates_the_har_file(page: Page):
# Get the response from the HAR file
page.route_from_har("./hars/fruit.har", url="*/**/api/v1/fruits", update=True)

# Go to the page
page.goto("https://demo.playwright.dev/api-mocking")

# Assert that the fruit is visible
expect(page.get_by_text("Strawberry")).to_be_visible()

HAR ファイルの変更

HAR ファイルを記録したら、'hars' フォルダ内のハッシュ化された .txt ファイルを開き、JSON を編集することで変更できます。このファイルはソース管理にコミットする必要があります。update: true でこのテストを実行するたびに、API からのリクエストで HAR ファイルが更新されます。

[
{
"name": "Playwright",
"id": 100
},
// ... other fruits
]

HAR からのリプレイ

HAR ファイルを記録し、モックデータを変更したので、テストで一致するレスポンスを提供するために使用できます。これを行うには、update オプションをオフにするか、単に削除してください。これにより、API にアクセスする代わりに、HAR ファイルに対してテストが実行されます。

def test_gets_the_json_from_har_and_checks_the_new_fruit_has_been_added(page: Page):
# Replay API requests from HAR.
# Either use a matching response from the HAR,
# or abort the request if nothing matches.
page.route_from_har("./hars/fruit.har", url="*/**/api/v1/fruits", update=False)

# Go to the page
page.goto("https://demo.playwright.dev/api-mocking")

# Assert that the Playwright fruit is visible
expect(page.get_by_text("Playwright", exact=True)).to_be_visible()

テストのトレースでは、ルートが HAR ファイルから fulfilled され、API が呼び出されなかったことがわかります。trace showing the HAR file being used

レスポンスを検査すると、新しいフルーツが JSON に追加されたことがわかります。これは、hars フォルダ内のハッシュ化された .txt ファイルを手動で更新することで行われました。trace showing response from HAR file

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 で終わる場合、アーティファクトは個別のファイルとして書き込まれ、すべて 1 つの zip に圧縮されます。

# Save API requests from example.com as "example.har" archive.
playwright open --save-har=example.har --save-har-glob="**/api/**" https://example.com

高度なネットワークの詳細はこちらをご覧ください。

WebSocket のモック

次のコードは、WebSocket 接続をインターセプトし、サーバーに接続する代わりに、WebSocket を介した通信全体をモックします。この例では、"request""response" で応答します。

def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
ws.send("response")

page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
lambda message: message_handler(ws, message)
))

または、実際のサーバーに接続したいが、途中のメッセージをインターセプトして変更またはブロックしたい場合があります。これは、ページからサーバーに送信されたメッセージの一部を変更し、残りを変更しないままにする例です。

def message_handler(server: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
server.send("request2")
else:
server.send(message)

def handler(ws: WebSocketRoute):
server = ws.connect_to_server()
ws.on_message(lambda message: message_handler(server, message))

page.route_web_socket("wss://example.com/ws", handler)

詳細については、WebSocketRoute を参照してください。