page.getByText(...))は言語ごとに壊れるか、常に1言語に固定してテストせざるを得ない。ui-smoke.mjsのinput[type=password]等)は、実装がTailwindユーティリティクラスの組み替えやコンポーネント構造の変更をするたびに壊れる。data-testid="{feature}-{component}-{element}[-{state}]"
feature — 機能領域。notifications / monitor / helpdesk / chat / billing / org / auth 等、仕様書のスコープと一致させる。component — 画面/セクション名。例: prefs(通知設定)、ticket-list、settings-form。element — 具体的な操作対象。例: toggle、submit-button、row、banner、select。state(任意) — その要素が特定の分岐/状態でのみ現れる場合に明示。例: critical-banner(平常時は存在しない)、verify-pending-banner。全て小文字・ハイフン区切り(kebab-case)。Reactコンポート名やCSSクラス名をそのまま転記しない — data-testidは「テストが何を選択しているか」を表す独立した語彙にする(実装のリネームでテストが壊れないようにするのが目的そのものなので、実装名と結合させない)。
4カテゴリ×3チャネルの通知設定マトリクスやチケット一覧のように、同じdata-testidを持つ要素が複数回現れる場合は、個体識別用の別属性を併用する — data-testid自体を要素数だけ量産しない。
<!-- 例: 通知設定マトリクスの1セル -->
<button data-testid="notifications-prefs-channel-toggle"
data-category="system_alert" data-channel="email">...</button>
<!-- Playwrightでの選択 -->
page.locator('[data-testid="notifications-prefs-channel-toggle"][data-category="system_alert"][data-channel="email"]')
<!-- 例: チケット一覧の行 -->
<tr data-testid="helpdesk-ticket-row" data-ticket-id="182">...</tr>
stateサフィックスで分岐を明示。prefsSavedのような一時的なUI状態)。逆に、純粋に装飾的な要素(アイコン、区切り線)や、分岐に関与しない静的テキストには付与しない — 全要素へ機械的に付与すると命名規則自体の可読性が失われる。
各仕様書のMermaidフローチャートの分岐ノード/エッジに、対応するTest IDをコメントとして注記していく(issue #54)。注記されていてもテストが実在するとは限らない — テスト有無は各仕様書側の注記と、下記の追跡Issueを参照。
| 仕様書 | 状態 |
|---|---|
| notification-spec.html | 注記済み(§3-B/§3-C。§3-Aは分岐なし) |
| system-monitor-spec.html | 注記済み(§3-A〜§3-E。§3-Eの「両テンプレート」の記述漏れも修正) |
| support-desk-spec.html | 注記済み(§3-A〜§3-C。埋め込みWidgetは既存の安定id属性をそのまま採用) |
注記済み = フローチャートにTest IDまたは「バックエンド専用」の判定を追記済み。実際のPlaywrightテストは現時点(2026-07-28)で全分岐とも未実装 — 追跡はissue #54とそのサブIssue群を参照。
frontend/tests/ui-smoke.mjs — 既存のinput[type=password]等のCSS/タグセレクタは、対応するdata-testidが付与され次第page.getByTestId(...)に置き換える。一括置換はせず、要素にIDを付与した回のPRで該当箇所も更新する。data-testidが無ければ先に付与してから書く(逆順(先にテキストセレクタで書いて後で直す)は禁止)。featureプレフィックスを追加する際は、対応する仕様書のスコープ名(例: notification-spec.htmlのscope行)と一致させる。