package api import ( "encoding/json" "net/http" "net/http/httptest" "strconv" "testing" "github.com/thepeterstone/claudomator/internal/event" "github.com/thepeterstone/claudomator/internal/task" ) func TestListTaskEvents_ReturnsStreamInSeqOrder(t *testing.T) { srv, store := testServer(t) createTaskWithState(t, store, "ev-task", task.StateReady) req := httptest.NewRequest("GET", "/api/tasks/ev-task/events", nil) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("status: want 200, got %d; body %s", w.Code, w.Body.String()) } var events []*event.Event if err := json.Unmarshal(w.Body.Bytes(), &events); err != nil { t.Fatalf("unmarshal: %v", err) } if len(events) == 0 { t.Fatal("expected state-change events from the walk to READY") } for i := 1; i < len(events); i++ { if events[i].Seq <= events[i-1].Seq { t.Errorf("events not in ascending seq order: %d then %d", events[i-1].Seq, events[i].Seq) } } } func TestListTaskEvents_SinceSeqFilters(t *testing.T) { srv, store := testServer(t) createTaskWithState(t, store, "ev-since", task.StateReady) all := getEvents(t, srv, "ev-since", "") if len(all) < 2 { t.Skipf("need at least 2 events to test since_seq, got %d", len(all)) } firstSeq := all[0].Seq rest := getEvents(t, srv, "ev-since", "?since_seq="+itoa(firstSeq)) for _, e := range rest { if e.Seq <= firstSeq { t.Errorf("since_seq=%d returned event with seq %d", firstSeq, e.Seq) } } } func TestListTaskEvents_NotFound(t *testing.T) { srv, _ := testServer(t) req := httptest.NewRequest("GET", "/api/tasks/missing/events", nil) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, req) if w.Code != http.StatusNotFound { t.Errorf("want 404, got %d", w.Code) } } func TestListTaskEvents_InvalidSinceSeq(t *testing.T) { srv, store := testServer(t) createTaskWithState(t, store, "ev-bad", task.StateReady) req := httptest.NewRequest("GET", "/api/tasks/ev-bad/events?since_seq=abc", nil) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Errorf("want 400, got %d", w.Code) } } func getEvents(t *testing.T, srv *Server, taskID, query string) []*event.Event { t.Helper() req := httptest.NewRequest("GET", "/api/tasks/"+taskID+"/events"+query, nil) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("getEvents %s%s: status %d", taskID, query, w.Code) } var events []*event.Event if err := json.Unmarshal(w.Body.Bytes(), &events); err != nil { t.Fatalf("getEvents unmarshal: %v", err) } return events } func itoa(n int64) string { return strconv.FormatInt(n, 10) }