Playwright Intercepción de Red
La intercepción de red de Playwright (Network Interception) es una capacidad muy útil en escenarios de pruebas automatizadas y web scraping, que nos permite interceptar, modificar y simular solicitudes y respuestas de red.
Playwright proporcionapage.route()ypage.on('request') / page.on('response')y otras APIs, que pueden:
- Interceptar solicitudes: decidir si se deja pasar, modificar URL/headers/body, o devolver directamente una respuesta mock.
- Monitorear solicitudes/respuestas: ver la URL, método, cabeceras, código de estado de respuesta, cuerpo de respuesta, etc.
- Simular errores de red: bloquear solicitudes, devolver códigos de error, probar la lógica de tolerancia a fallos de la aplicación.
Escenarios de aplicación comunes:
- Mock API: ejecutar pruebas de UI del frontend sin necesidad de interfaces de backend.
- Modificar solicitudes: por ejemplo, añadir token, probar cabeceras anómalas.
- Depuración de rendimiento: contar el número de solicitudes, tiempo de respuesta.
- Inyección de errores: simular errores de servidor como 500/404.
Interceptar solicitudes: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();
});
Descripción de parámetros:
page.route(url, handler): registrar un interceptor,urlSoporta cadenas, expresiones regulares o**comodines.route.request(): obtener el objeto de solicitud.route.continue([options]): dejar pasar la solicitud, se pueden modificar método, headers, postData.route.fulfill(response): devolver directamente una respuesta mock.route.abort([errorCode]): interrumpir la solicitud, códigos de error comunes como"failed","aborted","timedout"。
Monitorear solicitudes y respuestas
// 监听所有请求
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());
Métodos comunes:
request.url()/request.method()/request.headers()/request.postData()response.status()/response.headers()/response.text()/response.json()
Simular el entorno de red
Ejemplo
// Simular error de red
await page.route('**/*.png', route => route.abort('failed'));
// Simular latencia
await page.route('**/api/**', async route => {
await new Promise(r => setTimeout(r, 2000));
await route.continue();
});
</pre>
<hr>
<h2>Ejemplo completo: Mock API</h2>
import { test, expect } from '@playwright/test';
test('Interceptar y simular API', async ({ page }) => {
// Interceptar la solicitud /api/todos y devolver datos fijos
await page.route('**/api/todos', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, text: 'Aprender Playwright', done: false },
{ id: 2, text: 'Escribir pruebas automatizadas', done: true },
]),
});
});
await page.goto('https://example-todo-app.com');
const items = await page.locator('.todo-item').allTextContents();
console.log('Tareas pendientes cargadas:', items);
// Afirmar que la UI muestra los datos mock
await expect(page.locator('.todo-item')).toHaveCount(2);
await expect(page.locator('.todo-item').first()).toContainText('Aprender Playwright');
});
await page.route('**/*.png', route => route.abort('failed'));
// Simular latencia
await page.route('**/api/**', async route => {
await new Promise(r => setTimeout(r, 2000));
await route.continue();
});
</pre>
<hr>
<h2>Ejemplo completo: Mock API</h2>
import { test, expect } from '@playwright/test';
test('Interceptar y simular API', async ({ page }) => {
// Interceptar la solicitud /api/todos y devolver datos fijos
await page.route('**/api/todos', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, text: 'Aprender Playwright', done: false },
{ id: 2, text: 'Escribir pruebas automatizadas', done: true },
]),
});
});
await page.goto('https://example-todo-app.com');
const items = await page.locator('.todo-item').allTextContents();
console.log('Tareas pendientes cargadas:', items);
// Afirmar que la UI muestra los datos mock
await expect(page.locator('.todo-item')).toHaveCount(2);
await expect(page.locator('.todo-item').first()).toContainText('Aprender Playwright');
});
API relacionadas con la intercepción de red
| API | Uso | Parámetros comunes / Descripción |
|---|---|---|
page.route(url, handler) |
Registrar intercepción de solicitudes | urlPuede ser cadena/expresión regular/comodín |
route.request() |
Obtener el objeto de solicitud | DevuelveRequest |
route.continue([options]) |
Dejar pasar la solicitud, se puede modificar | { method, headers, postData } |
route.fulfill(response) |
Devolver respuesta personalizada | { status, headers, body, contentType } |
route.abort([errorCode]) |
Interrumpir la solicitud | Comunes:'failed', 'aborted', 'timedout' |
page.unroute(url, handler?) |
Eliminar regla de intercepción | |
page.on('request', cb) |
Monitorear solicitudes | |
page.on('response', cb) |
Monitorear respuestas | |
request.url()/method()/headers()/postData() |
Información de la solicitud | |
response.status()/headers()/text()/json() |
Información de la respuesta | |
page.waitForResponse(urlOrPredicate) |
Esperar una respuesta específica | Se puede pasar una URL o una función |