プロキシ
.mock.json Next.js / TanStack Start SSR → プロキシ → 実際の API
サーバーと API の間に位置します。サーバーサイドのリクエスト — SSR フェッチ、ルートハンドラー、バックエンド・フォー・フロントエンドが呼び出すあらゆるものを記録します。
サーバーが API を呼び出すフルスタックアプリ向け。
Next.js の例を見る → TanStack Start の例を見る →Playwright の VCR
Playwright スイートをローカルで実行しながら実際の API レスポンスをキャプチャし、CI 上でバイト単位でそのまま再生します。バックエンド不要、ネットワーク不要、保守すべき手書きモックも不要。
npm i -D test-proxy-recorder GitHub でスター MIT · TypeScript · Next.js と TanStack Start の SSR、SPA、Chrome 拡張に対応 · WebSocket 対応
REC
saved e2e/recordings/todos.GET.mock.json
REPLAY
200 OK · 3 ms · zero network
1 回の Playwright 実行で実際のレスポンスをディスクに記録し、再生に切り替えれば同じスイートがバックエンドをオフにしたまま通過します — ネットワーク不要。
リクエストは 2 つの場所から発生するため、記録の仕組みも 2 つあります。どちらか、または両方を併用できます。どちらも一度記録してディスクから再生するため、CI はバックエンドをオフにしたまま手書きモックなしで実行されます。
.mock.json Next.js / TanStack Start SSR → プロキシ → 実際の API
サーバーと API の間に位置します。サーバーサイドのリクエスト — SSR フェッチ、ルートハンドラー、バックエンド・フォー・フロントエンドが呼び出すあらゆるものを記録します。
サーバーが API を呼び出すフルスタックアプリ向け。
Next.js の例を見る → TanStack Start の例を見る →.har ブラウザ → HAR 傍受 → 実際の API
ブラウザ自体の中で傍受します。クライアントサイドの fetch 呼び出し、Chrome 拡張の API トラフィック、アナリティクス、サードパーティ API を記録します。
SPA、拡張、ブラウザのみのアプリ向け。
Chrome 拡張の例を見る →モックツールはそれぞれ得意分野が異なります。以下の組み合わせ — SSR、ブラウザ、WebSocket にまたがって実際のトラフィックを記録し、手書きモックを必要としないこと — こそが、他のツールが埋められていない空白です。
| 機能 | test-proxy-recorder | Playwright routeFromHAR | MSW | Polly.js | playwright-network-cache | Mocky Balboa |
|---|---|---|---|---|---|---|
| 実際のトラフィックを記録 | 対応 | 対応 | 非対応 | 対応 | 対応 | 非対応 |
| サーバーサイド (SSR) | 対応 | 非対応 | 対応 | 部分的 | 非対応 | 対応 |
| ブラウザサイド | 対応 | 対応 | 対応 | 対応 | 対応 | 対応 |
| WebSocket | 対応 | 非対応 | 対応 | 非対応 | 非対応 | 非対応 |
| Playwright ネイティブ | 対応 | 対応 | 非対応 | 非対応 | 対応 | 対応 |
| メンテナンス状況 | 対応 | 対応 | 対応 | 非対応 | 対応 | 対応 |
Polly.js は Node の HTTP を傍受するため、SSR のモックはアプリプロセス内では可能ですが、Playwright 実行の一部としてはできません。MSW と Mocky Balboa も実際のレスポンスを再生します — ただしモックを手書きする必要があります。いつ他のツールを選ぶべきかは、 ドキュメントで説明されています。
Cognito、Auth0、Clerk、WorkOS を通じて、毎回の実行で本物のログインを行います。記録されるのはアプリの API だけで、認証はライブのまま、データはオフラインで再生されます。
// 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' });});AWS Cognito の例 → TanStack Start 上の Cognito → モック認証(クラウドアカウント不要)→
1 つのコマンドですべてをスキャフォールドし、API をプロキシに向け、記録してコミットします。ブラウザのみのアプリですか? init は SSR の手順をスキップしてくれます。
これをコピーし、バックエンド URL を差し替えて、Claude Code、Cursor、または任意のコーディングエージェントに貼り付けてください — エージェントは init を実行し、 init が表示するプロンプトに従って配線を完了させます。
Set up test-proxy-recorder for end-to-end tests in this project, then follow theinstructions 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 — findit yourself from the app's env/config (the URL the app calls in dev); don'tassume 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 atthe proxy in dev/test only, tag server-side fetches (Next.js), add a smoke test,and verify record → replay.または手動で配線する:
init は、プロキシ設定、Playwright フィクスチャ、グローバルティアダウン、 package.json のスクリプトを作成し、(Next.js では)SSR フェッチのタグ付けをルートレイアウトに配線します — 非破壊的に。
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 init が推測できない唯一のものは、どの環境変数が API のベース URL を保持しているかです。レコーダーが有効な場合はプロキシを指し、それ以外の場合は実際のバックエンドを指します — プロキシは本番環境では決して動きません。
// 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`); Next.js では、 init は registerProxyFetch() もルートレイアウトに追加して、サーバーサイドの fetch 呼び出しをタグ付けします — 本番では no-op です:
// app/layout.tsx — tag server-side fetches so SSR is recorded/replayedimport { registerProxyFetch } from 'test-proxy-recorder/nextjs';
registerProxyFetch(); // no-op in production unless TEST_PROXY_RECORDER_ENABLED=true MODE = 'record'に設定し、実際の API に対して一度実行し、その後 'replay' に切り替えてコミットします。記録は git に保存されます — これが CI を決定論的にするものです。gitignore に追加しないでください。
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();});# 1. Set MODE = 'record' in your test file, run against the real APInpx playwright test --ui # recordings written to e2e/recordings/
# 2. Flip MODE back to 'replay' and commit the recordingsgit add e2e/recordings/git commit -m "add e2e recordings"API はすでに正しい答えを返しています。それを記録しましょう。
npm i -D test-proxy-recorder GitHub でスター 午後の時間が節約できたなら、スターは 1 秒で済みます — 次の人が見つける手段であり、1 人で保守を続ける者への「作り続けて」という合図です。つまずいたりアイデアがあれば、 issue を開く か Discord に参加してください。