From f479f7a66071bf9dc628a5bfe00455e2a806d360 Mon Sep 17 00:00:00 2001
From: han <2992336417@qq.com>
Date: Wed, 10 Jun 2026 23:14:10 +0800
Subject: [PATCH] test: cover rewind selector fallback states (#4905)
---
.../src/ui/components/RewindSelector.test.tsx | 84 +++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/packages/cli/src/ui/components/RewindSelector.test.tsx b/packages/cli/src/ui/components/RewindSelector.test.tsx
index 6ae676bcbf..1b3f5b6207 100644
--- a/packages/cli/src/ui/components/RewindSelector.test.tsx
+++ b/packages/cli/src/ui/components/RewindSelector.test.tsx
@@ -154,4 +154,88 @@ describe('RewindSelector', () => {
expect(lastFrame()).toContain('› #2 second prompt');
expect(lastFrame()).not.toContain('Restore conversation only');
});
+
+ it('falls back to conversation-only options when diff stats fail', async () => {
+ vi.spyOn(fileHistoryService, 'getDiffStats').mockRejectedValue(
+ new Error('diff unavailable'),
+ );
+
+ const { lastFrame } = render(
+ ,
+ );
+
+ pressKey({ name: 'return' });
+ await flush();
+
+ expect(fileHistoryService.getDiffStats).toHaveBeenCalledWith('prompt-2');
+ expect(lastFrame()).toContain('Restore conversation only');
+ expect(lastFrame()).toContain('Never mind');
+ expect(lastFrame()).toContain('File restore is unavailable for this turn');
+ expect(lastFrame()).not.toContain('Restore code and conversation');
+ expect(lastFrame()).not.toContain('Restore code only');
+ });
+
+ it('does not request diff stats when the selected turn has no prompt id', async () => {
+ vi.spyOn(fileHistoryService, 'getDiffStats').mockResolvedValue({
+ filesChanged: ['src/foo.ts'],
+ insertions: 2,
+ deletions: 0,
+ });
+
+ const { lastFrame } = render(
+ ,
+ );
+
+ pressKey({ name: 'return' });
+ await flush();
+
+ expect(fileHistoryService.getDiffStats).not.toHaveBeenCalled();
+ expect(lastFrame()).toContain('Restore conversation only');
+ expect(lastFrame()).toContain('Never mind');
+ expect(lastFrame()).toContain('File restore is unavailable for this turn');
+ expect(lastFrame()).not.toContain('Restore code and conversation');
+ expect(lastFrame()).not.toContain('Restore code only');
+ });
+
+ it('confirms a conversation-only rewind when checkpointing is disabled', () => {
+ const onRewind = vi.fn();
+
+ const { lastFrame } = render(
+ ,
+ );
+
+ pressKey({ name: 'return' });
+
+ expect(lastFrame()).toContain(
+ 'This will remove all conversation after this turn.',
+ );
+
+ pressKey({ sequence: 'y' });
+
+ expect(onRewind).toHaveBeenCalledWith(
+ expect.objectContaining({ id: 2 }),
+ 'conversation',
+ );
+ });
});