[Astro] #152 E2E自動テストとリアルタイム開発診断UIの実装 — Playwrightによる非同期3Dアセット404検知とDevモード警告ボタン

[Astro] #152 E2E自動テストとリアルタイム開発診断UIの実装 — Playwrightによる非同期3Dアセット404検知とDevモード警告ボタン

はじめに

PROTOCOL.LAIN では Three.js や WebGL を活用した 3D アバター描画やアニメーション再生を行っているが、アセットファイル(.vrma 等)のパス変更やファイル欠損が起きると、サイレントに処理がクラッシュし <canvas> 要素すら生成されない問題があった。

今回、Playwright による E2E 自動テストで非同期アセットの 404 エラーを正確に補捉・出力する仕組みを整え、さらに開発環境(Dev モード)の WEB 画面上にエラー発生をリアルタイム通知する「診断警告 UI」を組み込んだ。

1. 課題:3D アセット読み込み失敗による描画崩壊

Three.js でアニメーションアセット(例: stand-talk.vrma)を取得する際、ファイルが 404 になると resolveAnims(アセット初期化処理)が途中で例外を出して停止する。

[CACHE_ERROR] Failed to process SYS_TALK2: Error: Network error: 404
  at getCachedAssetUrl (...)
  at async resolveAnims (...)

この結果、Three.js のレンダラーが <canvas> を DOM に追加する処理まで到達できず、画面には何も映らないまま無言で壊れる現象が発生していた。開発中にこれに気づかずコミットしてしまうリスクを減らすため、自動検知と視覚的通知の仕組みが必要だった。

2. Playwright による非同期 404 アセット検知

ブラウザ自動テストスクリプト(Playwright)側で、以下のロジックを構築した。

  1. アセット待機時間の確保: ページロード後に 5 秒間の待機(waitForTimeout)を挟み、Three.js が非同期で .vrma アセットを取りに行くタイミングを逃さずキャッチ。

  2. ログと DOM の監視: レスポンスステータス 404、コンソールエラー、および 3D 描画用 <canvas> 要素の存在チェックを実施。

  3. 結果の JSON 保存: 検知結果を /public/test-result.json へ出力。

実行ログと検知結果

アセットが欠損している状態でテストを実行すると、ターミナルへ即座に検知結果が出力される。

❌ 3D描画用の canvas 要素が見つかりませんでした
❌ 読み込み失敗ファイル (404等):
  - 404 : [https://127.0.0.1:4321/animations/anim/stand-talk.vrma](https://127.0.0.1:4321/animations/anim/stand-talk.vrma)
❌ ブラウザコンソールエラー :
  - Failed to load resource: the server responded with a status of 404 ()
  - [CACHE_ERROR] Failed to process SYS_TALK2: Error: Network error: 404

📝 テスト結果を /home/lain/github/my-new-site/public/test-result.json に保存しました

出力される /public/test-result.json の構造:

{
  "hasError": true,
  "failedRequests": [
    "404 : [https://127.0.0.1:4321/animations/anim/stand-talk.vrma](https://127.0.0.1:4321/animations/anim/stand-talk.vrma)"
  ],
  "consoleErrors": [
    "Failed to load resource: the server responded with a status of 404 ()",
    "[CACHE_ERROR] Failed to process SYS_TALK2: Error: Network error: 404"
  ],
  "canvasFound": false
}

3. WEB ページへのリアルタイム診断通知 UI (index.astro)

テスト結果の JSON ファイルを開発環境(Dev モード)のフロントエンドが自動で監視し、不具合がある場合は WEB ページ上に直接アラートを表示するプロトコルを実装した。

実装手順

① アラートボタンの配置 (src/pages/index.astro)

UI コンテナ内に警告用のネオンボタンを配置する(初期状態は display: none)。

<!-- SYSTEM ALERT ボタン(エラー発生時のみ動的表示) -->
<button id="system-alert-btn" class="mobile-update-trigger alert-trigger" style="display: none;">ERROR</button>

② import.meta.env.DEV による自動チェックロジック

クライアントスクリプト内に test-result.json を取得して判定する処理を追加。

// =========================================================
// 🚨 [DEV ONLY] 自動テスト結果(404等)の監視・通知プロトコル
// =========================================================
if (import.meta.env.DEV) {
  fetch('/test-result.json')
    .then((res) => res.json())
    .then((data) => {
      if (data && data.hasError) {
        const alertBtn = document.getElementById('system-alert-btn');
        if (alertBtn) {
          alertBtn.style.display = 'block';

          // ターミナル UI へエラーログを通知
          window.dispatchEvent(
            new CustomEvent('wired-log', {
              detail: {
                msg: `[ALERT] ${data.failedRequests.length} ASSET MISSING DETECTED`,
                type: 'error',
                color: '#ff0055',
              },
            })
          );

          // ボタンクリックで詳細ダイアログを表示
          alertBtn.addEventListener('click', () => {
            const logs = [
              '--- [SYSTEM DIAGNOSTIC ALERT] ---',
              ...data.failedRequests.map((r: string) => `❌ ${r}`),
              ...data.consoleErrors.map((e: string) => `⚠️ ${e}`),
            ].join('\n');

            alert(logs);
          });
        }
      }
    })
    .catch(() => {
      // test-result.json が存在しない場合は無視
    });
}

③ 発光アニメーションスタイル (CSS)

PROTOCOL.LAIN の世界観に合わせ、赤色ネオンの点滅アニメーションを設定。

/* ★ アラートボタン(赤い警告色 + 点滅) */
.alert-trigger {
  bottom: 170px;
  border-color: #ff0055 !important;
  color: #ff0055 !important;
  background: rgba(255, 0, 85, 0.15) !important;
  box-shadow: 0 0 10px rgba(255, 0, 85, 0.5);
  animation: alert-blink 1.2s ease-in-out infinite alternate;
}

.alert-trigger:hover {
  background: #ff0055 !important;
  color: #000 !important;
  box-shadow: 0 0 20px #ff0055;
}

@keyframes alert-blink {
  0% {
    opacity: 0.6;
    box-shadow: 0 0 5px rgba(255, 0, 85, 0.3);
  }
  100% {
    opacity: 1;
    box-shadow: 0 0 15px rgba(255, 0, 85, 0.9);
  }
}

4. 動作検証とクリーンアップ

エラー検知時

アセットが読み込めない場合、画面右下に赤い ERROR ボタンが点滅出現する。ボタンを押すと [SYSTEM DIAGNOSTIC ALERT] ダイアログが開かれ、どの URL で 404 が起きているか一目で確認できる。

正常復旧時

欠損していたアセットファイル名(例: stand-talk.vrma)を正しい位置へ復元してテストを再実行すると、/public/test-result.json の hasError が false に更新される。次回リロード時には ERROR ボタンが自動的に消滅し、Three.js の <canvas> と アバター描画が正常に復旧する。

5. まとめ

段階挙動
E2E テスト実行Playwright が 5 秒待機し非同期 404 エラーと Canvas 存在を検証

| | 結果出力 | /public/test-result.json へ構造化データを保存

| | フロントエンド検知 | Dev モード限定で JSON を監視し、不具合時に ERROR ボタンを表示

| | 修正と検証 | アセット復元後、テスト再実行で自動的に警告表示が解除

|

サイレントクラッシュしやすい WebGL/Three.js アプリケーションにおいて、自動テストと画面上の即時警告 UI を連携させることで、アセット欠損の発見から修正までのデバッグコストを大幅に削減できた。