diff --git a/cli/cmd/watch.go b/cli/cmd/watch.go index 51acea3d..ef683645 100644 --- a/cli/cmd/watch.go +++ b/cli/cmd/watch.go @@ -75,6 +75,9 @@ type pollDoneMsg struct { const maxStaleRetries = 5 const maxConnRetries = 10 +// sparklinePoints is how many polls the throughput sparkline shows. +const sparklinePoints = 40 + type pollModel struct { ctx context.Context id string @@ -188,6 +191,11 @@ func (m pollModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } m.recordsSent = totalSent m.throughputHist = append(m.throughputHist, maxThroughput) + // The whole run's history grew without bound: an hour in, the + // sparkline was 1,823 columns and the live number was cut off. + if len(m.throughputHist) > sparklinePoints { + m.throughputHist = m.throughputHist[len(m.throughputHist)-sparklinePoints:] + } if test.Spec != nil && test.Spec.Records > 0 { m.totalRecords = float64(test.Spec.Records) diff --git a/cli/cmd/watch_test.go b/cli/cmd/watch_test.go index 8a9ee4ca..147a3d01 100644 --- a/cli/cmd/watch_test.go +++ b/cli/cmd/watch_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/bmscomp/kates/cli/client" + tea "github.com/charmbracelet/bubbletea" ) // stubPoll scripts a sequence of GetTest responses and restores the seams on @@ -41,6 +42,21 @@ func run(status string, sent float64) func() (*client.TestRun, error) { } } +// The throughput sparkline kept every poll of the run: an hour in it was 1,823 +// columns wide, and the renderer cut off the live number after it. +func TestPollModel_SparklineKeepsTheLastPoints(t *testing.T) { + var m tea.Model = pollModel{id: "test-1234"} + for i := range 100 { + m, _ = m.Update(pollResultMsg{test: &client.TestRun{ID: "test-1234", Status: "RUNNING", + Results: []client.PhaseResult{{ThroughputRecordsPerSec: float64(i)}}}}) + } + hist := m.(pollModel).throughputHist + if len(hist) != sparklinePoints || hist[0] != 100-sparklinePoints || hist[len(hist)-1] != 99 { + t.Errorf("history = %d points from %v to %v, want the last %d, 60 to 99", + len(hist), hist[0], hist[len(hist)-1], sparklinePoints) + } +} + // The flagship contract: a FAILED test is reported as FAILED, never swallowed. // The previous pollUntilDone returned nothing at all — the TUI printed "Test // failed" and callers exited 0, keeping CI green on failed load tests.