VCR para Playwright

Graba una vez.
Reproduce para siempre.

Captura respuestas reales de la API mientras tu suite de Playwright se ejecuta localmente, y luego las reproduce byte a byte en CI. Sin backend, sin red, sin mocks escritos a mano que mantener.

npm i -D test-proxy-recorder Dar estrella en GitHub Recuento de estrellas de GitHub

MIT · TypeScript · funciona con SSR de Next.js y TanStack Start, SPAs y extensiones de Chrome · soporte de WebSocket

REC · MODE=record · local run

saved e2e/recordings/todos.GET.mock.json

REPLAY · MODE=replay · CI

200 OK · 3 ms · zero network

Míralo grabar y luego reproducir

Una ejecución de Playwright graba respuestas reales en disco; cambia a reproducir y la misma suite pasa con el backend apagado — sin red.

Dos grabadores, un proxy

Las peticiones se originan en dos lugares, así que hay dos mecanismos de grabación. Usa uno u otro — o ambos a la vez. Ambos graban una vez y reproducen desde el disco, así que CI se ejecuta con el backend apagado y sin mocks escritos a mano.

Proxy

.mock.json

SSR de Next.js / TanStack Start → proxy → API real

Se sitúa entre tu servidor y la API. Graba las peticiones del lado del servidor — fetch SSR, route handlers, cualquier cosa que llame tu backend-for-frontend.

Para apps full-stack donde el servidor llama a la API.

Ver el ejemplo de Next.js → Ver el ejemplo de TanStack Start →

HAR

.har

navegador → interceptación HAR → API real

Intercepta en el propio navegador. Graba las llamadas fetch del lado del cliente, el tráfico de API de extensiones de Chrome, la analítica y las APIs de terceros.

Para SPAs, extensiones y apps solo de navegador.

Ver el ejemplo de extensión de Chrome →

Dónde encaja

Las herramientas de mocking son buenas para trabajos distintos. La combinación de abajo — grabar tráfico real a través de SSR, navegador y WebSockets, sin mocks escritos a mano — es el hueco que las demás dejan abierto.

Comparación de características de test-proxy-recorder frente a routeFromHAR de Playwright, MSW, Polly.js, playwright-network-cache y Mocky Balboa.
Característica test-proxy-recorder Playwright routeFromHAR MSW Polly.js playwright-network-cache Mocky Balboa
Graba tráfico real No No
Lado del servidor (SSR) No Parcial No
Lado del navegador
WebSocket No No No No
Nativo de Playwright No No
Mantenido No

Polly.js intercepta el HTTP de Node, así que el mocking de SSR es posible dentro del proceso de la app, pero no como parte de una ejecución de Playwright. MSW y Mocky Balboa también reproducen respuestas reales — pero escribes los mocks a mano. Cuándo recurrir a otra cosa se explica en la documentación.

Funciona con tu proveedor de auth real

Inicia sesión a través de Cognito, Auth0, Clerk o WorkOS — de verdad, en cada ejecución. Solo se graba la API de tu app; la auth se mantiene en vivo y tus datos quedan sin conexión.

// e2e/auth.setup.ts — log in for real, once. Never recorded.
import { test as setup } from '@playwright/test';
import { setProxyMode } from 'test-proxy-recorder';
setup('authenticate', async ({ page }) => {
await setProxyMode('transparent'); // login bypasses the recorder
await page.goto('/login');
await page.getByTestId('email').fill(process.env.TEST_EMAIL!);
await page.getByTestId('password').fill(process.env.TEST_PASSWORD!);
await page.getByTestId('signinButton').click();
await page.waitForURL('/dashboard');
// Reused by every test — they start already signed in.
await page.context().storageState({ path: 'e2e/.auth/state.json' });
});

Configúralo en tres pasos

Genera todo el andamiaje con un solo comando, apunta tu API al proxy, luego graba y haz commit. ¿App solo de navegador? init se salta el paso de SSR por ti.

Vía más rápida: dáselo a tu agente de IA

Copia esto, cambia la URL de tu backend y pégalo en Claude Code, Cursor o cualquier agente de codificación — ejecuta init y termina el cableado a partir del prompt que init imprime.

