diff --git a/cmd/roborev/tui/action_test.go b/cmd/roborev/tui/action_test.go index badd9957..a517e693 100644 --- a/cmd/roborev/tui/action_test.go +++ b/cmd/roborev/tui/action_test.go @@ -393,10 +393,10 @@ func TestTUIClosedToggleMovesSelectionWithHideActive(t *testing.T) { } // Simulate what happens in 'a' handler - selection should move - // Since job 2 is now hidden, find next visible - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx != 2 { - t.Errorf("Expected next visible job at index 2, got %d", nextIdx) + // Since job 2 is now hidden, find prev (older) visible job + prevIdx := m.findPrevVisibleJob(m.selectedIdx) + if prevIdx != 2 { + t.Errorf("Expected prev visible job at index 2, got %d", prevIdx) } } diff --git a/cmd/roborev/tui/handlers.go b/cmd/roborev/tui/handlers.go index f085395d..420fe248 100644 --- a/cmd/roborev/tui/handlers.go +++ b/cmd/roborev/tui/handlers.go @@ -81,11 +81,11 @@ func (m model) handleGlobalKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return m.handleHomeKey() case "up": return m.handleUpKey() - case "k", "left": + case "j", "left": return m.handlePrevKey() case "down": return m.handleDownKey() - case "j", "right": + case "k", "right": return m.handleNextKey() case "pgup": return m.handlePageUpKey() @@ -197,9 +197,9 @@ func (m model) handleHomeKey() (tea.Model, tea.Cmd) { func (m model) handleUpKey() (tea.Model, tea.Cmd) { switch m.currentView { case viewQueue: - prevIdx := m.findPrevVisibleJob(m.selectedIdx) - if prevIdx >= 0 { - m.selectedIdx = prevIdx + nextIdx := m.findNextVisibleJob(m.selectedIdx) + if nextIdx >= 0 { + m.selectedIdx = nextIdx m.updateSelectedJobID() } else { m.setFlash("No newer review", 2*time.Second, viewQueue) @@ -224,22 +224,22 @@ func (m model) handleUpKey() (tea.Model, tea.Cmd) { return m, nil } -func (m model) handlePrevKey() (tea.Model, tea.Cmd) { +func (m model) handleNextKey() (tea.Model, tea.Cmd) { switch m.currentView { case viewQueue: - prevIdx := m.findPrevVisibleJob(m.selectedIdx) - if prevIdx >= 0 { - m.selectedIdx = prevIdx + nextIdx := m.findNextVisibleJob(m.selectedIdx) + if nextIdx >= 0 { + m.selectedIdx = nextIdx m.updateSelectedJobID() } case viewReview: - prevIdx := m.findPrevViewableJob() - if prevIdx >= 0 { + nextIdx := m.findNextViewableJob() + if nextIdx >= 0 { m.closeFixPanel() - m.selectedIdx = prevIdx + m.selectedIdx = nextIdx m.updateSelectedJobID() m.reviewScroll = 0 - job := m.jobs[prevIdx] + job := m.jobs[nextIdx] switch job.Status { case storage.JobStatusDone: return m, m.fetchReview(job.ID) @@ -255,12 +255,12 @@ func (m model) handlePrevKey() (tea.Model, tea.Cmd) { m.setFlash("No newer review", 2*time.Second, viewReview) } case viewKindPrompt: - prevIdx := m.findPrevPromptableJob() - if prevIdx >= 0 { - m.selectedIdx = prevIdx + nextIdx := m.findNextPromptableJob() + if nextIdx >= 0 { + m.selectedIdx = nextIdx m.updateSelectedJobID() m.promptScroll = 0 - job := m.jobs[prevIdx] + job := m.jobs[nextIdx] if job.Status == storage.JobStatusDone { return m, m.fetchReviewForPrompt(job.ID) } else if job.Status == storage.JobStatusRunning && job.Prompt != "" { @@ -275,7 +275,7 @@ func (m model) handlePrevKey() (tea.Model, tea.Cmd) { } case viewLog: if m.logFromView == viewTasks { - idx := m.findPrevLoggableFixJob() + idx := m.findNextLoggableFixJob() if idx >= 0 { m.fixSelectedIdx = idx job := m.fixJobs[idx] @@ -285,11 +285,11 @@ func (m model) handlePrevKey() (tea.Model, tea.Cmd) { ) } } else { - prevIdx := m.findPrevLoggableJob() - if prevIdx >= 0 { - m.selectedIdx = prevIdx + nextIdx := m.findNextLoggableJob() + if nextIdx >= 0 { + m.selectedIdx = nextIdx m.updateSelectedJobID() - job := m.jobs[prevIdx] + job := m.jobs[nextIdx] m.logStreaming = false return m.openLogView( job.ID, job.Status, m.logFromView, @@ -304,11 +304,11 @@ func (m model) handlePrevKey() (tea.Model, tea.Cmd) { func (m model) handleDownKey() (tea.Model, tea.Cmd) { switch m.currentView { case viewQueue: - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx >= 0 { - m.selectedIdx = nextIdx + prevIdx := m.findPrevVisibleJob(m.selectedIdx) + if prevIdx >= 0 { + m.selectedIdx = prevIdx m.updateSelectedJobID() - if cmd := m.maybePrefetch(nextIdx); cmd != nil { + if cmd := m.maybePrefetch(prevIdx); cmd != nil { return m, cmd } } else if m.canPaginate() { @@ -335,14 +335,14 @@ func (m model) handleDownKey() (tea.Model, tea.Cmd) { return m, nil } -func (m model) handleNextKey() (tea.Model, tea.Cmd) { +func (m model) handlePrevKey() (tea.Model, tea.Cmd) { switch m.currentView { case viewQueue: - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx >= 0 { - m.selectedIdx = nextIdx + prevIdx := m.findPrevVisibleJob(m.selectedIdx) + if prevIdx >= 0 { + m.selectedIdx = prevIdx m.updateSelectedJobID() - if cmd := m.maybePrefetch(nextIdx); cmd != nil { + if cmd := m.maybePrefetch(prevIdx); cmd != nil { return m, cmd } } else if m.canPaginate() { @@ -350,13 +350,13 @@ func (m model) handleNextKey() (tea.Model, tea.Cmd) { return m, m.fetchMoreJobs() } case viewReview: - nextIdx := m.findNextViewableJob() - if nextIdx >= 0 { + prevIdx := m.findPrevViewableJob() + if prevIdx >= 0 { m.closeFixPanel() - m.selectedIdx = nextIdx + m.selectedIdx = prevIdx m.updateSelectedJobID() m.reviewScroll = 0 - job := m.jobs[nextIdx] + job := m.jobs[prevIdx] switch job.Status { case storage.JobStatusDone: return m, m.fetchReview(job.ID) @@ -376,12 +376,12 @@ func (m model) handleNextKey() (tea.Model, tea.Cmd) { m.setFlash("No older review", 2*time.Second, viewReview) } case viewKindPrompt: - nextIdx := m.findNextPromptableJob() - if nextIdx >= 0 { - m.selectedIdx = nextIdx + prevIdx := m.findPrevPromptableJob() + if prevIdx >= 0 { + m.selectedIdx = prevIdx m.updateSelectedJobID() m.promptScroll = 0 - job := m.jobs[nextIdx] + job := m.jobs[prevIdx] if job.Status == storage.JobStatusDone { return m, m.fetchReviewForPrompt(job.ID) } else if job.Status == storage.JobStatusRunning && job.Prompt != "" { @@ -400,7 +400,7 @@ func (m model) handleNextKey() (tea.Model, tea.Cmd) { } case viewLog: if m.logFromView == viewTasks { - idx := m.findNextLoggableFixJob() + idx := m.findPrevLoggableFixJob() if idx >= 0 { m.fixSelectedIdx = idx job := m.fixJobs[idx] @@ -410,11 +410,11 @@ func (m model) handleNextKey() (tea.Model, tea.Cmd) { ) } } else { - nextIdx := m.findNextLoggableJob() - if nextIdx >= 0 { - m.selectedIdx = nextIdx + prevIdx := m.findPrevLoggableJob() + if prevIdx >= 0 { + m.selectedIdx = prevIdx m.updateSelectedJobID() - job := m.jobs[nextIdx] + job := m.jobs[prevIdx] m.logStreaming = false return m.openLogView( job.ID, job.Status, m.logFromView, @@ -435,11 +435,11 @@ func (m model) handlePageUpKey() (tea.Model, tea.Cmd) { switch m.currentView { case viewQueue: for range pageSize { - prevIdx := m.findPrevVisibleJob(m.selectedIdx) - if prevIdx < 0 { + nextIdx := m.findNextVisibleJob(m.selectedIdx) + if nextIdx < 0 { break } - m.selectedIdx = prevIdx + m.selectedIdx = nextIdx } m.updateSelectedJobID() case viewReview: @@ -466,12 +466,12 @@ func (m model) handlePageDownKey() (tea.Model, tea.Cmd) { case viewQueue: reachedEnd := false for range pageSize { - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx < 0 { + prevIdx := m.findPrevVisibleJob(m.selectedIdx) + if prevIdx < 0 { reachedEnd = true break } - m.selectedIdx = nextIdx + m.selectedIdx = prevIdx } m.updateSelectedJobID() if reachedEnd && m.canPaginate() { diff --git a/cmd/roborev/tui/handlers_msg.go b/cmd/roborev/tui/handlers_msg.go index b92125e3..ece86056 100644 --- a/cmd/roborev/tui/handlers_msg.go +++ b/cmd/roborev/tui/handlers_msg.go @@ -163,7 +163,7 @@ func (m model) handleJobsMsg(msg jobsMsg) (tea.Model, tea.Cmd) { m.paginateNav = 0 switch nav { case viewReview: - nextIdx := m.findNextViewableJob() + nextIdx := m.findPrevViewableJob() if nextIdx >= 0 { m.selectedIdx = nextIdx m.updateSelectedJobID() @@ -182,7 +182,7 @@ func (m model) handleJobsMsg(msg jobsMsg) (tea.Model, tea.Cmd) { } } case viewKindPrompt: - nextIdx := m.findNextPromptableJob() + nextIdx := m.findPrevPromptableJob() if nextIdx >= 0 { m.selectedIdx = nextIdx m.updateSelectedJobID() @@ -199,7 +199,7 @@ func (m model) handleJobsMsg(msg jobsMsg) (tea.Model, tea.Cmd) { } } case viewLog: - nextIdx := m.findNextLoggableJob() + nextIdx := m.findPrevLoggableJob() if nextIdx >= 0 { m.selectedIdx = nextIdx m.updateSelectedJobID() diff --git a/cmd/roborev/tui/handlers_review.go b/cmd/roborev/tui/handlers_review.go index 05c8f68d..e7d36ff2 100644 --- a/cmd/roborev/tui/handlers_review.go +++ b/cmd/roborev/tui/handlers_review.go @@ -72,15 +72,15 @@ func (m model) handleCloseKey() (tea.Model, tea.Cmd) { m.pendingClosed[job.ID] = pendingState{newState: newState, seq: seq} m.applyStatsDelta(newState) if m.hideClosed && newState { - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx < 0 { - nextIdx = m.findPrevVisibleJob(m.selectedIdx) + idx := m.findPrevVisibleJob(m.selectedIdx) + if idx < 0 { + idx = m.findNextVisibleJob(m.selectedIdx) } - if nextIdx < 0 { - nextIdx = m.findFirstVisibleJob() + if idx < 0 { + idx = m.findFirstVisibleJob() } - if nextIdx >= 0 { - m.selectedIdx = nextIdx + if idx >= 0 { + m.selectedIdx = idx m.updateSelectedJobID() } } @@ -103,15 +103,15 @@ func (m model) handleCancelKey() (tea.Model, tea.Cmd) { job.FinishedAt = &now // Canceled jobs are hidden when hideClosed is active if m.hideClosed { - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx < 0 { - nextIdx = m.findPrevVisibleJob(m.selectedIdx) + idx := m.findPrevVisibleJob(m.selectedIdx) + if idx < 0 { + idx = m.findNextVisibleJob(m.selectedIdx) } - if nextIdx < 0 { - nextIdx = m.findFirstVisibleJob() + if idx < 0 { + idx = m.findFirstVisibleJob() } - if nextIdx >= 0 { - m.selectedIdx = nextIdx + if idx >= 0 { + m.selectedIdx = idx m.updateSelectedJobID() } } diff --git a/cmd/roborev/tui/nav.go b/cmd/roborev/tui/nav.go index 33891971..019a52ef 100644 --- a/cmd/roborev/tui/nav.go +++ b/cmd/roborev/tui/nav.go @@ -12,9 +12,9 @@ func (m *model) updateSelectedJobID() { } } -// findNextViewableJob finds the next job that can be viewed (done or failed). +// findPrevViewableJob finds the previous (older, lower ID) viewable job. // Respects active filters. Returns the index or -1 if none found. -func (m *model) findNextViewableJob() int { +func (m *model) findPrevViewableJob() int { for i := m.selectedIdx + 1; i < len(m.jobs); i++ { job := m.jobs[i] if (job.Status == storage.JobStatusDone || job.Status == storage.JobStatusFailed) && @@ -25,9 +25,9 @@ func (m *model) findNextViewableJob() int { return -1 } -// findPrevViewableJob finds the previous job that can be viewed (done or failed). +// findNextViewableJob finds the next (newer, higher ID) viewable job. // Respects active filters. Returns the index or -1 if none found. -func (m *model) findPrevViewableJob() int { +func (m *model) findNextViewableJob() int { for i := m.selectedIdx - 1; i >= 0; i-- { job := m.jobs[i] if (job.Status == storage.JobStatusDone || job.Status == storage.JobStatusFailed) && @@ -38,9 +38,9 @@ func (m *model) findPrevViewableJob() int { return -1 } -// findNextPromptableJob finds the next job that has a viewable prompt (done or running with prompt). +// findPrevPromptableJob finds the previous (older) job with a viewable prompt. // Respects active filters. Returns the index or -1 if none found. -func (m *model) findNextPromptableJob() int { +func (m *model) findPrevPromptableJob() int { for i := m.selectedIdx + 1; i < len(m.jobs); i++ { job := m.jobs[i] if m.isJobVisible(job) && @@ -51,9 +51,9 @@ func (m *model) findNextPromptableJob() int { return -1 } -// findPrevPromptableJob finds the previous job that has a viewable prompt (done or running with prompt). +// findNextPromptableJob finds the next (newer) job with a viewable prompt. // Respects active filters. Returns the index or -1 if none found. -func (m *model) findPrevPromptableJob() int { +func (m *model) findNextPromptableJob() int { for i := m.selectedIdx - 1; i >= 0; i-- { job := m.jobs[i] if m.isJobVisible(job) && @@ -64,9 +64,9 @@ func (m *model) findPrevPromptableJob() int { return -1 } -// findNextLoggableJob finds the next job that has a log -// (running, done, or failed). Respects active filters. -func (m *model) findNextLoggableJob() int { +// findPrevLoggableJob finds the previous (older) job with a log. +// Respects active filters. +func (m *model) findPrevLoggableJob() int { for i := m.selectedIdx + 1; i < len(m.jobs); i++ { job := m.jobs[i] if job.Status != storage.JobStatusQueued && @@ -77,9 +77,9 @@ func (m *model) findNextLoggableJob() int { return -1 } -// findPrevLoggableJob finds the previous job that has a log -// (running, done, or failed). Respects active filters. -func (m *model) findPrevLoggableJob() int { +// findNextLoggableJob finds the next (newer) job with a log. +// Respects active filters. +func (m *model) findNextLoggableJob() int { for i := m.selectedIdx - 1; i >= 0; i-- { job := m.jobs[i] if job.Status != storage.JobStatusQueued && @@ -90,8 +90,8 @@ func (m *model) findPrevLoggableJob() int { return -1 } -// findNextLoggableFixJob finds the next fix job that has a log. -func (m *model) findNextLoggableFixJob() int { +// findPrevLoggableFixJob finds the previous (older) fix job with a log. +func (m *model) findPrevLoggableFixJob() int { for i := m.fixSelectedIdx + 1; i < len(m.fixJobs); i++ { if m.fixJobs[i].Status != storage.JobStatusQueued { return i @@ -100,9 +100,8 @@ func (m *model) findNextLoggableFixJob() int { return -1 } -// findPrevLoggableFixJob finds the previous fix job that has a -// log. -func (m *model) findPrevLoggableFixJob() int { +// findNextLoggableFixJob finds the next (newer) fix job with a log. +func (m *model) findNextLoggableFixJob() int { for i := m.fixSelectedIdx - 1; i >= 0; i-- { if m.fixJobs[i].Status != storage.JobStatusQueued { return i @@ -161,22 +160,23 @@ func (m *model) logHelpRows() [][]helpItem { // Call this when returning to queue view from review view. func (m *model) normalizeSelectionIfHidden() { if m.selectedIdx >= 0 && m.selectedIdx < len(m.jobs) && !m.isJobVisible(m.jobs[m.selectedIdx]) { - nextIdx := m.findNextVisibleJob(m.selectedIdx) - if nextIdx < 0 { - nextIdx = m.findPrevVisibleJob(m.selectedIdx) + idx := m.findPrevVisibleJob(m.selectedIdx) + if idx < 0 { + idx = m.findNextVisibleJob(m.selectedIdx) } - if nextIdx < 0 { - nextIdx = m.findFirstVisibleJob() + if idx < 0 { + idx = m.findFirstVisibleJob() } - if nextIdx >= 0 { - m.selectedIdx = nextIdx + if idx >= 0 { + m.selectedIdx = idx m.updateSelectedJobID() } } } -// findNextVisibleJob returns the first visible job index after currentIdx. -func (m model) findNextVisibleJob(currentIdx int) int { +// findPrevVisibleJob returns the first visible job at a higher index +// (older, lower ID) than currentIdx. +func (m model) findPrevVisibleJob(currentIdx int) int { for i := currentIdx + 1; i < len(m.jobs); i++ { if m.isJobVisible(m.jobs[i]) { return i @@ -185,8 +185,9 @@ func (m model) findNextVisibleJob(currentIdx int) int { return -1 } -// findPrevVisibleJob returns the first visible job index before currentIdx. -func (m model) findPrevVisibleJob(currentIdx int) int { +// findNextVisibleJob returns the first visible job at a lower index +// (newer, higher ID) than currentIdx. +func (m model) findNextVisibleJob(currentIdx int) int { for i := currentIdx - 1; i >= 0; i-- { if m.isJobVisible(m.jobs[i]) { return i diff --git a/cmd/roborev/tui/queue_test.go b/cmd/roborev/tui/queue_test.go index 8b0ed73e..ef0481d6 100644 --- a/cmd/roborev/tui/queue_test.go +++ b/cmd/roborev/tui/queue_test.go @@ -96,20 +96,20 @@ func TestTUIQueueNavigation(t *testing.T) { wantJobID: 1, }, { - name: "left arrow moves up", + name: "left arrow moves down", jobs: threeJobs, startIdx: 1, key: tea.KeyLeft, - wantIdx: 0, - wantJobID: 1, + wantIdx: 2, + wantJobID: 3, }, { - name: "right arrow moves down", + name: "right arrow moves up", jobs: threeJobs, startIdx: 1, key: tea.KeyRight, - wantIdx: 2, - wantJobID: 3, + wantIdx: 0, + wantJobID: 1, }, { name: "g jumps to top (unfiltered)", @@ -993,6 +993,59 @@ func TestTUIPageDownBlockedWhileLoadingJobs(t *testing.T) { } } +func TestTUIPageUpDownMovesSelection(t *testing.T) { + // Verify pgup moves toward newer (lower index) and pgdown moves + // toward older (higher index), including with hidden jobs. + m := newModel("http://localhost", withExternalIODisabled()) + m.currentView = viewQueue + m.hideClosed = true + m.height = 15 // pageSize = max(1, 15-10) = 5 + + // 10 visible jobs plus one hidden (canceled + hideClosed) in the + // middle. + m.jobs = []storage.ReviewJob{ + makeJob(1), // idx 0 (newest) + makeJob(2), // idx 1 + makeJob(3), // idx 2 + makeJob(4), // idx 3 + makeJob(5), // idx 4 + makeJob(6, withStatus(storage.JobStatusCanceled)), // idx 5 hidden + makeJob(7), // idx 6 + makeJob(8), // idx 7 + makeJob(9), // idx 8 + makeJob(10), // idx 9 + makeJob(11), // idx 10 (oldest) + } + m.selectedIdx = 0 + m.selectedJobID = 1 + + // pgdown should move 5 visible steps toward older (higher index), + // skipping the hidden job at index 5. + m2, _ := pressSpecial(m, tea.KeyPgDown) + if m2.selectedIdx != 6 { + t.Errorf( + "pgdown: expected selectedIdx=6 (skipped hidden idx 5), got %d", + m2.selectedIdx, + ) + } + if m2.selectedJobID != 7 { + t.Errorf("pgdown: expected selectedJobID=7, got %d", m2.selectedJobID) + } + + // pgup from idx 6 should move 5 visible steps toward newer (lower + // index), again skipping the hidden job. + m3, _ := pressSpecial(m2, tea.KeyPgUp) + if m3.selectedIdx != 0 { + t.Errorf( + "pgup: expected selectedIdx=0 (back to newest), got %d", + m3.selectedIdx, + ) + } + if m3.selectedJobID != 1 { + t.Errorf("pgup: expected selectedJobID=1, got %d", m3.selectedJobID) + } +} + func TestTUIResizeBehavior(t *testing.T) { tests := []struct { name string @@ -1636,16 +1689,16 @@ func TestTUIQueueNavigationSequences(t *testing.T) { t.Errorf("after 'g', expected selectedIdx 0, got %d", m.selectedIdx) } - // Sequence: Right (down/next), Left (up/prev) + // Sequence: Left (down/prev), Right (up/next) // We are at index 0 - m, _ = pressSpecial(m, tea.KeyRight) + m, _ = pressSpecial(m, tea.KeyLeft) if m.selectedIdx != 1 { - t.Errorf("after KeyRight, expected selectedIdx 1, got %d", m.selectedIdx) + t.Errorf("after KeyLeft, expected selectedIdx 1, got %d", m.selectedIdx) } - m, _ = pressSpecial(m, tea.KeyLeft) + m, _ = pressSpecial(m, tea.KeyRight) if m.selectedIdx != 0 { - t.Errorf("after KeyLeft, expected selectedIdx 0, got %d", m.selectedIdx) + t.Errorf("after KeyRight, expected selectedIdx 0, got %d", m.selectedIdx) } } diff --git a/cmd/roborev/tui/review_log_test.go b/cmd/roborev/tui/review_log_test.go index 2c924bff..0fb2e171 100644 --- a/cmd/roborev/tui/review_log_test.go +++ b/cmd/roborev/tui/review_log_test.go @@ -341,10 +341,10 @@ func TestTUILogNavFromTasks(t *testing.T) { } m.selectedIdx = 0 - // Right arrow -> next fix job (ID 30) - m2, cmd := pressSpecial(m, tea.KeyRight) + // Left arrow -> prev (older) fix job (ID 30, index 2) + m2, cmd := pressSpecial(m, tea.KeyLeft) if cmd == nil { - t.Fatal("expected command from right arrow nav") + t.Fatal("expected command from left arrow nav") } if m2.fixSelectedIdx != 2 { t.Errorf( @@ -360,10 +360,10 @@ func TestTUILogNavFromTasks(t *testing.T) { ) } - // Left arrow from index 1 -> prev fix job (ID 10) - m3, cmd := pressSpecial(m, tea.KeyLeft) + // Right arrow from index 1 -> next (newer) fix job (ID 10, index 0) + m3, cmd := pressSpecial(m, tea.KeyRight) if cmd == nil { - t.Fatal("expected command from left arrow nav") + t.Fatal("expected command from right arrow nav") } if m3.fixSelectedIdx != 0 { t.Errorf( diff --git a/cmd/roborev/tui/review_navigation_test.go b/cmd/roborev/tui/review_navigation_test.go index 20fbf0a8..9c20a892 100644 --- a/cmd/roborev/tui/review_navigation_test.go +++ b/cmd/roborev/tui/review_navigation_test.go @@ -61,7 +61,7 @@ func TestTUIReviewNavigation(t *testing.T) { wantCmd: false, }, { - name: "Left Arrow acts like K (Prev)", + name: "Left Arrow acts like J (Prev)", initialJobs: []storage.ReviewJob{ makeJob(1), makeJob(2), @@ -70,12 +70,12 @@ func TestTUIReviewNavigation(t *testing.T) { initialIdx: 1, initialID: 2, key: tea.KeyLeft, - wantIdx: 0, - wantJobID: 1, + wantIdx: 2, + wantJobID: 3, wantCmd: true, }, { - name: "Right Arrow acts like J (Next)", + name: "Right Arrow acts like K (Next)", initialJobs: []storage.ReviewJob{ makeJob(1), makeJob(2), @@ -84,8 +84,8 @@ func TestTUIReviewNavigation(t *testing.T) { initialIdx: 1, initialID: 2, key: tea.KeyRight, - wantIdx: 2, - wantJobID: 3, + wantIdx: 0, + wantJobID: 1, wantCmd: true, }, {