Intercepción de red y Mock en Playwright
Este capítulo presenta cómo usar Playwright para interceptar, modificar y simular solicitudes de red, logrando pruebas independientes que no dependen de la API del backend.
Qué es la intercepción de red
La intercepción de red te permite intervenir cuando el navegador realiza solicitudes HTTP.
Puedesbloquear solicitudes, modificar respuestas, devolver datos simulados, para que las pruebas no dependan de API externas ni del estado de la red.
page.route() para interceptar solicitudes
page.route(url, handler)Se utiliza para interceptar todas las solicitudes de red que coinciden con el patrón de URL especificado.
Intercepción básica
Ejemplo
// Interceptar todas las imágenes PNG y JPEG
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Navegar a la página (las imágenes no se cargarán)
await page.goto('https://www.example.com/');
// La página puede cargar más rápido porque no se descargan imágenes
});
Patrones de coincidencia de URLSe admiten los siguientes formatos:
| Patrón | Ejemplo | Descripción |
|---|---|---|
| URL completa | 'https://api.example.com/users' | Coincidencia exacta |
| Comodines Glob | '**/api/**' | **Coincide con cualquier ruta |
| Expresión regular | /\/api\/v\d\/users/ | Coincidencia flexible |
| Función | url => url.includes('/api/') | Coincidencia mediante lógica de programación |
route.abort() para bloquear solicitudes
Ejemplo
// Bloquear scripts de análisis como Google Analytics
await page.route('**/*analytics*', route => route.abort());
// Bloquear archivos CSS
await page.route('**/*.css', route => route.abort());
await page.goto('https://www.example.com/');
// La página se carga sin estilos, pero no afecta las pruebas funcionales
});
route.fulfill() para simular respuestas
route.fulfill()Es el método de Mock más potente, puede devolver cualquier respuesta personalizada.
Mock de datos JSON
Ejemplo
// Interceptar la API de lista de usuarios y devolver datos simulados
await page.route('**/api/users', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
json: [
{ id: 1, name: 'ejemplo_user', email: '[email protected]' },
{ id: 2, name: 'test_user', email: '[email protected]' },
],
});
});
await page.goto('https://www.example.com/users');
// La página mostrará los datos Mock en lugar de los datos reales de la API
});
Mock de respuestas de error
Ejemplo
// Simular un error 500 del servidor
await page.route('**/api/data', async route => {
await route.fulfill({
status: 500,
contentType: 'application/json',
json: { error: 'Error interno del servidor' },
});
});
await page.goto('https://www.example.com/dashboard');
// Verificar que el mensaje de error se muestre correctamente
await expect(page.getByText('Error interno del servidor')).toBeVisible();
});
route.continue() continuar después de modificar
No devuelve directamente datos simulados, sino que continúa enviando al servidor después de modificar la solicitud o respuesta real.
Ejemplo
await page.route('**/api/**', async (route, request) => {
// Modificar las cabeceras de la solicitud, añadir una cabecera personalizada
const headers = {
...request.headers(),
'X-Custom-Header': 'EJEMPLO-TEST',
};
await route.continue({ headers });
});
await page.goto('https://www.example.com/');
});
test('Modificar datos POST', async ({ page }) => {
await page.route('**/api/login', async (route, request) => {
// Sobrescribir el body de la solicitud POST
const postData = JSON.parse(request.postData() || '{}');
postData.mode = 'test'; // Añadir marcador de prueba
await route.continue({
postData: JSON.stringify(postData),
});
});
});
route.fetch() solicitud real
En la función de manejo de Mock, se puede usarroute.fetch()para enviar realmente la solicitud y obtener la respuesta real, y luego modificarla.
Ejemplo
await page.route('**/api/products', async route => {
// Primero obtener la respuesta real
const response = await route.fetch();
const body = await response.json();
// Modificar los datos de la respuesta
body.items[0].name = 'EJEMPLO nombre del producto modificado';
// Devolver los datos modificados
await route.fulfill({
status: response.status(),
contentType: 'application/json',
json: body,
});
});
});
Intercepción a nivel de Context vs intercepción a nivel de Page
| Método | Alcance | Escenario de uso |
|---|---|---|
page.route() | Solo la página actual | Mock de red para una sola página |
context.route() | Todas las páginas bajo ese Context | Reglas de Mock compartidas por múltiples páginas |
Ejemplo
// Interceptar en todo el Context, aplica a todas las páginas
await context.route('**/*.css', route => route.abort());
});
test('Prueba 1', async ({ page }) => { /* Sin CSS */ });
test('Prueba 2', async ({ page }) => { /* Sin CSS */ });
Grabación y reproducción de archivos HAR
Los archivos HAR (HTTP Archive) pueden registrar todas las solicitudes de red de la página y luego reproducirlas como simulación.
Ejemplo
// Cargar el registro de red desde el archivo HAR y reproducirlo
await page.routeFromHAR('tests/hars/api-responses.har');
await page.goto('https://www.example.com/');
// Todas las solicitudes coincidentes obtendrán la respuesta desde el archivo HAR
});
# 录制 HAR 文件 npx playwright open --save-har=tests/hars/api-responses.har https://www.example.com/
Otras extensionesLos archivos HAR son adecuados para simular respuestas de API numerosas o complejas. Graba una vez, y las pruebas posteriores se reproducen desde el HAR, sin depender del servidor real.