Set up test-proxy-recorder for end-to-end tests in this project, then follow the
instructions that `init` prints. Run these commands:
npx @tanstack/intent@latest install
npm install --save-dev test-proxy-recorder
Then run init, passing this project's backend API base URL as the target — find
it yourself from the app's env/config (the URL the app calls in dev); don't
assume the default:
npx test-proxy-recorder init <your-backend-api-url> --port 8100 --dir ./e2e/recordings
Then complete the app-specific steps init prints: point the app's API base URL at
the proxy in dev/test only, tag server-side fetches (Next.js), add a smoke test,
and verify record → replay.

O cablea a mano:

  1. Instala y genera el andamiaje

    init escribe la config del proxy, un fixture de Playwright, un teardown global y los scripts de package.json y, en Next.js, cablea el etiquetado de los fetch SSR en tu root layout — de forma no destructiva.

    Terminal window
    npm install --save-dev test-proxy-recorder
    # http://localhost:3002 is your API endpoint; 8100 is the proxy. Flags are optional.
    npx test-proxy-recorder init http://localhost:3002 --port 8100 --dir ./e2e/recordings
  2. Apunta la API de tu app al proxy

    Lo único que init no puede adivinar: qué variable de entorno guarda la URL base de tu API. Apúntala al proxy cuando el grabador está activo, y al backend real en caso contrario — el proxy nunca se ejecuta en producción.

    // Point your app at the proxy when the recorder is enabled, at the real backend otherwise.
    // The proxy never runs in production — TEST_PROXY_RECORDER_ENABLED is set only for e2e.
    const API_BASE =
    process.env.NODE_ENV === 'production' && !process.env.TEST_PROXY_RECORDER_ENABLED
    ? 'https://api.example.com'
    : 'http://localhost:8100'; // proxy address from `init`
    const res = await fetch(`${API_BASE}/todos`);

    En Next.js, init también añade registerProxyFetch() a tu root layout para etiquetar las llamadas del lado del servidor fetch — un no-op en producción:

    // app/layout.tsx — tag server-side fetches so SSR is recorded/replayed
    import { registerProxyFetch } from 'test-proxy-recorder/nextjs';
    registerProxyFetch(); // no-op in production unless TEST_PROXY_RECORDER_ENABLED=true
  3. Graba, haz commit, reproduce

    Establece MODE = 'record', ejecuta una vez contra la API real, luego cambia a 'replay' y haz commit. Las grabaciones viven en git — eso es lo que hace a CI determinista. No las pongas en .gitignore.

    e2e/my.test.ts
    import { test, expect } from '@playwright/test';
    import { playwrightProxy } from 'test-proxy-recorder';
    // Full-stack: the browser also talks to the proxy, so match its URL.
    // (Browser-only app? Match your real API domain instead, e.g. /api\.example\.com/.)
    const CLIENT_SIDE_URL = /localhost:8100/;
    // 'record' hits the real API and saves responses.
    // 'replay' serves them from disk — no network needed.
    const MODE = 'replay' as const;
    test.beforeEach(async ({ page }, testInfo) => {
    await playwrightProxy.before(page, testInfo, MODE, { url: CLIENT_SIDE_URL });
    });
    test('homepage loads', async ({ page }) => {
    await page.goto('/');
    await expect(page.getByText('Welcome')).toBeVisible();
    });
    Terminal window
    # 1. Set MODE = 'record' in your test file, run against the real API
    npx playwright test --ui # recordings written to e2e/recordings/
    # 2. Flip MODE back to 'replay' and commit the recordings
    git add e2e/recordings/
    git commit -m "add e2e recordings"

Deja de escribir mocks a mano

Tu API ya da las respuestas correctas. Grábalas.

npm i -D test-proxy-recorder Dar estrella en GitHub

Si te ahorró una tarde, una estrella cuesta un segundo — así es como la encuentra la siguiente persona, y le dice a un mantenedor en solitario que siga construyendo. ¿Topaste con un problema o tienes una idea? Abre un issue o únete a Discord.