演題登録システム (endai-system)

E2Eテスト実装状況・技術的制約・トラブルシューティングガイド

バージョン: 1.1 最終更新: 2026-01-29 作成者: Claude Code

1. E2Eテスト実装状況

1.1 テスト環境

項目 設定
フレームワーク Playwright
実行コマンド npx playwright test
テストディレクトリ e2e/
スクリーンショット e2e/screenshots/
動画記録 e2e/videos/(失敗時のみ)
ベースURL http://localhost:3000

1.2 テスト結果サマリ

14
合計テスト数
14
成功
0
失敗

1.3 ユーザー登録テスト

ファイル: 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}`;
}

1.4 演題投稿テスト

ファイル: e2e/abstract-submission.spec.ts

テスト名 状態 説明
ログインできる ✅ PASS 認証確認
投稿フォームにアクセスできる ✅ PASS 権限確認
ステップ1: 基本情報を入力できる ✅ PASS フォーム入力
ステップ2: 著者・所属情報を入力できる ✅ PASS 動的フィールド
ステップ3: 抄録本文を入力できる ✅ PASS テキストエリア
ステップ4: 利益相反・倫理を入力できる ✅ PASS ラジオボタン
ステップ5: 確認画面で投稿を完了できる ✅ PASS RLSポリシー修正済み
マイページで投稿済み演題を確認できる ✅ PASS ステータス確認

2. 技術的制約とリミテーション

2.1 Supabaseの制約

2.1.1 メール送信レート制限(重要)

Supabase Free プラン: 4通/時間のメール送信制限
開発・テスト時に頻繁に制限に到達します。
プラン 制限 影響
Free 4通/時間 開発・テスト時に頻繁に制限に到達
Pro 100通/時間 本番運用には十分

影響を受ける機能:

対処法:

  1. Supabase Dashboard → Authentication → Email Templates → Rate Limitingで制限を緩和
  2. 開発環境では「Confirm email」を無効化(推奨しない)
  3. 1時間待ってから再試行
// エラーメッセージ
error.message: "email rate limit exceeded"
error.code: "over_email_send_rate_limit"
HTTP Status: 429

2.1.2 RLS(Row Level Security)ポリシー

INSERT時の注意点:
USING 句ではなく WITH CHECK 句を使用してください。
UPDATE時の注意点:
ステータス変更を許可するには 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())
  );

2.2 Next.js / Vercelの制約

項目 制限 対処法
Server Action ペイロード 1MB ファイルはSupabase Storageへ
Vercel Hobby プラン 100GB帯域/月 Proプランへ移行
Edge Runtime Node.js API制限あり 必要に応じてNode.jsランタイム使用

2.3 テスト環境の制約

項目 制限 対処法
E2Eテストでのメール送信 レート制限 テストでは成功 or レート制限を許容
example.com ドメイン Supabaseが拒否 Gmailエイリアス使用
セレクタの厳密性 Playwright strict mode [role="option"] など明示的セレクタ使用

3. トラブルシューティングガイド

3.1 エラー対応一覧

エラー: new row violates row-level security policy for table "abstracts"

症状: 演題の投稿(INSERT)またはステータス更新(UPDATE)が失敗

原因:

  1. RLSポリシーの WITH CHECK 句が欠落
  2. UPDATE時に 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())
  );

エラー: email rate limit exceeded / over_email_send_rate_limit

症状: ユーザー登録やパスワードリセットが失敗

原因: Supabase Free プランのメール送信制限(4通/時間)

解決策:

  1. 開発環境: E2Eテストでレート制限エラーを許容する
  2. 本番環境: Supabase Proプランにアップグレード
  3. 一時対応: 1時間待つ

コード対応 (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: "リクエストが多すぎます。しばらく待ってから再試行してください。" };
  }
  // ...
}

エラー: locator resolved to X elements (Playwright)

症状: 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();

エラー: Invalid email domain

症状: テスト用メールアドレス(example.com)がSupabaseに拒否される

原因: Supabaseが一部のドメインを無効として拒否

解決策: Gmailエイリアス機能を使用

// baseEmail: kawaguchi.ns.reha033@gmail.com
// 生成例: kawaguchi.ns.reha033+e2e1706500000@gmail.com
const testEmail = generateTestEmail();

3.2 デバッグ用ログ出力

Server Actions でのエラーログ

// src/lib/actions/auth.ts
if (error) {
  console.error("[register] Supabase signup error:", error.message, error);
  // error オブジェクト全体をログ出力して詳細を確認
}

E2Eテストでのスクリーンショット

// 各ステップでスクリーンショットを保存
await page.screenshot({ path: "e2e/screenshots/step-01.png" });

// エラー時のコンテキストキャプチャ
const errorText = await page.locator(".error-message").textContent();
console.log("Error message:", errorText);

3.3 RLSポリシー確認用SQL

-- 現在のRLSポリシー一覧を確認
SELECT
  schemaname,
  tablename,
  policyname,
  permissive,
  roles,
  cmd,
  qual AS "USING clause",
  with_check AS "WITH CHECK clause"
FROM pg_policies
WHERE tablename = 'abstracts';

4. 変更履歴

バージョン 日付 変更内容 作成者
1.0 2026-01-27 初版作成 Claude Code
1.1 2026-01-29 E2Eテスト実装状況、制約、トラブルシューティング追加 Claude Code