aboutsummaryrefslogtreecommitdiff
path: root/cmds/serve_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/serve_test.go')
-rw-r--r--cmds/serve_test.go57
1 files changed, 56 insertions, 1 deletions
diff --git a/cmds/serve_test.go b/cmds/serve_test.go
index e8aec19..509de6c 100644
--- a/cmds/serve_test.go
+++ b/cmds/serve_test.go
@@ -384,7 +384,9 @@ func TestServeRoutes(t *testing.T) {
}
cmd := &ServeCommand{Runs: runsPath, RSSBatches: 21}
- handler := cmd.routes([]int{360, 720, 1080}, time.Now().Add(-48*time.Hour))
+ pollCalls := 0
+ pollStub := func() error { pollCalls++; return nil }
+ handler := cmd.routes([]int{360, 720, 1080}, time.Now().Add(-48*time.Hour), pollStub)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/recommendations.xml", nil))
@@ -422,3 +424,56 @@ func TestServeRoutes(t *testing.T) {
t.Errorf("model_age_hours = %v, want positive", status["model_age_hours"])
}
}
+
+func TestManualPollRoute(t *testing.T) {
+ dir := t.TempDir()
+ runsPath := filepath.Join(dir, "runs.jsonl")
+ // Last run hours ago: well outside the manual-poll cooldown.
+ if err := core.AppendRun(runsPath, core.RunRow{
+ RanAt: time.Now().Add(-time.Hour), EntriesSeen: 3,
+ }); err != nil {
+ t.Fatalf("AppendRun: %v", err)
+ }
+
+ pollCalls := 0
+ pollStub := func() error { pollCalls++; return nil }
+ cmd := &ServeCommand{Runs: runsPath}
+ handler := cmd.routes([]int{360, 720, 1080}, time.Now(), pollStub)
+
+ // GET is rejected; only POST triggers.
+ rec := httptest.NewRecorder()
+ handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/poll", nil))
+ if rec.Code != http.StatusMethodNotAllowed {
+ t.Errorf("GET /api/poll = %d, want 405", rec.Code)
+ }
+
+ // POST runs the poll; the stub wrote no row, so no new run is reported.
+ rec = httptest.NewRecorder()
+ handler.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/api/poll", nil))
+ if rec.Code != http.StatusOK {
+ t.Fatalf("POST /api/poll = %d, want 200", rec.Code)
+ }
+ if pollCalls != 1 {
+ t.Errorf("poll called %d times, want 1", pollCalls)
+ }
+ var resp map[string]any
+ if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
+ t.Fatalf("response not JSON: %v", err)
+ }
+ if resp["polled"] != true || resp["new_run"] != false {
+ t.Errorf("response = %v, want polled=true new_run=false", resp)
+ }
+
+ // A fresh run row puts the next POST inside the cooldown window.
+ if err := core.AppendRun(runsPath, core.RunRow{RanAt: time.Now(), EntriesSeen: 5}); err != nil {
+ t.Fatalf("AppendRun: %v", err)
+ }
+ rec = httptest.NewRecorder()
+ handler.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/api/poll", nil))
+ if rec.Code != http.StatusTooManyRequests {
+ t.Errorf("POST inside cooldown = %d, want 429", rec.Code)
+ }
+ if pollCalls != 1 {
+ t.Errorf("poll called %d times, want still 1 (cooldown)", pollCalls)
+ }
+}