コンテンツにスキップ

手動セットアップ

ほとんどの人は init を実行すべきです — 以下のファイルをすべて書き出してくれます。このページは init が生成する内容のリファレンスで、手で組み込んだり、コード生成を省いたり、各ピースを理解したりするために使います。

フルスタック(SSR + ブラウザ)

Section titled “フルスタック(SSR + ブラウザ)”

Next.js や類似フレームワーク向けで、サーバーとブラウザの両方が API 呼び出しを行う場合。両方の記録メカニズムを併用します — 仕組みを参照。

プロキシはテスト実行のためにアプリと並べて起動する(以下のスクリプトや Playwright の webServer で)軽量なプロセスであり、デプロイや保守するインフラではありません。セットアップ全体は、アプリの隣で起動し、アプリの API ベース URL をそこに向け、SSR からセッションヘッダーを伝播し、フィクスチャを 1 つ書くだけです。

1. package.json にスクリプトを追加する

Section titled “1. 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\""
}
}

アプリのコードでは、recorder が有効な場合はプロキシへ、そうでない場合は実際のバックエンドへ API のベース URL を向けてください — プロキシは本番では実行されません:

const API_BASE =
process.env.NODE_ENV === 'production' && !process.env.TEST_PROXY_RECORDER_ENABLED
? 'https://api.example.com'
: 'http://localhost:8100'; // proxy address

TEST_PROXY_RECORDER_ENABLED は上記の dev:proxy / serve:proxy スクリプト、および init が生成したスクリプトによって設定されます。アプリが API のベース URL に既に使用している環境変数を使ってください(例えば API_URLNEXT_PUBLIC_API_URL) — 同じ条件分岐が適用されます。

2. サーバーサイドフェッチにタグ付けする(Next.js)

Section titled “2. サーバーサイドフェッチにタグ付けする(Next.js)”

サーバーサイドの fetch 呼び出しには記録セッションヘッダーが必要で、これによりプロキシはそのリクエストがどのテストに属するかを知ります。Playwright がすでにブラウザのナビゲーションにそれを設定しているため、id は next/headers にあります — あとは送信する SSR リクエストにそれを付与するだけです。ルートレイアウトに 1 行追加してください(init がこれを行います):

app/layout.tsx
import { registerProxyFetch } from 'test-proxy-recorder/nextjs';
registerProxyFetch(); // no-op in production unless TEST_PROXY_RECORDER_ENABLED=true
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

これは Node と Edge の両方のランタイムで動作します。axios アプリの場合は、代わりに各サーバーサイドインスタンスで registerProxyAxios(instance) を呼んでください。単一の fetch には createHeadersWithRecordingId(await headers()) がパッチ不要の代替です。setNextProxyHeaders を使う proxy.ts/middleware.ts任意です — id を公開するだけで、フェッチにはタグ付けしません。本番ビルドnext build && next start)に対して記録し、next dev では行わないでください。詳しくは Next.js インテグレーションを参照。ブラウザのみのアプリはこのステップを省略できます。

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();
});
Terminal window
# Terminal 1
npm run serve:proxy
# Terminal 2 — .mock.json and .har files are written automatically
npx playwright test

5. 再生に切り替えてコミットする

Section titled “5. 再生に切り替えてコミットする”
Terminal window
git add e2e/recordings/
git commit -m "add e2e recordings"

すべての API 呼び出しがブラウザから来る場合(SSR なし)、必要なのは HAR メカニズムだけです。記録そのものにプロキシのバックエンドは不要です — プロキシのプロセスはセッション管理を提供するだけです。

Terminal window
npm install --save-dev test-proxy-recorder

2. playwright.config.ts にプロキシを追加する

Section titled “2. 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,
},
});

ブラウザのみの記録では、プロキシのターゲット(https://api.example.com)は重要ではありません — サーバーサイド(SSR)リクエストもプロキシ経由にする必要がある場合にのみ使われます。プロキシのプロセスは、セッション管理のために /__control エンドポイントが利用可能になるよう実行されている必要があります。

e2e/fixtures.ts
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);
},
});
e2e/my.test.ts
import { test, expect } from './fixtures';
test('homepage loads', async ({ page }) => {
await page.goto('https://myapp.com/');
await expect(page.getByText('Welcome')).toBeVisible();
});

5. 記録する — 実際の API に対して一度実行する

Section titled “5. 記録する — 実際の API に対して一度実行する”
Terminal window
# In fixtures.ts: const MODE = 'record' as const;
npx playwright test
# .har files are written to e2e/recordings/ automatically

6. 再生に切り替えてコミットする

Section titled “6. 再生に切り替えてコミットする”
Terminal window
# In fixtures.ts: const MODE = 'replay' as const;
git add e2e/recordings/
git commit -m "add e2e recordings"

CI はネットワークアクセスなしで実行できるようになります。

PR の差分で大きな記録ファイルを折りたたむには、.gitattributes に次を追加してください:

/e2e/recordings/** binary