Skip to content

Add tests for RewindSelector + handleRewindConfirm orchestration #4187

@doudouOUC

Description

@doudouOUC

Background

PR #4064 added two large rewind-related code paths with no direct test coverage:

  • packages/cli/src/ui/components/RewindSelector.tsx (≈239 LOC) — a 3-phase Ink component:

    1. Pick list — select which user turn to rewind to
    2. Restore options — choose code/conversation/both with async diff stats loading
    3. Legacy confirm — Y/N fallback when fileCheckpointingEnabled is false

    Plus an isRestoring keypress-guard state surfaced as a Spinner while onRewind is awaited.

  • packages/cli/src/ui/AppContainer.tsx#handleRewindConfirm (~140 LOC) — orchestrates the post-selection flow:

    • Pre-validates conversation truncation before touching files for 'both' mode
    • Routes the file-restore call (with proper truncateHistory flag)
    • Surfaces no-client / partial-failure / unrecoverable-snapshot errors via the history manager
    • Skips conversation truncation when file restore partially fails (avoids inconsistent state)
    • Falls through to a clean error path when the whole flow throws

The component / orchestration have been manually verified end-to-end via tmux-driven REPL sessions (see PR #4064 "Automated verification results" section), but there is no automated regression coverage.

Why this is a follow-up, not part of #4064

Both surfaces require similar testing scaffolding the repo does not yet use:

  • An ink-testing-library setup (rendering, keypress simulation, snapshot/text assertion) for RewindSelector
  • A heavier AppContainer mock harness — config / geminiClient / historyManager / fileHistoryService — for handleRewindConfirm

Building both layers together is the right shape (≈350-500 LOC of new test code plus a one-time pattern pass for ink-testing patterns) but bundling it into the rewind PR (already 30+ commits and several review rounds) significantly delays the merge for in-session functionality that has been manually verified.

Acceptance criteria

RewindSelector.test.tsx

  • Phase 1 (turn selection) keypress navigation up/down/enter/cancel
  • Phase 2 (restore options) renders each RestoreOption correctly
  • Phase 2 getDiffStats success populates the (+N -M in K files) detail string
  • Phase 2 getDiffStats rejection falls back to undefined diffStats without crashing
  • isRestoring blocks all keypresses including Escape (per the upstream-parity decision in PR feat(rewind): add file restoration support to /rewind command #4064)
  • Esc from Phase 2 returns to Phase 1
  • Legacy confirm Y/N path when fileCheckpointingEnabled is false
  • The "File restore is unavailable for this turn" hint shows when getRestoreOptions(...) doesn't include code/both

handleRewindConfirm tests (in AppContainer.test.tsx or a focused harness)

  • 'both' mode with file restore failure skips conversation truncation
  • 'both' mode with file restore success still truncates conversation
  • 'code' only mode does NOT truncate history
  • 'conversation' only mode does NOT call getFileHistoryService().rewind
  • No-client fallback messages: 'conversation' shows error and returns; 'both' flips into code-only with the warning history item
  • Outer try/catch surfaces unexpected errors via historyManager.addItem of type: 'error'
  • Compressed-turn error path: apiTruncateIndex < 0 adds the t-wrapped error and bails

Related

🤖 Generated with Qwen Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions