Skip to content

fix(ui): e2e のモックを実際の API の形にそろえ、メモが描かれることを確かめる (#3651) - #3658

Merged
Kewton merged 6 commits into
developfrom
feature/3651-worktree
Oct 13, 2026
Merged

Kewton merged 6 commits into
developfrom
feature/3651-worktree

Conversation

@Kewton

@Kewton Kewton commented Oct 13, 2026

Copy link
Copy Markdown
Owner

768px・表示サイズ medium / large の e2e で、worktree 一覧のモックが配列を
返していた。共有のキャッシュ(src/hooks/useWorktreesCache.ts)は
data.worktrees を読むので一覧が空になり、一覧からメモを読む useSessionNote
には保存済みのメモが届かず、前提が成り立っていなかった。

各モックを、ルートの実装を読んで実際の応答の形に合わせた。

  • GET /api/worktrees(src/app/api/worktrees/route.ts): 配列 → { worktrees:
    [row], repositories: [] }。行は worktree にセッションの状態
    (sessionStatusByCli / sessionStatusByInstance / isSessionRunning /
    isWaitingForResponse / isProcessing)と sessionNotes・autoYesByInstance・
    lastActivityByInstance を足した形。実際の応答にある defaultSelectedAgents
    と tmuxSessionNamespace、行の agentInstances は、この画面の経路で読まれず
    共有の fixture も持たないので省いた。
  • GET /api/worktrees/:id([id]/route.ts): worktree に gitStatus と
    セッションの状態を展開した形。実際の応答に無い sessionNotes を外し、
    無かった sessionStatusByInstance / isSessionRunning / isWaitingForResponse /
    isProcessing を足した(agentInstances は共有の fixture と同じく省略)。
  • GET /api/worktrees/:id/current-output(current-output/route.ts):
    CurrentOutputPayload に agentMode を足した形。型に無い isGenerating を外し、
    必須の sessionName / sessionStatus / sessionStatusReason / lineCount と
    agentMode を足した。終了ボタンはここの isRunning で描かれる。
  • それ以外(messages・tasks・verify など)は setupSplitTest の共有モックに
    落ちる。この spec では変えていない。

メモの日時の assert は既にあった(split-session-note-time-0 の日付つきの
時刻)。加えて、メモの本文が一覧から届いて描かれていること
(split-session-note-0 が本文を含む)を先に確かめ、モックの形が崩れたら
ここで落ちるようにした。1440 幅の陰性にも、同じ前提(メモの本文と日時、
終了ボタン)の assert を足した。

e2e は書いただけで走らせていない(UAT で走らせる)。lint と tsc は clean。

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

Refs #3651

Kewton and others added 5 commits October 13, 2026 09:54
## 決めたこと・確かめたこと
1. 使われていない部品の削除
   - grep: src 全体(src/app・src/components/mobile・layout を含む)で
     `SortSelectorBase` / `WorktreeCard` の import・JSX・dynamic import は 0 件。
     使っていたのはテストだけ(SortSelectorBase.test.tsx、escape-stacked-layers-3630 の
     該当 describe、WorktreeCard-nextAction.test.tsx、BranchListItem-worktree-status-3594 の
     WorktreeCard のソースを読む describe)。
   - 描画の経路: Sessions 画面(PC・スマホ共通の src/app/sessions/page.tsx)の並び替えは
     #1046 から Radix の `Select`、サイドバー(スマホの引き出しを含む)は #3575 から
     `SidebarListOptionsMenu`。WorktreeCard は #1135 で最後の描画元 WorktreeList を削除済み
     (`git log -S"<WorktreeCard"`)。よって 2 部品とそのテストを削除した。
   - BranchListItem-worktree-status-3594.test.tsx の
     「WorktreeCard says where the status is changed (Issue #3594)」は削除したファイルの
     ソースを読むだけのテストなので、決定 1 の「そのテスト」に含めて削除した(不要になった
     fs / path の import も外した)。
   - next-action-helper.ts の冒頭コメントは今の利用元(/api/worktrees 経由の Review 画面と
     sidebar.ts の toBranchItem)に、WorktreeDetailSubComponents.tsx の #1787 のコメントから
     WorktreeCard を外した。
2. /more の Repositories: `common.nav.repositories`(en「Repositories」/ ja「リポジトリ」)が
   そのまま使えたので新しいキーは足していない。
3. docs/en/user-guide/webapp-guide.md の「[N others ▾]」3 箇所を画面
   (locales/en/worktree.json の agentStatus.otherSessions = "{count} more")どおり
   「[N more ▾]」に。ja 版の「ほか N ▾」は画面と一致。
4. 「…」の吹き出し: 原因は `clampOverflowPanelLeft` の左の下限が画面の左端+8px だったこと。
   1024 幅・サイドバー開では「…」の右端(約 436px)より吹き出し(約 512px)が広く、
   右揃えの位置が負になって x=8(サイドバーの上)に固定されていた。下限を本文
   (`terminal-split-container`)の左端+8px に変え(第 4 引数 regionLeft、省略時は従来どおり 0)、
   max-width も本文の左端から測る(regionLeft 0 で従来の calc(100vw - 16px) と同じ値)。
   受入は jsdom で rect を差し替えた描画テスト(style の left / max-width)と、
   e2e spec(tests/e2e/action-bar-overflow-sidebar-3651.spec.ts、走らせるのは UAT)。

テスト: 陽性対照は直す前の TerminalSplitContainer.tsx / SettingsPanel.tsx で 6 件落ちることを
確認(ファイルを HEAD の版に一時的に戻して実行、すぐ戻した)。docs のテストは os.tmpdir() の
コピーで旧表記を検出する対照を置いた。既存の 3590 の clampOverflowPanelLeft のテストは無変更で通る。

## 対になる場所を探した結果
- 同じ吹き出しの別経路: `ActionBarItemsOverflow` の呼び出しは TerminalSplitContainer.tsx の 1 箇所だけ。
  ヘッダーの道具の「…」(HeaderToolBar)は右端にあり左へ伸びても本文内なので対象外と判断。
- スマホ: 2 段目の action bar は PC 専用(スマホは描かない)。
- docs の ja と en: ja の webapp-guide は画面と一致。

## 本文に無い指摘
- docs/en/UI_UX_GUIDE.md:57 も「[N others ▾]」(画面は「N more」)。scope 外のため未修正。
- docs/features/sidebar-status-indicator.md:72・:75 が削除した WorktreeCard に触れている。scope 外のため未修正。
- locales/{en,ja}/worktree.json の `card.*`(WorktreeCard だけが使っていたキー)が未使用になった。
  キーの削除はこの Issue の範囲を超えるので残した。
- `isNextActionKey`(src/lib/session/next-action-helper.ts)は src からの利用が WorktreeCard だけだった。
- docs/module-reference.md:791(Sidebar.tsx の行)の「SortSelectorBase は Sessions 画面用に残る」が
  実態と違う(断片 dev-reports/module-reference/issue-3651.md に書き換えを記載)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 本目(91b314493)の「本文に無い指摘」のうち、2 本目の契約で直すと決めた 4 件。

## 決めたこと・確かめたこと
1. docs/en/UI_UX_GUIDE.md: 「[N others ▾]」を画面(locales/en/worktree.json の
   agentStatus.otherSessions = "{count} more")どおり「[N more ▾]」に。:57 の図に加え、
   同じ表記の :75(Session field の説明)も直した。ja 版の「ほか N ▾」は画面と一致。
   grep: docs 全体で「N others」は 0 件になった。
2. docs/features/sidebar-status-indicator.md:72・:75: WorktreeCard の記述を外した。
   isNextActionKey() の段落は呼び出し元ごと無くなったので削除。awaitingInstruction の緑バッジの
   表示先は今の実装(BranchListItem.tsx と WorktreeDetailSubComponents.tsx の
   desktop-awaiting-instruction-badge、どちらも awaitingInstruction.badge)に合わせて
   「サイドバー行と PC の worktree 詳細ヘッダー」とした。
3. locales/{en,ja}/worktree.json の card.*(main / description / link / openLink / updated):
   grep で src からの使用は 5 キーとも 0 件(`card.<key>` の直書き・テンプレート文字列とも無し。
   src にある t('card.*') は ExternalAppCard.tsx の externalApps 名前空間で別物)。
   en / ja から同じく card グループごと削除。キーの存在を要求していた
   tests/unit/i18n/worktree-git-panels-keys.test.ts の一覧の card.* 5 件と
   placeholder の ['worktree', 'card.updated', ['{time}']] を外した(it / describe は無変更。
   en / ja のキー一致の parity テストは通る)。
4. src/lib/session/next-action-helper.ts の isNextActionKey: grep で src からの使用は 0 件
   (使っていたのは削除済みの WorktreeCard だけ)。関数と、それだけが使う NEXT_ACTION_KEY_SET を
   削除し、tests/unit/next-action-helper.test.ts の describe('isNextActionKey') と import を削除
   (決定で許可された範囲)。NextActionKey 型は src/types/sidebar.ts が使うので残した。

テスト: tests/unit/docs/worktree-card-leftovers-3651.test.ts を追加。4 ファイルを HEAD の版に
一時的に戻すと 4 件落ちる(陽性対照)ことを確かめ、すぐ戻した。os.tmpdir() のコピーで旧表記・
旧記述・旧キーを検出する対照と、今の形を通す対照を置いた。

## 対になる場所を探した結果
- docs の ja(docs/UI_UX_GUIDE.md、docs/user-guide/webapp-guide.md)は画面と一致。直すもの無し。
- docs/ で WorktreeCard / isNextActionKey を挙げるのは docs/module-reference.md だけ(下記)。

## 本文に無い指摘
- docs/module-reference.md:710(next-action-helper.ts の行)が isNextActionKey() を説明している。
  scope 外のため未修正(断片 dev-reports/module-reference/issue-3651.md に記載)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
整合性レビューの指摘: 吹き出しの幅を本文の左端から測るようにした(91b314493)ので、
PC 768px でサイドバーを最大 480px(AppShell.tsx の MAX_SIDEBAR_WIDTH)まで広げると上限は
768 - 480 - 16 = 272px。1 分割の「…」には札とセッションの操作(選択・Terminal / Chat・モデル・
メモ)が退避され、1 行のままでは約 512px あるため箱からはみ出し、届かない操作が出る。

## 直し方と理由
- 吹き出しを `flex-wrap` にした(定数 OVERFLOW_PANEL_CLASS)。札とセッションの欄が行を分けて
  並び、重ならず、箱の中に収まる。収まる幅(1024 幅など)では従来どおり 1 行のまま。
- 退避中のセッションの欄(split-action-bar-session)に `max-w-full` を付けた(`min-w-0` は既存)。
  1 行に入りきらないときは欄が箱の幅まで縮み、中の選択(バーでは min-w-0)・モデル・メモは
  既存の truncate で省略される。札の根は元から `max-w-full` で題名が truncate する。
  Terminal / Chat の切替(flex-shrink-0、約 135px)を含めても最小幅は 272px の内側に収まる。
- スクロール(overflow-x-auto)は採らなかった。overflow を付けると札の理由の吹き出しや
  選択のメニューが切れる恐れがあり、スクロールバー越しに隠れる操作も「届く」と言いにくい。
- 契約の範囲(TerminalSplitContainer.tsx)だけで直った。TerminalSplitPane.tsx は変えていない。

## テスト
- tests/unit/components/worktree/action-bar-overflow-narrow-3651.test.tsx(新規):
  768px・本文の左端 480px で、吹き出しの max-width 272px・left 488px・`flex-wrap`・overflow なし、
  退避した操作がすべて吹き出しの中にあり、札の根とセッションの欄が `max-w-full` であることを
  描画結果で確かめる。直す前の TerminalSplitContainer.tsx(HEAD の版に一時的に戻して実行、すぐ戻した)
  では 2 件落ちる(陽性)。1440px・サイドバー閉では右揃えの位置と幅が従来どおり、収まる間は
  バーのセッションの欄の class が従来どおり(陰性)。
- tests/e2e/action-bar-overflow-sidebar-3651.spec.ts に 768×768・サイドバー 480px のケース
  (吹き出しが本文の中・幅 272px 以下、札・ⓘ・選択・Terminal・Chat が箱の中で最前面に描かれ
  互いに重ならない、scrollWidth が clientWidth を超えない)と、1024 幅で 1 行のままの陰性を追加。
  1024×768・サイドバー開の既存ケースはそのまま。e2e は書いただけで、走らせるのは UAT。

## 対になる場所を探した結果
- ActionBarItemsOverflow の呼び出しは TerminalSplitContainer.tsx の 1 箇所だけ。
- ヘッダーの道具の「…」(HeaderToolBar)は別の部品で、clampOverflowPanelLeft / 本文の左端からの
  上限を使っていないため、今回の変更は及ばない。直すもの無し。

## 本文に無い指摘
無し

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
整合性レビューの再レビューの指摘。b5df64a で吹き出しの外側(札とセッションの欄)は折り返す
ようにしたが、セッションの欄の中は TerminalSplitPane.tsx の 1 列のまま(`split-bar-session-N`、
`relative flex min-w-0 items-center gap-1.5`)だった。狭い本文(768px・サイドバー 480px、表示
サイズ「大」ではさらに狭い)で、前日以前のメモ(日時に日付が付く)を持つ実行中のセッション
(終了ボタンあり)を退避すると、選択・Terminal / Chat・メモと日時・終了ボタンが 1 行に詰まる。

## 直し方と理由
- 退避中だけ、欄の中の行を折り返す。TerminalSplitContainer.tsx は退避中のセッションの欄
  (split-action-bar-session)に `data-folded="true"` と `group/bar-session` を付け、
  TerminalSplitPane.tsx の行は `group-data-[folded=true]/bar-session:flex-wrap` を持つ
  (定数 BAR_SESSION_ROW_CLASS)。行の `gap-1.5` は行間にも効く。
- Pane に退避の状態を渡す経路(SplitHeaderSlots の型)は SplitPaneHeaderControls.tsx で範囲外の
  ため、React の再描画を増やさない CSS の group 変種にした。生成される CSS は
  `:where(.group\/bar-session)[data-folded="true"] *` → `flex-wrap: wrap`(tailwindcss 4.3.2 の
  compile で確認)。
- 退避していない 2 段目では欄に data-folded も group も付かず、行の class の効き方も変わらない
  (1 行のまま。欄の class は従来の文字列のまま)。
- 縦の配置ではなく折り返しにしたのは、幅に余裕がある吹き出し(1024 幅など)では 1 行のまま
  見せられ、狭いときだけ必要な分だけ行が増えるため。
- TerminalSplitContainer.tsx の OVERFLOW_PANEL_CLASS のコメントを実際の構造に合わせた。
  理由の吹き出し(PC は body への portal)と選択の Radix メニュー(portal)は overflow で切れない
  ので、その説明は外し、本当の理由(退避した操作をすべて一度に見せる。スクロールでは一部が
  スクロールバーの先に隠れ、キーボードのフォーカスが見えない位置に入りうる)に直した。

## テスト
- tests/unit/components/worktree/action-bar-overflow-session-row-3651.test.tsx(新規):
  前日のメモ・終了ボタン(headerExtras)を持つセッションを狭いバーで退避すると、欄が
  data-folded="true" の group/bar-session で、行が折り返しの class を持ち、CSS の selector どおり
  行がその group の下にあり、選択・Terminal・Chat・メモ・日時・終了ボタンがすべて行の中にある(陽性)。
  直す前の 2 ファイル(HEAD の版に一時的に戻して実行、すぐ戻した)では 1 件落ちる。
  退避していないときは欄に data-folded が無く、class は従来の文字列、行に無条件の flex-wrap が
  無い(陰性)。
- tests/e2e/action-bar-overflow-sidebar-3651.spec.ts: 768×768・サイドバー 480px・表示サイズ
  medium / large で、実行中(current-output の isRunning)・前日のメモ(sessionNotes)のセッションを
  退避したケースを追加(終了ボタンと日付つきの日時が出ていることを前提として確認、各操作が
  吹き出しの箱の中で最前面に描かれ互いに重ならない、日時がメモの中、行の flex-wrap が wrap、
  行と吹き出しの scrollWidth が clientWidth を超えない)。陰性として 1440 幅で退避せず 1 行
  (flex-wrap が nowrap)。e2e は書いただけで、走らせるのは UAT。

## 対になる場所を探した結果
- 同じ行の 2 分割以上の場合(各分割の 30px の見出し、split-header-N)は「…」に退避しないので
  対象外。退避の経路は TerminalSplitContainer.tsx の ActionBarItemsOverflow 1 箇所だけ。
- 札(VerificationStatusChip)の中は元から max-w-full と題名の truncate で、変更不要。

## 本文に無い指摘
無し

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
768px・表示サイズ medium / large の e2e で、worktree 一覧のモックが配列を
返していた。共有のキャッシュ(src/hooks/useWorktreesCache.ts)は
data.worktrees を読むので一覧が空になり、一覧からメモを読む useSessionNote
には保存済みのメモが届かず、前提が成り立っていなかった。

各モックを、ルートの実装を読んで実際の応答の形に合わせた。
- GET /api/worktrees(src/app/api/worktrees/route.ts): 配列 → { worktrees:
  [row], repositories: [] }。行は worktree にセッションの状態
  (sessionStatusByCli / sessionStatusByInstance / isSessionRunning /
  isWaitingForResponse / isProcessing)と sessionNotes・autoYesByInstance・
  lastActivityByInstance を足した形。実際の応答にある defaultSelectedAgents
  と tmuxSessionNamespace、行の agentInstances は、この画面の経路で読まれず
  共有の fixture も持たないので省いた。
- GET /api/worktrees/:id([id]/route.ts): worktree に gitStatus と
  セッションの状態を展開した形。実際の応答に無い sessionNotes を外し、
  無かった sessionStatusByInstance / isSessionRunning / isWaitingForResponse /
  isProcessing を足した(agentInstances は共有の fixture と同じく省略)。
- GET /api/worktrees/:id/current-output(current-output/route.ts):
  CurrentOutputPayload に agentMode を足した形。型に無い isGenerating を外し、
  必須の sessionName / sessionStatus / sessionStatusReason / lineCount と
  agentMode を足した。終了ボタンはここの isRunning で描かれる。
- それ以外(messages・tasks・verify など)は setupSplitTest の共有モックに
  落ちる。この spec では変えていない。

メモの日時の assert は既にあった(split-session-note-time-0 の日付つきの
時刻)。加えて、メモの本文が一覧から届いて描かれていること
(split-session-note-0 が本文を含む)を先に確かめ、モックの形が崩れたら
ここで落ちるようにした。1440 幅の陰性にも、同じ前提(メモの本文と日時、
終了ボタン)の assert を足した。

e2e は書いただけで走らせていない(UAT で走らせる)。lint と tsc は clean。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Kewton Kewton added the bug Something isn't working label Oct 13, 2026
@Kewton
Kewton merged commit 0e831d2 into develop Oct 13, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant