Перехват сетевых запросов в Playwright
Перехват сетевых запросов в Playwright — очень полезная возможность в сценариях автоматизированного тестирования и веб-скрапинга, позволяющая перехватывать, изменять и имитировать сетевые запросы и ответы.
Playwright предоставляетpage.route()иpage.on('request') / page.on('response')и другие API, которые могут:
- Перехват запросов: решать, разрешать ли, изменять URL/заголовки/тело или сразу возвращать мок-ответы.
- Мониторинг запросов/ответов: просмотр URL запроса, метода, заголовков, кода состояния ответа, тела ответа и т. д.
- Имитация сетевых ошибок: блокировать запросы, возвращать коды ошибок, тестировать логику отказоустойчивости приложения.
Типичные случаи использования:
- Мок API: запускать UI-тесты фронтенда без API бэкенда.
- Изменение запросов: например, добавить токен, протестировать некорректные заголовки.
- Отладка производительности: подсчёт запросов, времени ответа.
- Инъекция ошибок: имитировать серверные ошибки, такие как 500/404.
Перехват запросов:page.route()
await page.route('**/api/todos', async route => {
// 拦截匹配的请求
console.log('拦截到请求:', route.request().url());
// 1. 直接放行(继续请求)
await route.continue();
// 2. 修改请求
// await route.continue({ headers: { ...route.request().headers(), 'X-Test': 'true' } });
// 3. 返回 mock 响应
// await route.fulfill({
// status: 200,
// contentType: 'application/json',
// body: JSON.stringify([{ id: 1, text: 'mock todo', done: false }]),
// });
// 4. 拒绝请求
// await route.abort();
});
Описание параметра:
page.route(url, handler): зарегистрировать перехватчик,urlподдерживает строку, регулярное выражение или**подстановочный знак.route.request(): получить объект запроса.route.continue([options]): разрешить запрос, можно изменить method, headers, postData.route.fulfill(response): напрямую вернуть поддельный ответ.route.abort([errorCode]): прервать запрос, распространённые коды ошибок, такие как"failed","aborted","timedout"。
Мониторинг запросов и ответов
// 监听所有请求
page.on('request', req => {
console.log(`➡️ 请求: ${req.method()} ${req.url()}`);
});
// 监听所有响应
page.on('response', async res => {
console.log(`⬅️ 响应: ${res.status()} ${res.url()}`);
});
// 获取响应 body
const response = await page.waitForResponse('**/api/data');
console.log('响应内容:', await response.text());
Часто используемые методы:
request.url()/request.method()/request.headers()/request.postData()response.status()/response.headers()/response.text()/response.json()
Симуляция сетевой среды
Примеры
// Симуляция сетевой ошибки
await page.route('**/*.png', route => route.abort('failed'));
// Симуляция задержки
await page.route('**/api/**', async route => {
await new Promise(r => setTimeout(r, 2000));
await route.continue();
});
</pre>
<hr>
<h2>Полный пример: имитация API</h2>
import { test, expect } from '@playwright/test';
test('Перехват и имитация API', async ({ page }) => {
// Перехватить запрос /api/todos и вернуть фиксированные данные
await page.route('**/api/todos', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, text: 'Изучение Playwright', done: false },
{ id: 2, text: 'Написать автоматизированные тесты', done: истина },
]),
});
});
await page.goto('https://example-todo-app.com');
const items = await page.locator('.todo-item').allTextContents();
console.log('Загруженные задачи:', items);
// Проверка, что UI отображает mock-данные
await expect(page.locator('.todo-item')).toHaveCount(2);
await expect(page.locator('.todo-item').first()).toContainText('Playwright Learning');
});
await page.route('**/*.png', route => route.abort('failed'));
// Симуляция задержки
await page.route('**/api/**', async route => {
await new Promise(r => setTimeout(r, 2000));
await route.continue();
});
</pre>
<hr>
<h2>Полный пример: имитация API</h2>
import { test, expect } from '@playwright/test';
test('Перехват и имитация API', async ({ page }) => {
// Перехватить запрос /api/todos и вернуть фиксированные данные
await page.route('**/api/todos', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, text: 'Изучение Playwright', done: false },
{ id: 2, text: 'Написать автоматизированные тесты', done: истина },
]),
});
});
await page.goto('https://example-todo-app.com');
const items = await page.locator('.todo-item').allTextContents();
console.log('Загруженные задачи:', items);
// Проверка, что UI отображает mock-данные
await expect(page.locator('.todo-item')).toHaveCount(2);
await expect(page.locator('.todo-item').first()).toContainText('Playwright Learning');
});
API, связанные с перехватом сетевых запросов
| API | Назначение | Общие параметры/описание |
|---|---|---|
page.route(url, handler) |
Зарегистрировать перехват запроса | urlМожет быть строкой/регулярным выражением/шаблоном с подстановочными знаками |
route.request() |
Получить объект запроса | ВозвращаетRequest |
route.continue([options]) |
Разрешить запрос, можно изменить | { method, headers, postData } |
route.fulfill(response) |
Вернуть пользовательский ответ | { status, headers, body, contentType } |
route.abort([errorCode]) |
Прервать запрос | Общие:'failed', 'aborted', 'timedout' |
page.unroute(url, handler?) |
Удалить правило перехвата | |
page.on('request', cb) |
Мониторинг запроса | |
page.on('response', cb) |
Мониторинг ответа | |
request.url()/method()/headers()/postData() |
Информация о запросе | |
response.status()/headers()/text()/json() |
Информация об ответе | |
page.waitForResponse(urlOrPredicate) |
Ожидать конкретный ответ | Можно передать URL или функцию |