Cómo interceptar peticiones de red en Playwright: guía práctica

Una de las funcionalidades más potentes de Playwright que poca gente conoce cuando empieza es la interceptación de peticiones de red. Permite controlar exactamente qué respuestas recibe tu aplicación durante los tests, sin depender de APIs externas reales. En este artículo te explico cómo funciona y cuándo usarla.


Para qué sirve interceptar peticiones de red

Cuando tu aplicación hace llamadas a una API externa durante los tests, dependes de que esa API esté disponible, sea rápida y devuelva los datos correctos. Si la API está caída o lenta, tus tests fallan por razones ajenas a tu código.

La interceptación de red resuelve este problema — puedes simular las respuestas de la API devolviendo los datos que tú controlas, sin hacer llamadas reales. Esto hace los tests más rápidos, más estables y más predecibles.

También permite probar casos difíciles de reproducir en producción — errores del servidor, timeouts, respuestas malformadas, estados de error específicos.


page.route — el método principal

El método page.route() de Playwright intercepta las peticiones que coinciden con un patrón de URL y te permite decidir qué hacer con ellas.

python

from playwright.sync_api import Page

def test_con_mock_api(page: Page):
    # Interceptar todas las peticiones a /api/usuarios
    def mock_usuarios(route):
        route.fulfill(
            status=200,
            content_type="application/json",
            body='[{"id": 1, "nombre": "Fátima"}, {"id": 2, "nombre": "Carlos"}]'
        )
    
    page.route("**/api/usuarios", mock_usuarios)
    
    page.goto("https://miweb.com/usuarios")
    
    # La página recibe los datos mockeados, no los reales
    assert page.locator(".usuario").count() == 2

El patrón **/api/usuarios usa wildcards — el ** coincide con cualquier parte de la URL antes de /api/usuarios.


Mockear respuestas de error

Una de las situaciones más útiles es probar cómo se comporta tu aplicación cuando la API devuelve un error:

python

def test_error_servidor(page: Page):
    def simular_error_500(route):
        route.fulfill(
            status=500,
            content_type="application/json",
            body='{"error": "Internal Server Error"}'
        )
    
    page.route("**/api/productos", simular_error_500)
    
    page.goto("https://miweb.com/productos")
    
    # Verificar que la aplicación muestra el mensaje de error correctamente
    assert page.locator(".mensaje-error").is_visible()
    assert "Error al cargar los productos" in page.locator(".mensaje-error").text_content()

Interceptar y modificar la respuesta real

En lugar de reemplazar completamente la respuesta, puedes interceptar la petición real, obtener la respuesta y modificarla antes de que llegue a la aplicación:

python

def test_modificar_respuesta(page: Page):
    def modificar_precio(route):
        # Continuar con la petición real
        response = route.fetch()
        # Parsear la respuesta
        import json
        data = response.json()
        # Modificar los datos
        data["precio"] = 999
        # Devolver la respuesta modificada
        route.fulfill(
            response=response,
            body=json.dumps(data)
        )
    
    page.route("**/api/producto/1", modificar_precio)
    page.goto("https://miweb.com/producto/1")
    
    assert "999" in page.locator(".precio").text_content()

Bloquear peticiones específicas

Puedes bloquear peticiones completamente — útil para evitar que los tests carguen recursos innecesarios como analytics, publicidad o fuentes externas que ralentizan la ejecución:

python

def test_sin_analytics(page: Page):
    # Bloquear todas las peticiones a Google Analytics
    page.route("**/google-analytics.com/**", lambda route: route.abort())
    page.route("**/gtag/**", lambda route: route.abort())
    
    page.goto("https://miweb.com")
    # El test se ejecuta más rápido sin cargar analytics

Usar route en el fixture para aplicarlo a todos los tests

Si quieres aplicar un mock a todos los tests de un archivo, defínelo en un fixture:

python

import pytest
from playwright.sync_api import Page

@pytest.fixture
def page_con_mock(page: Page):
    def mock_auth(route):
        route.fulfill(
            status=200,
            content_type="application/json",
            body='{"token": "test-token-123", "usuario": "test@test.com"}'
        )
    
    page.route("**/api/auth/login", mock_auth)
    yield page

def test_login(page_con_mock):
    page_con_mock.goto("https://miweb.com/login")
    page_con_mock.fill("#email", "test@test.com")
    page_con_mock.fill("#password", "password")
    page_con_mock.click("#btn-login")
    assert "dashboard" in page_con_mock.url

Cuándo usar interceptación de red y cuándo no

La interceptación de red es muy útil para tests que dependen de APIs externas inestables o lentas, para probar casos de error difíciles de reproducir, para aislar el frontend del backend en tests de UI y para hacer los tests más rápidos eliminando llamadas de red reales.

No deberías usar mocks cuando quieras probar la integración real entre frontend y backend — para eso necesitas tests de integración con la API real. Los mocks son para tests de UI que quieren aislar el comportamiento del frontend.

Si quieres profundizar en Playwright puedes leer cómo usar locators en Playwright o cómo eliminar tests flaky.

Scroll al inicio