機能の end-to-end 動作確認を Playwright で自動化したスクリプト群です。CI には組み込まれていません(手動で node <script>.mjs で実行)。複数タブ間の連動 (Mesh v2 ↔ クラス管理など) のように unit / integration テストでは網羅しづらい挙動を、ローカルでサッと回すための場所です。
- dev server が起動中:
docker compose up -d appで http://localhost:8601 が応答する状態 .envのDEV_BYPASS_TOKEN: 教師の Google ログインをバイパスするためのトークンが設定されている(stg / ローカル前提)- このディレクトリで
npm install済み(最初の 1 回のみ)
cd tools/playwright-verify
npm install # 初回のみ
npx playwright install chromium # 初回のみ(OS の Playwright cache が無い場合)node <script>.mjsヘッドフルブラウザが 2 つ立ち上がります。スクリプトは Redux store / DOM testid の両方を経由して状態を確認し、最後にスクリーンショットを .screenshots/ に保存します。
ブラウザプロファイルは .profiles/teacher .profiles/student に永続化されます (両方 gitignore 済み)。永続化されているのは Chromium の cookie / cache / IndexedDB のみ — 教師 idToken は in-memory なのでリロード/再起動で再ログインが必要です。プロファイルをリセットしたい場合:
rm -rf .profiles| ファイル | 検証対象 |
|---|---|
mesh-v2-classroom-binding.mjs |
クラス管理と Mesh v2 ドメインの連動。教師タブでクラス作成→サイドバーで選択、生徒タブで ?classcode= 経由参加し、両方の state.scratchGui.meshV2.domain が参加コードに揃うこと、接続モーダル入力欄が disabled になること、解除時に元のドメインに戻ることをチェック |
スクリプトを書く / 拡張するときの留意点。失敗を踏み抜いた後の蓄積です。
?devlogin=<DEV_BYPASS_TOKEN> を URL に付けると教師として自動ログインしてダッシュボードまで到達します(.env の DEV_BYPASS_TOKEN を使用)。Google OAuth 待ちが不要になり、CI 化の道筋ができます。
window.smalruby は Ruby タブを訪れた後にしか存在しません。Redux store が必要なら React 18 の Fiber Tree から memoizedProps.store または memoizedProps.value.store を探すヘルパーを使います(各スクリプトの findStore() 参照)。掘り出した store は window.__store に貼って後続 evaluate で使い回します。
classroom-phase-teacher-dashboard: ダッシュボードフェーズの testid はcomponents/classroom-teacher-modal/classroom-teacher-modal.jsxのデフォルト分岐に付けた(旧コードでは login と google-courses 以外に testid が無く、フェーズ検知できなかった)- サイドバー項目:
classroom-sidebar-item-{classroomId}(classroom-item-*ではない)。表示テキストはassignmentName · 人数 · 参加コード(小文字) - クラス作成:
classroom-name-input/classroom-count-input/classroom-assignment-name-inputの 3 つすべて 必須。1 つでも空だとclassroom-create-submitは disabled - 作成後の遷移:
classroom-create-submit押下 →phase==='teacher-dashboard'に戻る(自動で詳細画面に遷移しない)。新クラスはサイドバーに追加されるが selectedClassroom は null のまま — テストでteacherSelectionを埋めたいなら明示的にサイドバー項目をクリック
state.scratchGui.classroom.role: student のみ。teacher ログイン中でも nullstate.scratchGui.classroom.joinCode: 学生セッションの参加コードstate.scratchGui.classroom.teacherSelection.joinCode: 教師がサイドバーで選んだクラスの参加コードstate.scratchGui.meshV2.domain: Mesh v2 ドメイン(バインディングは小文字化した joinCode を入れる)
- 「同じ assignmentName を 2 度使うと前回のクラスが選ばれてしまう」:
Date.now()でユニーク化する - 「全席 taken でテストが進まない」: 同じクラスに既に上限まで参加している。新規クラスを作成するか、空席を
:not([disabled])で動的に選ぶ - 「modal が閉じる」: persistent context は同じプロファイルを使い回すので、前回のテストで残った state が悪さする場合がある。
rm -rf .profilesしてやり直す