Skip to content

Commit 9d1482d

Browse files
wesmclaude
andcommitted
Add tests for TUI selection retention behavior
Tests cover: - Selection maintained when new jobs inserted at top - Selection clamps when selected job is removed - First job selected when transitioning from empty - Selection cleared when list becomes empty 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7fdac91 commit 9d1482d

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

cmd/roborev/tui_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,103 @@ func TestTUIHTTPTimeout(t *testing.T) {
200200
t.Fatalf("Expected tuiErrMsg for timeout, got %T: %v", msg, msg)
201201
}
202202
}
203+
204+
func TestTUISelectionMaintainedOnInsert(t *testing.T) {
205+
m := newTuiModel("http://localhost")
206+
207+
// Initial state with 3 jobs, select the middle one (ID=2)
208+
m.jobs = []storage.ReviewJob{
209+
{ID: 3}, {ID: 2}, {ID: 1},
210+
}
211+
m.selectedIdx = 1
212+
m.selectedJobID = 2
213+
214+
// New jobs added at the top (newer jobs first)
215+
newJobs := tuiJobsMsg([]storage.ReviewJob{
216+
{ID: 5}, {ID: 4}, {ID: 3}, {ID: 2}, {ID: 1},
217+
})
218+
219+
updated, _ := m.Update(newJobs)
220+
m = updated.(tuiModel)
221+
222+
// Should still be on job ID=2, now at index 3
223+
if m.selectedJobID != 2 {
224+
t.Errorf("Expected selectedJobID=2, got %d", m.selectedJobID)
225+
}
226+
if m.selectedIdx != 3 {
227+
t.Errorf("Expected selectedIdx=3 (ID=2 moved), got %d", m.selectedIdx)
228+
}
229+
}
230+
231+
func TestTUISelectionClampsOnRemoval(t *testing.T) {
232+
m := newTuiModel("http://localhost")
233+
234+
// Initial state with 3 jobs, select the last one (ID=1)
235+
m.jobs = []storage.ReviewJob{
236+
{ID: 3}, {ID: 2}, {ID: 1},
237+
}
238+
m.selectedIdx = 2
239+
m.selectedJobID = 1
240+
241+
// Job ID=1 is removed
242+
newJobs := tuiJobsMsg([]storage.ReviewJob{
243+
{ID: 3}, {ID: 2},
244+
})
245+
246+
updated, _ := m.Update(newJobs)
247+
m = updated.(tuiModel)
248+
249+
// Should clamp to last valid index and update selectedJobID
250+
if m.selectedIdx != 1 {
251+
t.Errorf("Expected selectedIdx=1 (clamped), got %d", m.selectedIdx)
252+
}
253+
if m.selectedJobID != 2 {
254+
t.Errorf("Expected selectedJobID=2 (new selection), got %d", m.selectedJobID)
255+
}
256+
}
257+
258+
func TestTUISelectionFirstJobOnEmpty(t *testing.T) {
259+
m := newTuiModel("http://localhost")
260+
261+
// No prior selection (empty jobs list, zero selectedJobID)
262+
m.jobs = []storage.ReviewJob{}
263+
m.selectedIdx = 0
264+
m.selectedJobID = 0
265+
266+
// Jobs arrive
267+
newJobs := tuiJobsMsg([]storage.ReviewJob{
268+
{ID: 5}, {ID: 4}, {ID: 3},
269+
})
270+
271+
updated, _ := m.Update(newJobs)
272+
m = updated.(tuiModel)
273+
274+
// Should select first job
275+
if m.selectedIdx != 0 {
276+
t.Errorf("Expected selectedIdx=0, got %d", m.selectedIdx)
277+
}
278+
if m.selectedJobID != 5 {
279+
t.Errorf("Expected selectedJobID=5 (first job), got %d", m.selectedJobID)
280+
}
281+
}
282+
283+
func TestTUISelectionEmptyList(t *testing.T) {
284+
m := newTuiModel("http://localhost")
285+
286+
// Had jobs, now empty
287+
m.jobs = []storage.ReviewJob{{ID: 1}}
288+
m.selectedIdx = 0
289+
m.selectedJobID = 1
290+
291+
newJobs := tuiJobsMsg([]storage.ReviewJob{})
292+
293+
updated, _ := m.Update(newJobs)
294+
m = updated.(tuiModel)
295+
296+
if m.selectedIdx != 0 {
297+
t.Errorf("Expected selectedIdx=0, got %d", m.selectedIdx)
298+
}
299+
if m.selectedJobID != 0 {
300+
t.Errorf("Expected selectedJobID=0, got %d", m.selectedJobID)
301+
}
302+
}

0 commit comments

Comments
 (0)