VCR para Playwright

Grave uma vez.
Reproduza para sempre.

Captura respostas reais da API enquanto sua suite do Playwright roda localmente e depois as reproduz byte por byte na CI. Sem backend, sem rede, sem mocks escritos à mão para manter.

npm i -D test-proxy-recorder Estrelar no GitHubContagem de estrelas do GitHub

MIT · TypeScript · funciona com SSR de Next.js e TanStack Start, SPAs e extensões do Chrome · suporte a WebSocket

REC · MODE=record · local run

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

REPLAY · MODE=replay · CI

200 OK · 3 ms · zero network

Veja gravar e depois reproduzir

Uma execução do Playwright grava respostas reais no disco; mude para reproduzir e a mesma suite passa com o backend desligado — sem rede.

Dois gravadores, um proxy

As requisições se originam em dois lugares, então há dois mecanismos de gravação. Use um ou outro — ou ambos juntos. Ambos gravam uma vez e reproduzem a partir do disco, então a CI roda com o backend desligado e sem mocks escritos à mão.

Proxy

.mock.json

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

Fica entre o seu servidor e a API. Grava requisições do lado do servidor — fetches SSR, route handlers, tudo o que seu backend-for-frontend chama.

Para aplicações full-stack onde o servidor chama a API.

Ver o exemplo de Next.js →Ver o exemplo de TanStack Start →

HAR

.har

navegador → interceptação HAR → API real

Intercepta no próprio navegador. Grava chamadas fetchdo lado do cliente, tráfego de API de extensões do Chrome, analytics e APIs de terceiros.

Para SPAs, extensões e aplicações somente de navegador.

Ver o exemplo de extensão do Chrome →

Onde ele se encaixa

As ferramentas de mock são boas em trabalhos diferentes. A combinação abaixo — gravar tráfego real em SSR, navegador e WebSockets, sem mocks escritos à mão — é a lacuna que as outras deixam em aberto.

Comparação de recursos do test-proxy-recorder com o routeFromHAR do Playwright, MSW, Polly.js, playwright-network-cache e Mocky Balboa.
Recursotest-proxy-recorderPlaywright routeFromHARMSWPolly.jsplaywright-network-cacheMocky Balboa
Grava tráfego realSimSimNãoSimSimNão
Lado do servidor (SSR)SimNãoSimParcialNãoSim
Lado do navegadorSimSimSimSimSimSim
WebSocketSimNãoSimNãoNãoNão
Nativo do PlaywrightSimSimNãoNãoSimSim
MantidoSimSimSimNãoSimSim

O Polly.js intercepta o HTTP do Node, então mockar SSR é possível dentro do processo da aplicação, mas não como parte de uma execução do Playwright. O MSW e o Mocky Balboa também reproduzem respostas reais — mas você escreve os mocks à mão. Quando optar por outra ferramenta é explicado nadocumentação.

Funciona com o seu provedor de autenticação real

Faça login via Cognito, Auth0, Clerk ou WorkOS — de verdade, em cada execução. Somente a API da sua aplicação é gravada; a autenticação permanece ao vivo e seus dados ficam offline.

// 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' });
});

Configure em três passos

Gere tudo com um comando, aponte sua API para o proxy, depois grave e faça commit. Aplicação somente de navegador? initpula a etapa de SSR para você.

Caminho mais rápido: entregue ao seu agente de IA

Copie isto, troque pela URL do seu backend e cole no Claude Code, Cursor ou em qualquer agente de codificação — ele executa inite conclui a configuração a partir do prompt que initimprime.

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.

Ou configure à mão:

  1. Instale e gere

    init escreve a config do proxy, uma fixture do Playwright, um teardown global e os scripts depackage.json e (no Next.js) conecta a marcação das buscas SSR ao seu root layout — de forma não destrutiva.

    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. Aponte a API da sua aplicação para o proxy

    A única coisa que o initnão consegue adivinhar: qual variável de ambiente guarda a URL base da sua API. Aponte-a para o proxy quando o recorder estiver habilitado e para o backend real caso contrário — o proxy nunca roda em produção.

    // 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`);

    No Next.js, o inittambém adiciona registerProxyFetch()ao seu root layout para marcar as chamadas fetchdo lado do servidor — um no-op em produção:

    // 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. Grave, faça commit, reproduza

    Defina MODE = 'record', execute uma vez contra a API real, depois mude para 'replay'e faça commit. As gravações vivem no git — é isso que torna a CI determinística. Não as coloque no .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"

Pare de escrever mocks à mão

Sua API já dá as respostas certas. Grave-as.

npm i -D test-proxy-recorder Estrelar no GitHub

Se isso economizou uma tarde, uma estrela leva um segundo — é assim que a próxima pessoa encontra e diz a um mantenedor solo para continuar construindo. Esbarrou em um problema ou teve uma ideia? Abra uma issueouentre no Discord.