Skip to content

ディープリンク再実装とMaestro E2Eリグレッションテストの追加 #5439

Merged
TinyKitten merged 12 commits intodevfrom
claude/e2e-train-line-tests-z5YPw
Feb 23, 2026
Merged

ディープリンク再実装とMaestro E2Eリグレッションテストの追加 #5439
TinyKitten merged 12 commits intodevfrom
claude/e2e-train-line-tests-z5YPw

Conversation

@TinyKitten
Copy link
Member

@TinyKitten TinyKitten commented Feb 23, 2026

Summary

  • ディープリンク機能(useDeepLink / useOpenRouteFromLink)を削除し、SelectBoundModal.handleBoundSelectedパターンに準拠して再実装
  • navigationRefを導入し、ランタイムディープリンクでもMain画面へ明示的にナビゲート
  • DeepLinkProviderinitialUrlProcessedフラグを追加し、初回URL処理完了までレンダリングをブロックするレースコンディション修正
  • 山手線(内回り/外回り)のMaestro E2Eリグレッションテストを追加(stopApp + openLinkによるコールドスタートディープリンク、permissions: { all: allow }でPrivacy画面バイパス)

Key Changes

  • src/hooks/useDeepLink.ts: lid必須化、lgidオプション、CommonActions.navigateによるランタイムナビゲーション
  • src/stacks/rootNavigation.ts: createNavigationContainerRefnavigationRefをエクスポート
  • src/index.tsx: NavigationContainerref={navigationRef}を設定
  • src/providers/DeepLinkProvider.tsx: initialUrlProcessedでレンダリングゲート
  • .maestro/yamanote-inbound.yaml / yamanote-outbound.yaml: 新宿駅起点の駅進行シミュレーションE2Eテスト
  • src/hooks/useOpenRouteFromLink.ts / .test.tsx: 削除

