E2Eテスト実装状況・技術的制約・トラブルシューティングガイド
| 項目 | 設定 |
|---|---|
| フレームワーク | Playwright |
| 実行コマンド | npx playwright test |
| テストディレクトリ | e2e/ |
| スクリーンショット | e2e/screenshots/ |
| 動画記録 | e2e/videos/(失敗時のみ) |
| ベースURL | http://localhost:3000 |
ファイル: e2e/registration.spec.ts
| テスト名 | 状態 | 説明 |
|---|---|---|
| 登録ページが正しく表示される | ✅ PASS | フォーム要素の存在確認 |
| 正しい情報で登録すると成功メッセージまたはレート制限エラーが表示される | ✅ PASS | 実際のSupabase signupを実行 |
| 必須項目が未入力の場合、送信できない | ✅ PASS | HTML5バリデーション確認 |
| パスワードが一致しない場合、エラーが表示される | ✅ PASS | クライアント側バリデーション |
| 既存のメールアドレスで登録するとエラーまたは成功が表示される | ✅ PASS | 重複チェック |
| ログインページへのリンクが機能する | ✅ PASS | ナビゲーション確認 |
// Gmailエイリアス機能を使用してユニークなアドレスを生成
function generateTestEmail() {
const timestamp = Date.now();
const baseEmail = process.env.E2E_AUTHOR_EMAIL ?? "example@gmail.com";
const [localPart, domain] = baseEmail.split("@");
return `${localPart}+e2e${timestamp}@${domain}`;
}
ファイル: e2e/abstract-submission.spec.ts
| テスト名 | 状態 | 説明 |
|---|---|---|
| ログインできる | ✅ PASS | 認証確認 |
| 投稿フォームにアクセスできる | ✅ PASS | 権限確認 |
| ステップ1: 基本情報を入力できる | ✅ PASS | フォーム入力 |
| ステップ2: 著者・所属情報を入力できる | ✅ PASS | 動的フィールド |
| ステップ3: 抄録本文を入力できる | ✅ PASS | テキストエリア |
| ステップ4: 利益相反・倫理を入力できる | ✅ PASS | ラジオボタン |
| ステップ5: 確認画面で投稿を完了できる | ✅ PASS | RLSポリシー修正済み |
| マイページで投稿済み演題を確認できる | ✅ PASS | ステータス確認 |
| プラン | 制限 | 影響 |
|---|---|---|
| Free | 4通/時間 | 開発・テスト時に頻繁に制限に到達 |
| Pro | 100通/時間 | 本番運用には十分 |
影響を受ける機能:
対処法:
// エラーメッセージ
error.message: "email rate limit exceeded"
error.code: "over_email_send_rate_limit"
HTTP Status: 429
USING 句ではなく WITH CHECK 句を使用してください。
USING: 既存行の読み取り/更新/削除条件WITH CHECK: 新規行の挿入/更新後の行の検証WITH CHECK が必要です。
-- 正しいUPDATEポリシー例
CREATE POLICY abstracts_update_own ON abstracts
FOR UPDATE
TO authenticated
USING (
(submitter_id = auth.uid())
AND (status = ANY (ARRAY['draft'::text, 'revision_requested'::text]))
)
WITH CHECK (
(submitter_id = auth.uid())
);
| 項目 | 制限 | 対処法 |
|---|---|---|
| Server Action ペイロード | 1MB | ファイルはSupabase Storageへ |
| Vercel Hobby プラン | 100GB帯域/月 | Proプランへ移行 |
| Edge Runtime | Node.js API制限あり | 必要に応じてNode.jsランタイム使用 |
| 項目 | 制限 | 対処法 |
|---|---|---|
| E2Eテストでのメール送信 | レート制限 | テストでは成功 or レート制限を許容 |
example.com ドメイン |
Supabaseが拒否 | Gmailエイリアス使用 |
| セレクタの厳密性 | Playwright strict mode | [role="option"] など明示的セレクタ使用 |
症状: 演題の投稿(INSERT)またはステータス更新(UPDATE)が失敗
原因:
WITH CHECK 句が欠落USING 句のみで、ステータス変更後の行を検証できない解決策:
-- INSERTポリシーの確認・修正
DROP POLICY IF EXISTS abstracts_insert_own ON abstracts;
CREATE POLICY abstracts_insert_own ON abstracts
FOR INSERT
TO authenticated
WITH CHECK (submitter_id = auth.uid());
-- UPDATEポリシーの確認・修正
DROP POLICY IF EXISTS abstracts_update_own ON abstracts;
CREATE POLICY abstracts_update_own ON abstracts
FOR UPDATE
TO authenticated
USING (
(submitter_id = auth.uid())
AND (status = ANY (ARRAY['draft'::text, 'revision_requested'::text]))
)
WITH CHECK (
(submitter_id = auth.uid())
);
症状: ユーザー登録やパスワードリセットが失敗
原因: Supabase Free プランのメール送信制限(4通/時間)
解決策:
コード対応 (src/lib/actions/auth.ts):
if (error) {
console.error("[register] Supabase signup error:", error.message, error);
if (error.message.includes("rate limit") || error.message.includes("too many")) {
return { error: "リクエストが多すぎます。しばらく待ってから再試行してください。" };
}
// ...
}
症状: E2Eテストでセレクタが複数の要素にマッチ
原因: Playwrightのstrict modeでセレクタが一意でない
解決策:
// 悪い例: テキストが複数箇所に存在
await page.locator('text=理学療法士').click();
// 良い例: roleとhas-textを組み合わせ
await page.locator('[role="option"]:has-text("理学療法士")').click();
// 良い例: first()を使用
await page.locator('text=ログイン').first().click();
症状: テスト用メールアドレス(example.com)がSupabaseに拒否される
原因: Supabaseが一部のドメインを無効として拒否
解決策: Gmailエイリアス機能を使用
// baseEmail: kawaguchi.ns.reha033@gmail.com
// 生成例: kawaguchi.ns.reha033+e2e1706500000@gmail.com
const testEmail = generateTestEmail();
// src/lib/actions/auth.ts
if (error) {
console.error("[register] Supabase signup error:", error.message, error);
// error オブジェクト全体をログ出力して詳細を確認
}
// 各ステップでスクリーンショットを保存
await page.screenshot({ path: "e2e/screenshots/step-01.png" });
// エラー時のコンテキストキャプチャ
const errorText = await page.locator(".error-message").textContent();
console.log("Error message:", errorText);
-- 現在のRLSポリシー一覧を確認
SELECT
schemaname,
tablename,
policyname,
permissive,
roles,
cmd,
qual AS "USING clause",
with_check AS "WITH CHECK clause"
FROM pg_policies
WHERE tablename = 'abstracts';
| バージョン | 日付 | 変更内容 | 作成者 |
|---|---|---|---|
| 1.0 | 2026-01-27 | 初版作成 | Claude Code |
| 1.1 | 2026-01-29 | E2Eテスト実装状況、制約、トラブルシューティング追加 | Claude Code |