Procedure
- DB隔離: Next.js はランタイム環境変数が
.env.localより優先される。起動時に上書きして本番DBを遮断する:
注意:TURSO_DATABASE_URL="file:/tmp/<app>-e2e.db" TURSO_AUTH_TOKEN="" \ AUTH_SECRET="<使い捨てdev文字列>" AUTH_TRUST_HOST=true \ npx next dev -p 3105 > /tmp/dev.log 2>&1 # run_in_backgroundTURSO_AUTH_TOKEN=""は空文字(falsy判定でfile DBに落とすコードが多い)。URL側を空文字にするとurl ?? fallbackを素通りして壊れる。 - セッションCookie mint: プロジェクト内に一時 .mjs を置き(bare import解決のため)、同じ AUTH_SECRET で:
Cookie名はimport { encode } from "next-auth/jwt"; const token = await encode({ token: { email: "...", name: "E2E", sub: "e2e" }, secret: process.env.AUTH_SECRET, salt: "authjs.session-token", // v5: salt = cookie名 (httpsなら __Secure- 接頭辞) maxAge: 3600, });authjs.session-token(http/localhost)。signIn callbackはセッション読取時には走らないので、Googleプロバイダ無効でも auth() は通る。 - Playwright:
context.addCookies([{ name: "authjs.session-token", value, domain: "localhost", path: "/", httpOnly: true, sameSite: "Lax" }])→ 認証必須ページ・API が全部動く。 - 検証後: 一時mintスクリプト削除、
pkill -f "next dev -p <port>"、/tmpのDB破棄。
Pitfalls
- Next dev overlayの
[role=dialog]: dev modeはhiddenなエラーoverlay dialogをDOMに常駐させる。モーダルのdetach待ちは[aria-label*='...']などアプリ固有セレクタで行う。[role=dialog]は永久にdetachしない。 page.once("dialog", ...)の残骸: 「念のためaccept」を仕掛けて発火しないと、後続テストのconfirmを横取りする。confirm検証前にpage.removeAllListeners("dialog")。- playwright未インストールのプロジェクトでは
/tmpにnpm i playwrightした使い捨てprojectから実行(対象repoのpackage.jsonを汚さない)。ブラウザバイナリは~/Library/Caches/ms-playwrightに共有キャッシュ済みのことが多い。 - 検証アサートの月表示等は実レンダリング文字列(例: "2026年 6月" のスペース)に合わせる。
Verification
curl -H "Cookie: authjs.session-token=$TOKEN" http://localhost:<port>/api/<protected>が200で実データを返す/tmp/<app>-e2e.dbが生成・成長している(=本番DB非接続の証拠)- 書き込み系フロー(保存→一覧反映)をPlaywrightで通し、スクショを /tmp に保存