package api import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/go-chi/chi/v5" "git.fabledsword.com/bvandeusen/minstrel/internal/auth" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) func getAdminSummary(t *testing.T, h *handlers, user dbq.User) (int, adminSummaryView) { t.Helper() r := chi.NewRouter() r.Route("/api/admin", func(admin chi.Router) { admin.Use(auth.RequireAdmin()) admin.Get("/summary", h.handleGetAdminSummary) }) w := httptest.NewRecorder() r.ServeHTTP(w, withUser(httptest.NewRequest(http.MethodGet, "/api/admin/summary", nil), user)) var out adminSummaryView if w.Code == http.StatusOK { if err := json.Unmarshal(w.Body.Bytes(), &out); err != nil { t.Fatal(err) } } return w.Code, out } // The summary counts each queue an admin acts on and says since when the // oldest item has waited; an empty queue has no since (#5605). func TestAdminSummary_CountsTheQueuesAndSinceWhen(t *testing.T) { h, _ := testHandlers(t) admin := seedUser(t, h.pool, "admin", "pw", true) listener := seedUser(t, h.pool, "listener", "pw", false) ctx := context.Background() code, empty := getAdminSummary(t, h, admin) if code != http.StatusOK { t.Fatalf("status = %d", code) } if empty.Requests.Count != 0 || empty.Requests.Since != nil || empty.Missing.Count != 0 { t.Errorf("empty summary = %+v", empty) } if _, err := dbq.New(h.pool).CreateRequest(ctx, dbq.CreateRequestParams{ UserID: listener.ID, Kind: dbq.RequestKindArtist, ArtistMbid: "a0000000-0000-4000-8000-000000000001", ArtistName: "Annadale", }); err != nil { t.Fatal(err) } _, got := getAdminSummary(t, h, admin) if got.Requests.Count != 1 || got.Requests.Since == nil { t.Errorf("requests = %+v, want 1 with a since", got.Requests) } if code, _ := getAdminSummary(t, h, listener); code != http.StatusForbidden { t.Errorf("a listener got %d, want 403", code) } } // Duplicates count what needs review: a cross-release group is kept and // linked by the resolver and waits on nobody (operator, 2026-10-19: the // headline said 3,479 when 536 needed review). func TestAdminSummary_DuplicatesCountOnlyWhatNeedsReview(t *testing.T) { h, _ := testHandlers(t) truncateLibrary(t, h.pool) admin := seedUser(t, h.pool, "dupsum-admin", "pw", true) ctx := context.Background() a := seedQuarantineTrack(t, h, "dupsum-a") b := seedQuarantineTrack(t, h, "dupsum-b") for _, g := range []struct{ key, class string }{{"dupsum-review", "review"}, {"dupsum-cross", "cross_release"}} { var id [16]byte if err := h.pool.QueryRow(ctx, `INSERT INTO duplicate_groups (member_key, tier, class) VALUES ($1, 'acoustic', $2) RETURNING id`, g.key, g.class).Scan(&id); err != nil { t.Fatal(err) } if _, err := h.pool.Exec(ctx, `INSERT INTO duplicate_group_members (group_id, track_id) VALUES ($1, $2), ($1, $3)`, id, a.ID, b.ID); err != nil { t.Fatal(err) } } _, got := getAdminSummary(t, h, admin) if got.Duplicates.Count != 1 { t.Errorf("duplicates = %d, want 1: the cross-release group needs nobody", got.Duplicates.Count) } }