Configuración manual
La mayoría debería ejecutar init — escribe por ti todos los archivos de abajo. Esta página es la referencia de lo que init genera, para que puedas cablearlo a mano, omitir el codegen o entender cada pieza.
Full-stack (SSR + navegador)
Sección titulada «Full-stack (SSR + navegador)»Para Next.js y frameworks similares, donde tanto el servidor como el navegador hacen llamadas a la API. Usa ambos mecanismos de grabación juntos — mira cómo funciona.
El proxy es un proceso ligero que arrancas junto a tu app para la ejecución de la prueba (vía un script, como abajo, o el webServer de Playwright) — no es infraestructura que despliegas o mantienes. El setup completo es: arráncalo junto a tu app, apunta la URL base de la API de tu app hacia él, propaga la cabecera de sesión desde SSR y escribe un fixture.
1. Añade scripts a package.json
Sección titulada «1. Añade scripts a package.json»{ "scripts": { "proxy": "test-proxy-recorder http://localhost:8000 --port 8100 --dir ./e2e/recordings", "dev:proxy": "concurrently \"npm run proxy\" \"TEST_PROXY_RECORDER_ENABLED=1 npm run dev\"", "serve:proxy": "concurrently \"npm run proxy\" \"TEST_PROXY_RECORDER_ENABLED=1 npm run serve\"" }}En el código de tu app, apunta la URL base de la API al proxy cuando el recorder está activado, y al backend real en caso contrario — el proxy nunca se ejecuta en producción:
const API_BASE = process.env.NODE_ENV === 'production' && !process.env.TEST_PROXY_RECORDER_ENABLED ? 'https://api.example.com' : 'http://localhost:8100'; // dirección del proxyTEST_PROXY_RECORDER_ENABLED lo establecen los scripts dev:proxy / serve:proxy de arriba, y los scripts generados por init. Usa la variable de entorno que tu app ya use para la URL base de la API (por ejemplo API_URL, NEXT_PUBLIC_API_URL) — la misma condicional aplica.
2. Etiqueta los fetch del lado del servidor (Next.js)
Sección titulada «2. Etiqueta los fetch del lado del servidor (Next.js)»Las llamadas fetch del lado del servidor necesitan la cabecera de sesión de grabación para que el proxy sepa a qué prueba pertenecen. Playwright ya la establece en la navegación del navegador, así que el id está en next/headers — solo tienes que adjuntarlo a las peticiones SSR salientes. Añade una línea a tu root layout (init hace esto por ti):
import { registerProxyFetch } from 'test-proxy-recorder/nextjs';
registerProxyFetch(); // no-op en producción salvo TEST_PROXY_RECORDER_ENABLED=true
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body>{children}</body> </html> );}Esto funciona en los runtimes Node y Edge. Para apps con axios, llama a registerProxyAxios(instance) en cada instancia del lado del servidor; para un único fetch, createHeadersWithRecordingId(await headers()) es una alternativa sin parchear. Un proxy.ts/middleware.ts con setNextProxyHeaders es opcional — solo expone el id, no etiqueta los fetch. Graba contra un build de producción (next build && next start), no next dev. Mira la integración de Next.js para más detalles. Las apps solo de navegador pueden saltarse este paso.
3. Escribe una prueba
Sección titulada «3. Escribe una prueba»import { test, expect } from '@playwright/test';import { playwrightProxy } from 'test-proxy-recorder';
// SSR requests (server → proxy) are recorded to .mock.json.// Browser requests to the proxy URL are also covered.const CLIENT_SIDE_URL = /localhost:8100/;
// Change to 'record' to update recordings.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();});4. Graba
Sección titulada «4. Graba»# Terminal 1npm run serve:proxy
# Terminal 2 — .mock.json and .har files are written automaticallynpx playwright test5. Cambia a reproducción y haz commit
Sección titulada «5. Cambia a reproducción y haz commit»git add e2e/recordings/git commit -m "add e2e recordings"Solo navegador / SPA / extensión
Sección titulada «Solo navegador / SPA / extensión»Cuando todas las llamadas a la API vienen del navegador (sin SSR), solo necesitas el mecanismo HAR. No hace falta un backend de proxy para la grabación en sí — el proceso del proxy solo proporciona gestión de sesiones.
1. Instala
Sección titulada «1. Instala»npm install --save-dev test-proxy-recorder2. Añade el proxy a playwright.config.ts
Sección titulada «2. Añade el proxy a playwright.config.ts»import { defineConfig } from '@playwright/test';
export default defineConfig({ webServer: { command: 'test-proxy-recorder https://api.example.com --port 8100 --dir ./e2e/recordings', url: 'http://localhost:8100/__control', reuseExistingServer: true, },});El destino del proxy (https://api.example.com) no importa para la grabación solo de navegador — solo se usa si también hay que enrutar peticiones del lado del servidor (SSR). El proceso del proxy debe ejecutarse para que su endpoint /__control esté disponible para la gestión de sesiones.
3. Escribe un fixture
Sección titulada «3. Escribe un fixture»import { test as base, type Page, type BrowserContext } from '@playwright/test';import { playwrightProxy } from 'test-proxy-recorder';
// Match the external API domain your browser makes requests to.// In record mode these requests go to the real API and are saved.// In replay mode they are served from disk — no network needed.const CLIENT_SIDE_URL = /api\.example\.com/;
// Change to 'record' to hit the real API and update recordings.const MODE = 'replay' as const;
export const test = base.extend<{ page: Page }>({ page: async ({ context }, use, testInfo) => { const page = await context.newPage(); await playwrightProxy.before(page, testInfo, MODE, { url: CLIENT_SIDE_URL }); await use(page); },});4. Escribe una prueba
Sección titulada «4. Escribe una prueba»import { test, expect } from './fixtures';
test('homepage loads', async ({ page }) => { await page.goto('https://myapp.com/'); await expect(page.getByText('Welcome')).toBeVisible();});5. Graba — ejecuta una vez contra la API real
Sección titulada «5. Graba — ejecuta una vez contra la API real»# In fixtures.ts: const MODE = 'record' as const;npx playwright test# .har files are written to e2e/recordings/ automatically6. Cambia a reproducción y haz commit
Sección titulada «6. Cambia a reproducción y haz commit»# In fixtures.ts: const MODE = 'replay' as const;git add e2e/recordings/git commit -m "add e2e recordings"CI ahora se ejecuta sin ningún acceso a la red.
Añade esto a .gitattributes para colapsar archivos de grabación grandes en los diffs de PR:
/e2e/recordings/** binary