UI 改修時にローカル検証を必ず実施するためのガイドライン。CLAUDE.md「変更時テスト」表の詳細手順を本ファイルに集約。

適用範囲

対象検証フロー
webapp_client/src/**/*.{ts,tsx,css} (Vite SPA)本ガイド §1〜§4
templates/*.html (GAS Web App)本ガイド §5

§1. type-check (必須)

cd webapp_client
npm run type-check

tsc --noEmit で型エラーを検出。0 件でなければ次に進まない。

§2. snapshot test で regression 検知 (必須)

cd webapp_client
npm run test:ui

webapp_client/tests/cockpit-visual.spec.ts (Playwright + visual snapshot) を実行。既存スナップショットとの差分があれば失敗。 GitHub Actions の .github/workflows/ui-test.yml も同じ spec を PR 時に自動実行する (本ステップで先行検知することで PR fail を防ぐ)。

snapshot mismatch が意図した変更の場合

npm run test:ui:update     # 新しい snapshot で上書き
git add webapp_client/tests/**/*.png
git commit -m "test(ui): snapshot 更新 (理由: <理由>)"

意図しない mismatch は実装バグ。snapshot 上書きで隠蔽してはいけない。

§3. 新規動作には新規 spec を追加 (動作変更がある場合)

新機能・新挙動の検証は**webapp_client/tests/ に Playwright spec を追加**する。/tmp/ への ad-hoc スクリプトは禁止 (再現性なし・CI 連携なし・後続セッションが利用不可)。

spec 雛形

// webapp_client/tests/<feature>.spec.ts
import { test, expect } from '@playwright/test';

test('<feature> が期待通り動作する', async ({ page }) => {
  await page.goto('/financial_cockpit.html');
  await page.waitForLoadState('networkidle');

  // クリック・入力等の操作
  await page.click('text=月次財務諸表');

  // DOM 状態を計測 (computed style / 属性 / テキスト)
  const stickyZIndex = await page.evaluate(() => {
    const el = document.querySelector('thead .pl-col-num--sticky');
    return getComputedStyle(el).zIndex;
  });
  expect(stickyZIndex).toBe('3');

  // または visual snapshot
  await expect(page).toHaveScreenshot('<feature>.png');
});

playwright.config.tswebServer 設定により npm run test:ui 時に dev サーバが自動起動する (port 5173 既定)。

§4. dev サーバでブラウザ目視 (視覚確認が必要な場合のみ)

snapshot だけでは UX が確認できない場合 (アニメーション・スクロール挙動・体感的な使いやすさ) に限定。

cd webapp_client
npm run dev:cockpit       # cockpit ターゲット (financial_cockpit)
# または
npm run dev:multiyear     # multiyear ターゲット
npm run dev               # sidebar ターゲット

ブラウザで http://localhost:5173/financial_cockpit.html 等を開く。

port 競合 (5173 が使用中) の対処

Vite は自動で次の port (5174, 5175, ...) に切替えるが、Claude が混乱するので明示的に port を指定するのが安全:

npm run dev:cockpit -- --port 5173 --strictPort

--strictPort で port 競合時はエラー終了 → 既存プロセスを kill してから再実行する。

Claude Code セッション内での目視

Claude Code 自身はブラウザを操作できない (ヘッドレス環境)。open コマンドで実機ブラウザを起動する手段はあるが、視覚確認は人間に依頼するのが正しい。Claude は npm run test:ui で snapshot 比較するか、Playwright で computed style を検査することで代替する。

人間確認ゲート (必須)

UI 変更がある場合、Claude は以下のフローを厳守する:

  1. 実装完了後、dev サーバを起動し、確認 URL を人間に提示
    例: dev サーバを起動しました。
    http://localhost:5173/financial_cockpit.html を開き、
    「月次タブで通期列が sticky 固定されている」ことを確認してください。
    OK / NG をお知らせください。
    
  2. 人間から OK 受領を確認するまで git push および PR 作成を実施しない
  3. NG の場合は修正 → ① に戻る (修正→確認のループ)
  4. 段階的修正中は git commit (ローカル) は OK だが、git push は OK 受領後のみ

なぜ必要か

  • npm run test:ui の snapshot pass = 既存挙動の自動退行検知 のみ。新機能・新挙動の妥当性は判定できない
  • type-check pass = 型エラーなし のみ。視覚的・UX 的な妥当性とは無関係
  • Playwright での computed style 検査 = Claude が予測した DOM 状態の検証のみ。人間が期待する見え方 とは別物
  • 結果として 新機能・新挙動の最終承認は人間目視のみ が信頼できる

Claude が暴走しないためのチェックリスト

git push 前に Claude 自身が確認すべき:

  • UI 変更がある場合、人間に「OK / NG」を尋ねたか
  • 人間から 明示的な OK を受領したか (snapshot pass や type-check pass を OK と誤認していないか)
  • NG が来た場合、修正後に再度 OK を尋ねたか

このチェックを通過しない限り、git push および mcp__github__create_pull_request を呼ばない。

§5. templates/*.html (GAS Web App) の検証

templates/financial_cockpit.html multiyear_cockpit.html *_sidebar.html 等は GAS Web App 経由で配信される。Vite dev サーバでは動作しない (GAS API バインディング google.script.run が未定義のため)。

検証フロー

npm run push:dev        # 開発用 GAS にデプロイ

その後、開発用 GAS の Web App /exec URL をブラウザで開いて目視確認。Env.isDev() が true の状態で挙動を確認する。

prod URL への直接 push は permissions.deny でブロック済 (scripts/hooks/pre_bash_guard.sh 参照)。

§6. 共通の地雷・避けるべきパターン

パターン問題対処
/tmp/verify*.mjs で ad-hoc Playwright再現性なし、CI 未連携webapp_client/tests/ に spec として追加
Playwright を絶対パスで import環境依存・他マシンで動かないwebapp_client/ 内で npx playwright test を使う
open コマンドで GUI 起動headless 環境で失敗、Claude 検証不可snapshot test or computed style 検査
port 5173/5174 を場当たり的に切替確認 URL の不一致--strictPort で明示的に管理
snapshot mismatch を上書きで隠蔽退行を見逃すmismatch の原因を分析、意図的なら理由付きで update

§7. CI との関係

  • .github/workflows/ui-test.yml が PR 時に npm run test:ui を自動実行する (webapp_client/src/** webapp_client/tests/** の変更で発火)
  • ローカル検証 = PR 時 CI で fail することを事前に防ぐための前段チェック
  • 「ローカルで通った」≠「CI で通る」(OS / browser version 差異あり) ので CI 結果も必ず確認する

関連ドキュメント

  • CLAUDE.md「変更時テスト」表 — 本ガイドへの参照元
  • webapp_client/playwright.config.ts — Playwright 設定の正準ソース
  • .github/workflows/ui-test.yml — CI ワークフロー定義