ネットワーク
導入
Playwright は、HTTP と HTTPS の両方のブラウザネットワークトラフィックを監視および変更するための API を提供します。ページが行うすべてのリクエスト ( XHR や fetch リクエストを含む) は、追跡、変更、および処理できます。
API のモック
API をモックする方法の詳細については、API モックガイドをご覧ください。
- API リクエストをモックして、API にアクセスしないようにする
- API リクエストを実行して、レスポンスを修正する
- HAR ファイルを使用してネットワークリクエストをモックする。
ネットワークモック
ネットワークリクエストをモックするために何かを設定する必要はありません。ブラウザコンテキストのネットワークをモックするカスタム Route を定義するだけです。
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ context }) => {
// Block any css requests for each test in this file.
await context.route(/.css$/, route => route.abort());
});
test('loads page without css', async ({ page }) => {
await page.goto('https://playwright.dokyumento.jp');
// ... test goes here
});
または、page.route() を使用して、単一ページでネットワークをモックすることもできます。
import { test, expect } from '@playwright/test';
test('loads page without images', async ({ page }) => {
// Block png and jpeg images.
await page.route(/(png|jpeg)$/, route => route.abort());
await page.goto('https://playwright.dokyumento.jp');
// ... test goes here
});
HTTP 認証
HTTP 認証を実行します。
- テスト
- ライブラリ
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
httpCredentials: {
username: 'bill',
password: 'pa55w0rd',
}
}
});
const context = await browser.newContext({
httpCredentials: {
username: 'bill',
password: 'pa55w0rd',
},
});
const page = await context.newPage();
await page.goto('https://example.com');
HTTP プロキシ
ページが HTTP(S) プロキシまたは SOCKSv5 経由でロードされるように設定できます。プロキシは、ブラウザ全体に対してグローバルに設定することも、ブラウザコンテキストごとに個別に設定することもできます。
オプションで、HTTP(S) プロキシのユーザー名とパスワードを指定したり、プロキシをバイパスするホストを指定したりすることもできます。
グローバルプロキシの例を次に示します。
- テスト
- ライブラリ
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
proxy: {
server: 'http://myproxy.com:3128',
username: 'usr',
password: 'pwd'
}
}
});
const browser = await chromium.launch({
proxy: {
server: 'http://myproxy.com:3128',
username: 'usr',
password: 'pwd'
}
});
コンテキストごとに指定することも可能です。
- テスト
- ライブラリ
import { test, expect } from '@playwright/test';
test('should use custom proxy on a new context', async ({ browser }) => {
const context = await browser.newContext({
proxy: {
server: 'http://myproxy.com:3128',
}
});
const page = await context.newPage();
await context.close();
});
const browser = await chromium.launch();
const context = await browser.newContext({
proxy: { server: 'http://myproxy.com:3128' }
});
ネットワークイベント
すべての Request と Response を監視できます。
// Subscribe to 'request' and 'response' events.
page.on('request', request => console.log('>>', request.method(), request.url()));
page.on('response', response => console.log('<<', response.status(), response.url()));
await page.goto('https://example.com');
または、page.waitForResponse() を使用して、ボタンクリック後のネットワークレスポンスを待機します。
// Use a glob URL pattern. Note no await.
const responsePromise = page.waitForResponse('**/api/fetch_data');
await page.getByText('Update').click();
const response = await responsePromise;
バリエーション
Response を page.waitForResponse() で待機します。
// Use a RegExp. Note no await.
const responsePromise = page.waitForResponse(/\.jpeg$/);
await page.getByText('Update').click();
const response = await responsePromise;
// Use a predicate taking a Response object. Note no await.
const responsePromise = page.waitForResponse(response => response.url().includes(token));
await page.getByText('Update').click();
const response = await responsePromise;
リクエストの処理
await page.route('**/api/fetch_data', route => route.fulfill({
status: 200,
body: testData,
}));
await page.goto('https://example.com');
Playwright スクリプトでネットワークリクエストを処理することにより、API エンドポイントをモックできます。
バリエーション
browserContext.route() または page.route() を使用して、ブラウザコンテキスト全体またはページにルートを設定します。これは、ポップアップウィンドウと開かれたリンクに適用されます。
await browserContext.route('**/api/login', route => route.fulfill({
status: 200,
body: 'accept',
}));
await page.goto('https://example.com');
リクエストの修正
// Delete header
await page.route('**/*', async route => {
const headers = route.request().headers();
delete headers['X-Secret'];
await route.continue({ headers });
});
// Continue requests as POST.
await page.route('**/*', route => route.continue({ method: 'POST' }));
修正を加えてリクエストを続行できます。上記の例では、送信リクエストから HTTP ヘッダーを削除しています。
リクエストの中止
page.route() と route.abort() を使用して、リクエストを中止できます。
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Abort based on the request type
await page.route('**/*', route => {
return route.request().resourceType() === 'image' ? route.abort() : route.continue();
});
レスポンスの修正
レスポンスを修正するには、APIRequestContext を使用して元のレスポンスを取得し、レスポンスを route.fulfill() に渡します。オプションを使用して、レスポンスの個々のフィールドをオーバーライドできます。
await page.route('**/title.html', async route => {
// Fetch original response.
const response = await route.fetch();
// Add a prefix to the title.
let body = await response.text();
body = body.replace('<title>', '<title>My prefix:');
await route.fulfill({
// Pass all fields from the response.
response,
// Override response body.
body,
// Force content type to be html.
headers: {
...response.headers(),
'content-type': 'text/html'
}
});
});
Glob URL パターン
Playwright は、page.route() や page.waitForResponse() などのネットワークインターセプトメソッドで URL マッチングに簡略化された glob パターンを使用します。これらのパターンは基本的なワイルドカードをサポートしています。
- アスタリスク
- 単一の
*
は/
を除く任意の文字に一致します。 - 二重の
**
は/
を含む任意の文字に一致します。
- 単一の
- 疑問符
?
は/
を除く任意の単一の文字に一致します。 - 中括弧
{}
は、コンマ,
で区切られたオプションのリストを一致させるために使用できます。 - 角括弧
[]
は、文字のセットを一致させるために使用できます。 - バックスラッシュ
\
は、特殊文字をエスケープするために使用できます (バックスラッシュ自体を\\
としてエスケープすることに注意してください)。
例
https://example.com/*.js
はhttps://example.com/file.js
に一致しますが、https://example.com/path/file.js
には一致しません。https://example.com/\\?page=1
はhttps://example.com/?page=1
に一致しますが、https://example.com
には一致しません。**/v[0-9]*
はhttps://example.com/v1/
に一致しますが、https://example.com/vote/
には一致しません。**/*.js
はhttps://example.com/file.js
とhttps://example.com/path/file.js
の両方に一致します。**/*.{png,jpg,jpeg}
はすべての画像リクエストに一致します。
重要な注意点
- glob パターンは、URL の一部ではなく、URL 全体に一致する必要があります。
- URL マッチングに glob を使用する場合は、プロトコルとパス区切り文字を含む完全な URL 構造を考慮してください。
- より複雑なマッチング要件については、glob パターンの代わりに RegExp を使用することを検討してください。
WebSocket
Playwright は、WebSocket の検査、モック、および変更をすぐにサポートしています。WebSocket をモックする方法については、API モックガイドをご覧ください。
WebSocket が作成されるたびに、page.on('websocket') イベントが発生します。このイベントには、その後の WebSocket フレーム検査のための WebSocket インスタンスが含まれています。
page.on('websocket', ws => {
console.log(`WebSocket opened: ${ws.url()}>`);
ws.on('framesent', event => console.log(event.payload));
ws.on('framereceived', event => console.log(event.payload));
ws.on('close', () => console.log('WebSocket closed'));
});
ネットワークイベントとサービスワーカーの欠落
Playwright の組み込み browserContext.route() および page.route() を使用すると、テストでネイティブにリクエストをルーティングし、モックとインターセプトを実行できます。
- Playwright のネイティブ browserContext.route() および page.route() を使用していて、ネットワークイベントが見つからない場合は、serviceWorkers を
'block'
に設定してサービスワーカーを無効にしてください。 - Mock Service Worker (MSW) などのモックツールを使用している可能性があります。このツールはレスポンスのモックにすぐに使用できますが、独自のサービスワーカーを追加してネットワークリクエストを引き継ぎ、browserContext.route() および page.route() から見えなくします。ネットワークテストとモックの両方に関心がある場合は、レスポンスモックに組み込みの browserContext.route() および page.route() を使用することを検討してください。
- サービスワーカーをテストとネットワークモックに単独で使用するのではなく、サービスワーカー自体が行うリクエストのルーティングとリッスンに関心がある場合は、この実験的な機能を参照してください。