Test plan

  • pnpm test 全134スイート、1241テスト合格
  • pnpm lint パス
  • pnpm typecheck パス
  • Maestroフロー実機確認(maestro test .maestro/yamanote-inbound.yaml

https://claude.ai/code/session_01XAuZBUUyZ8AbCLWSZyHtsh

Summary by CodeRabbit

  • テスト

    • 山手線(内回り/外回り)のエンドツーエンド回帰テストを追加しました。
    • ディープリンク処理のユニットテストを大幅に拡充しました。
  • バグ修正

    • ディープリンク受信時の初期処理、画面遷移の信頼性、駅表示の安定性を改善しました。
  • リファクタ

    • ディープリンクワークフローを再設計し、初期URL処理、読み込み/エラー集約、ナビゲーション準備待ちを強化しました。
  • 雑作業

    • 開発ランチャー関連のビルド参照と起動スクリプトを簡素化しました。

@github-actions github-actions bot added the react label Feb 23, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

既存の useOpenRouteFromLink フックとそのテストを削除し、ディープリンク処理を拡張した useDeepLink に統合。DeepLinkProvider の表示条件を更新し、グローバルな navigationRef を導入。Maestro の山手線 inbound/outbound E2E 設定を追加。

Changes

Cohort / File(s) Summary
Maestro E2E テスト設定
/.maestro/yamanote-inbound.yaml, /.maestro/yamanote-outbound.yaml
山手線 inbound/outbound の Maestro E2E 設定を追加(ディープリンク注入、アプリ初期化、Main 画面の駅表示待機と進行アサーション)。
削除された旧フックとテスト
src/hooks/useOpenRouteFromLink
src/hooks/useOpenRouteFromLink.ts, src/hooks/useOpenRouteFromLink.test.tsx, src/hooks/index.ts
useOpenRouteFromLink の実装と対応テストを削除し、hooks バレルからの再エクスポートを除去。
拡張された Deep Link 処理とテスト
src/hooks/useDeepLink.ts, src/hooks/useDeepLink.test.tsx
useDeepLink を大幅拡張(Apollo useLazyQuery で line/lineGroup を取得、applyRoute による jotai state 設定、初期URL 処理・ランタイムリスナ、ナビゲーション待機/リトライ、loading/error と initialUrlProcessed を公開)。単体テストを包括的に追加。
プロバイダとナビゲーションの調整
src/providers/DeepLinkProvider.tsx, src/index.tsx, src/stacks/rootNavigation.ts
DeepLinkProvider の読み込み/エラー判定を新フックに合わせて更新。グローバル navigationRef を追加して NavigationContainer に配線。
iOS プロジェクト / パッケージ設定
ios/TrainLCD.xcodeproj/project.pbxproj, package.json
Expo dev launcher/dev menu バンドル参照を pbxproj から削除。start スクリプトを expo start に変更し、expo-dev-client を削除。
ドキュメント削除
docs/spec/test/e2e.md
Maestro E2E の記述を削除(ドキュメントのみ削除)。

Sequence Diagram(s)

sequenceDiagram
    participant App as App / DeepLinkProvider
    participant Hook as useDeepLink
    participant GraphQL as Apollo (line / lineGroup queries)
    participant Store as Jotai Atoms
    participant Nav as Navigation (navigationRef)

    rect rgba(135,206,250,0.5)
    App->>Hook: 初期URL取得またはイベントで handleUrl(url)
    end

    rect rgba(144,238,144,0.5)
    Hook->>GraphQL: useLazyQuery(fetch by lineGroupId OR lineId)
    GraphQL-->>Hook: stations data / error
    end

    rect rgba(255,228,181,0.5)
    Hook->>Store: applyRoute -> setLine / setStation / setNavigation
    Store-->>Hook: state 更新完了
    end

    rect rgba(221,160,221,0.5)
    Hook->>Nav: navigationRef.isReady? -> navigate('Main') (retry logic)
    Hook-->>App: initialUrlProcessed / isLoading / error(集約)
    App->>App: 表示制御(ロード待ち or children 表示)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

ios

Poem

🐰 ディープリンクでぴょんと飛び込むよ、駅名が並んで光る、
新宿から次へ、state をそっと並べて、ナビは準備を待つ、
兎はリトライを数え、画面が動き出すのを見て跳ねる、
テストは緑、ログは柔らかく、今日もデプロイ前の小さな祝祭。

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed タイトルは主な変更内容(ディープリンク再実装とMaestro E2Eテストの追加)を的確に要約しており、変更内容全体をよく反映しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/e2e-train-line-tests-z5YPw

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/__fixtures__/yamanote.ts`:
- Around line 194-200: nameChinese フィールドが置換文字「�」を含む壊れた文字列になっていますので、fixtures
の該当エントリ(id: 1130210、name: '駒込' のオブジェクト)の nameChinese
プロパティの値を正しい中国語表記に修正してください(例: "駒込"
または適切な簡体字/繁体字表記に置き換え)。修正後、src/__fixtures__/yamanote.ts の該当オブジェクト(name, id
が目印)を更新してスナップショットやZH表示のテストを再実行してください。

In `@src/test/e2eHelpers.ts`:
- Around line 111-128: buildHeaderProps computes nextStation by using
currentIndex +/-1 which becomes undefined at line endpoints; detect loop lines
(e.g., config.selectedLine.isLoopLine or add an isLoopLine flag) and when
isLoopLine is true wrap the index arithmetic instead of returning undefined:
compute nextIndex = (currentIndex + (config.selectedDirection === 'INBOUND' ? 1
: -1) ± stations.length) % stations.length and use stations[nextIndex] for
nextStation so circular routes correctly wrap; ensure fallback for non-loop
lines still returns undefined when out of bounds.

In `@src/test/mainScreen.e2e.test.tsx`:
- Around line 338-341: The tests currently call jest.clearAllMocks() inside a
beforeEach; move that call into an afterEach block instead (for the describe
'メイン画面 E2E: Header (HeaderE235)' and the other describe flagged around lines
514-516) so mocks are cleared after each test; locate the existing beforeEach
that contains jest.clearAllMocks() and replace it with an afterEach containing
jest.clearAllMocks() to satisfy the guideline.
- Around line 1-16: This E2E test is standalone but must extend the shared
integration harness in src/test/e2e.ts instead of calling render directly;
replace direct use of render from '@testing-library/react-native' in
mainScreen.e2e.test.tsx by importing and using the shared setup/render helper
exported by src/test/e2e.ts (e.g., setupTestApp or renderApp from that module)
and move any Jotai state injection into that harness extension so the test uses
the common e2e flow and helpers.

@TinyKitten TinyKitten self-assigned this Feb 23, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/hooks/useDeepLink.test.tsx (1)

352-370: リスナーのクリーンアップテストの追加を検討してください。

イベントリスナーの登録は検証されていますが、コンポーネントのアンマウント時に remove 関数が呼ばれることを検証するテストがあると、メモリリーク防止の保証が強化されます。

♻️ クリーンアップテストの例
it('アンマウント時にURLイベントリスナーを解除する', () => {
  mockGetInitialURL.mockResolvedValue(null);

  setupAtoms();
  setupQueries();
  const mockRemove = jest.fn();
  mockAddEventListener.mockReturnValue({ remove: mockRemove });

  const { unmount } = render(
    <HookBridge
      onReady={() => {
        /* noop */
      }}
    />
  );

  unmount();

  expect(mockRemove).toHaveBeenCalled();
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useDeepLink.test.tsx` around lines 352 - 370, Add a test that
ensures the URL event listener is cleaned up on unmount: in the test for
HookBridge, set mockGetInitialURL.mockResolvedValue(null), create const
mockRemove = jest.fn(), have mockAddEventListener.mockReturnValue({ remove:
mockRemove }), render HookBridge, call unmount(), and assert mockRemove was
called; this verifies the remove function returned by mockAddEventListener is
invoked during component teardown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/hooks/useDeepLink.test.tsx`:
- Around line 352-370: Add a test that ensures the URL event listener is cleaned
up on unmount: in the test for HookBridge, set
mockGetInitialURL.mockResolvedValue(null), create const mockRemove = jest.fn(),
have mockAddEventListener.mockReturnValue({ remove: mockRemove }), render
HookBridge, call unmount(), and assert mockRemove was called; this verifies the
remove function returned by mockAddEventListener is invoked during component
teardown.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useDeepLink.ts`:
- Around line 166-183: Wrap the async calls to handleUrl in try/catch/finally so
that setInitialUrlProcessed is always invoked even if handleUrl throws: modify
checkInitialUrl to try { await handleUrl(initialUrl) } catch (err) { /* log */ }
finally { setInitialUrlProcessed(true) }; likewise in the Linking event listener
call handleUrl(e.url).catch(...) to swallow/log errors (prevent unhandled
promise rejections) and ensure the cleanup returns a function that calls
listener.remove() to unregister the listener; reference functions/vars:
handleUrl, setInitialUrlProcessed, checkInitialUrl, listener.remove.
- Around line 88-131: The openLink/handleUrl flow assumes lineId is required but
also has a branch that should work with only lineGroupId; update the types and
validation to allow that: make lineId optional (number | undefined) in
openLink's parameter type and any related type defs, change the handleUrl
validation from if (!stationGroupId || !lineId) to if (!stationGroupId ||
(!lineId && !lineGroupId)), and before calling fetchStationsByLineId (and using
lineId) add a guard that lineId is defined so you only follow the lineId path
when present; keep the existing lineGroupId branch as-is.

@TinyKitten TinyKitten changed the title Add E2E snapshot tests for main screen header component ディープリンク再実装とMaestro E2Eリグレッションテストの追加 Feb 23, 2026
@TinyKitten
Copy link
Member Author

@coderabbitai resume

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

✅ Actions performed

Reviews resumed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.maestro/yamanote-inbound.yaml (1)

44-46: assertTruecondition: true は常に成功するため、実質的なアサーションになっていません。

この assertTrue は condition: true が固定値のため、テストの成否に関係なく常にパスします。実際の検証は extendedWaitUntil で行われているので、このアサーションは削除するか、実際の状態を検証するように修正することを検討してください。

♻️ 修正案: 不要なアサーションを削除
 - extendedWaitUntil:
     visible:
       text: ".*代々木.*"
     timeout: 120000
     label: "シミュレーション進行: 代々木駅が表示される"
-
-- assertTrue:
-    condition: true
-    label: "内回り: 新宿から代々木への駅進行を確認"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.maestro/yamanote-inbound.yaml around lines 44 - 46, The assertTrue step
currently uses a fixed condition (assertTrue with condition: true) which always
passes and is redundant because the real check is performed by
extendedWaitUntil; remove the assertTrue block (or replace it with a meaningful
assertion that checks the actual station/state) so the YAML only relies on the
existing extendedWaitUntil verification or an assert that references the real
condition, and ensure you update or remove the label "内回り: 新宿から代々木への駅進行を確認"
accordingly to reflect the retained verification.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useDeepLink.ts`:
- Around line 117-124: The current useDeepLink flow calls
navigationRef.dispatch(CommonActions.navigate(...)) only when
navigationRef.isReady() is true and lacks a fallback; add a retry/fallback path
so the app doesn't get stuck on the Privacy screen when isReady() is false:
implement a short exponential/backoff retry loop that re-checks
navigationRef.isReady() for a bounded number of attempts (or timeout) and then
dispatches CommonActions.navigate to 'MainStack' -> 'Main' when ready, and if
still not ready, perform a safe fallback such as queuing the intended route in a
pendingNavigation variable or logging and calling a replacement navigation
method (or show a user-friendly error) so the behavior in the block around
navigationRef.isReady() and the similar block at the second occurrence (the code
around the CommonActions.navigate at the other location) both handle the false
case gracefully.

---

Duplicate comments:
In `@src/hooks/useDeepLink.ts`:
- Around line 184-193: The effect's async function checkInitialUrl can skip
calling setInitialUrlProcessed(true) if handleUrl throws; update checkInitialUrl
to wrap the await Linking.getInitialURL() and await handleUrl(initialUrl) in
try/catch and use a finally block to always call setInitialUrlProcessed(true).
Also log or forward the caught error inside the catch so failures in handleUrl
(or Linking.getInitialURL) are visible; this change touches the checkInitialUrl
function within the useEffect that calls Linking.getInitialURL(), handleUrl, and
setInitialUrlProcessed.
- Around line 163-165: The guard currently returns when either stationGroupId or
lineId is missing, preventing URLs that contain only lineGroupId from reaching
the existing lineGroupId handling; change the condition in useDeepLink so it
only returns when both are missing (i.e., require at least one of stationGroupId
or lineId). Update the check that references stationGroupId and lineId to use a
logical AND (both absent) rather than OR, so the later lineGroupId branch can
run.
- Around line 195-201: The event callback passed to Linking.addEventListener
calls handleUrl(e.url) but does not handle its returned Promise, risking
Unhandled Promise Rejection; update the listener to explicitly handle the
Promise (e.g., call void handleUrl(e.url).catch(err => /* log or handle error
*/) or Promise.resolve(handleUrl(e.url)).catch(err => /* log or handle error
*/)) so any rejection is caught, keeping the useEffect cleanup (return
listener.remove) unchanged and referencing the same handleUrl and
listener.remove symbols.

---

Nitpick comments:
In @.maestro/yamanote-inbound.yaml:
- Around line 44-46: The assertTrue step currently uses a fixed condition
(assertTrue with condition: true) which always passes and is redundant because
the real check is performed by extendedWaitUntil; remove the assertTrue block
(or replace it with a meaningful assertion that checks the actual station/state)
so the YAML only relies on the existing extendedWaitUntil verification or an
assert that references the real condition, and ensure you update or remove the
label "内回り: 新宿から代々木への駅進行を確認" accordingly to reflect the retained verification.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/hooks/useDeepLink.test.tsx (1)

101-117: setupAtoms のモック実装がコール順序に依存しすぎている。

atomCallIdx % 3 でセッターを順番に返す実装は、フックの内部実装(useSetAtom の呼び出し順序)に強く依存しています。フックのリファクタリングでアトムの追加や順序変更があるとテストが壊れやすくなります。

アトムを明示的に識別してモックするか、少なくとも現状の順序依存を認識できるようコメントを追加することを推奨します。

♻️ 順序依存を明示するコメント追加案
   const setupAtoms = () => {
     const mockSetStationState = jest.fn();
     const mockSetNavigationState = jest.fn();
     const mockSetLineState = jest.fn();
+    // NOTE: フック内のuseSetAtom呼び出し順序に依存
+    // 1: stationState, 2: navigationState, 3: lineState
     const setters = [
       mockSetStationState,
       mockSetNavigationState,
       mockSetLineState,
     ];
     let atomCallIdx = 0;
     mockUseSetAtom.mockImplementation(() => {
       const result = setters[atomCallIdx % 3];
       atomCallIdx++;
       return result;
     });
     return { mockSetStationState, mockSetNavigationState, mockSetLineState };
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useDeepLink.test.tsx` around lines 101 - 117, The current
setupAtoms mock uses an order-dependent implementation of mockUseSetAtom
(cycling setters via atomCallIdx % 3), which breaks if useSetAtom call order
changes; update the mock so mockUseSetAtom inspects its input atom argument and
returns the corresponding setter (map specific atoms to mockSetStationState,
mockSetNavigationState, mockSetLineState) instead of relying on call index, or
if you prefer to keep the index approach add a clear comment in setupAtoms
explaining the order dependency and why the cycle is used; ensure you reference
mockUseSetAtom, setupAtoms, and the three setter mocks (mockSetStationState,
mockSetNavigationState, mockSetLineState) when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/hooks/useDeepLink.ts`:
- Around line 216-233: Wrap calls to handleUrl in try/catch/finally so
setInitialUrlProcessed(true) always runs: inside the checkInitialUrl async
function, await handleUrl(initialUrl) inside a try block, catch and
log/error-handle any thrown errors, and put setInitialUrlProcessed(true) in a
finally block; similarly, update the Linking.addEventListener callback to call
handleUrl(e.url) and handle any returned Promise rejections (e.g., invoke
handleUrl(e.url).catch(...)) to avoid unhandled promise rejections. Target the
checkInitialUrl function, the useEffect that registers Linking.addEventListener,
handleUrl, and setInitialUrlProcessed so DeepLinkProvider no longer blocks on
exceptions.
- Around line 131-141: Confirm whether openLink's parameter contract requires
lineId to always be present or if lineGroupId (lgid) should be usable alone; if
lineId must remain mandatory, add a clarifying comment on openLink and keep the
signature as ({ stationGroupId, direction, lineGroupId, lineId }: {
stationGroupId: number; direction: 0 | 1; lineGroupId?: number; lineId: number
}) and ensure validation/assertion logic uses lineId; if lgid should be a valid
alternative, change the type to make lineId optional (lineId?: number) and
update the validation logic inside openLink to handle cases where only
lineGroupId is provided (and update any callers/tests that assume lid is always
present); reference the openLink function and its parameter object when making
the change and update related tests that construct URLs with lid/lgid.

---

Nitpick comments:
In `@src/hooks/useDeepLink.test.tsx`:
- Around line 101-117: The current setupAtoms mock uses an order-dependent
implementation of mockUseSetAtom (cycling setters via atomCallIdx % 3), which
breaks if useSetAtom call order changes; update the mock so mockUseSetAtom
inspects its input atom argument and returns the corresponding setter (map
specific atoms to mockSetStationState, mockSetNavigationState, mockSetLineState)
instead of relying on call index, or if you prefer to keep the index approach
add a clear comment in setupAtoms explaining the order dependency and why the
cycle is used; ensure you reference mockUseSetAtom, setupAtoms, and the three
setter mocks (mockSetStationState, mockSetNavigationState, mockSetLineState)
when making the change.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/hooks/useDeepLink.test.tsx (1)

549-597: リトライ待ちのテストは fake timers で短縮すると安定します。
実時間待ち(約1.5秒)が入るため、タイマーを進めて検証するとテスト時間とフレークを抑えられます。

♻️ 例: fake timers で待機を短縮
   it('ナビゲーターが未準備の場合はリトライ後にナビゲートしない', async () => {
+    jest.useFakeTimers();
     const mockDispatch = navigationRef.dispatch as jest.Mock;
     const mockIsReady = navigationRef.isReady as jest.Mock;
     mockIsReady.mockReturnValue(false);
@@
-    await waitFor(
-      () => {
-        expect(warnSpy).toHaveBeenCalledWith(
-          expect.stringContaining('not ready after retries')
-        );
-      },
-      { timeout: 5000 }
-    );
+    await act(async () => {
+      jest.advanceTimersByTime(2000);
+    });
+    await waitFor(() => {
+      expect(warnSpy).toHaveBeenCalledWith(
+        expect.stringContaining('not ready after retries')
+      );
+    });
+    jest.useRealTimers();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useDeepLink.test.tsx` around lines 549 - 597, Use fake timers to
avoid real 1.5s backoff in this test: call jest.useFakeTimers() before rendering
HookBridge, trigger the code path (render HookBridge), then advance timers by
the total retry backoff (about 1500ms) inside an act (e.g., await act(async ()
=> { jest.advanceTimersByTime(1500) })) so the retry loop driven by
navigationRef.isReady (mockIsReady) runs immediately; afterward assert warnSpy
was called. Ensure to restore timers (jest.useRealTimers()) after the assertion.
Reference: mockIsReady, navigationRef, HookBridge, warnSpy, and the waitFor
assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/hooks/useDeepLink.test.tsx`:
- Around line 549-597: Use fake timers to avoid real 1.5s backoff in this test:
call jest.useFakeTimers() before rendering HookBridge, trigger the code path
(render HookBridge), then advance timers by the total retry backoff (about
1500ms) inside an act (e.g., await act(async () => {
jest.advanceTimersByTime(1500) })) so the retry loop driven by
navigationRef.isReady (mockIsReady) runs immediately; afterward assert warnSpy
was called. Ensure to restore timers (jest.useRealTimers()) after the assertion.
Reference: mockIsReady, navigationRef, HookBridge, warnSpy, and the waitFor
assertion.

@TrainLCD TrainLCD deleted a comment from coderabbitai bot Feb 23, 2026
@TrainLCD TrainLCD deleted a comment from coderabbitai bot Feb 23, 2026
@TrainLCD TrainLCD deleted a comment from coderabbitai bot Feb 23, 2026
@TinyKitten
Copy link
Member Author

@coderabbitai ほかになければapproveしてください

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

@TinyKitten 変更内容を確認しました。ディープリンクの再実装は適切に行われており、テストカバレッジも十分です。問題は見当たりませんので、承認いたします。


🧠 Learnings used
Learnt from: TinyKitten
Repo: TrainLCD/MobileApp PR: 0
File: :0-0
Timestamp: 2025-08-11T21:13:39.083Z
Learning: TinyKitten prefers concise code reviews for the TrainLCD/MobileApp repository. Keep review comments brief and to the point.

Learnt from: CR
Repo: TrainLCD/MobileApp PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-20T10:31:13.520Z
Learning: Code reviews and feedback should be provided in Japanese

Learnt from: CR
Repo: TrainLCD/MobileApp PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-20T10:31:13.520Z
Learning: Interaction with GitHub Copilot should be conducted in Japanese

Learnt from: TinyKitten
Repo: TrainLCD/MobileApp PR: 4448
File: functions/src/funcs/tts.ts:214-232
Timestamp: 2025-08-11T20:23:23.071Z
Learning: PR `#4448` in TrainLCD/MobileApp is specifically about AI feedback summarization and labeling functionality, not about TTS (Text-to-Speech) improvements. The TTS code changes appear to be part of a modularization refactoring but are not the focus of this PR.
✅ Actions performed

Comments resolved and changes approved.

TinyKitten and others added 2 commits February 23, 2026 15:30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the ios label Feb 23, 2026
@TinyKitten TinyKitten merged commit 9a37ee3 into dev Feb 23, 2026
6 checks passed
@TinyKitten TinyKitten deleted the claude/e2e-train-line-tests-z5YPw branch February 23, 2026 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants