Files
minstrel/internal/api/admin_coverage_test.go
T
bvandeusen 97cca4411a chore(server/m7-coverage-gauge): align coverage test with peer style
Code-review polish on admin_coverage_test.go:
- Replace inline artist-seed SQL with the seedArtist helper used
  across the rest of the api test suite (admin_covers_test.go,
  likes_test.go, me_history_test.go, admin_quarantine_test.go).
- Rename the cover_art_source pointer locals from none/sidecar/mbcaa
  to sourceNone/sourceSidecar/sourceMbcaa so they don't read like
  zero-value identifiers.
2026-05-06 10:08:58 -04:00

141 lines
4.5 KiB
Go

package api
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/go-chi/chi/v5"
"git.fabledsword.com/bvandeusen/minstrel/internal/auth"
)
// newAdminCoverageRouter builds a test chi router exposing only the
// coverage endpoint, mirroring the pattern in admin_scan_test.go.
func newAdminCoverageRouter(h *handlers) chi.Router {
r := chi.NewRouter()
r.Route("/api/admin", func(admin chi.Router) {
admin.Use(auth.RequireAdmin())
admin.Get("/library/coverage", h.handleGetLibraryCoverage)
})
return r
}
func TestAdminLibraryCoverage_EmptyLibraryReturnsZeros(t *testing.T) {
if os.Getenv("MINSTREL_TEST_DATABASE_URL") == "" {
t.Skip("MINSTREL_TEST_DATABASE_URL not set")
}
h, pool := testHandlers(t)
admin := seedUser(t, pool, "covgauge1", "pw", true)
req := httptest.NewRequest(http.MethodGet, "/api/admin/library/coverage", nil)
req = withUser(req, admin)
rec := httptest.NewRecorder()
newAdminCoverageRouter(h).ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200; body=%s", rec.Code, rec.Body.String())
}
var resp coverageRollupResp
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("decode: %v", err)
}
if resp.Total != 0 || resp.WithArt != 0 || resp.Pending != 0 || resp.Settled != 0 || resp.PendingNoMbid != 0 {
t.Errorf("expected all zeros on empty library; got %+v", resp)
}
}
func TestAdminLibraryCoverage_MixedRowsReturnCorrectBuckets(t *testing.T) {
if os.Getenv("MINSTREL_TEST_DATABASE_URL") == "" {
t.Skip("MINSTREL_TEST_DATABASE_URL not set")
}
h, pool := testHandlers(t)
admin := seedUser(t, pool, "covgauge2", "pw", true)
// Seed an artist for FK satisfaction.
artist := seedArtist(t, pool, "Coverage Test")
// Seed albums covering each bucket. Use distinct titles to avoid the
// unique (artist_id, title) constraint. Distinct mbids where set so
// the partial unique index on mbid doesn't trip.
type seed struct {
title string
source *string
mbid *string
}
sourceNone := "none"
sourceSidecar := "sidecar"
sourceMbcaa := "mbcaa"
mbid1 := "11111111-1111-1111-1111-111111111111"
mbid2 := "22222222-2222-2222-2222-222222222222"
mbid3 := "33333333-3333-3333-3333-333333333333"
rows := []seed{
{title: "WithArtSidecar", source: &sourceSidecar, mbid: &mbid1}, // with_art
{title: "WithArtMbcaa", source: &sourceMbcaa, mbid: &mbid2}, // with_art
{title: "PendingHasMbid", source: nil, mbid: &mbid3}, // pending (eligible)
{title: "PendingNoMbid", source: nil, mbid: nil}, // pending + pending_no_mbid
{title: "Settled", source: &sourceNone, mbid: nil}, // settled (no mbid is fine here)
}
for _, s := range rows {
if _, err := pool.Exec(context.Background(), `
INSERT INTO albums (artist_id, title, sort_title, cover_art_source, mbid)
VALUES ($1, $2, $3, $4, $5)
`, artist.ID, s.title, s.title, s.source, s.mbid); err != nil {
t.Fatalf("seed album %q: %v", s.title, err)
}
}
req := httptest.NewRequest(http.MethodGet, "/api/admin/library/coverage", nil)
req = withUser(req, admin)
rec := httptest.NewRecorder()
newAdminCoverageRouter(h).ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200; body=%s", rec.Code, rec.Body.String())
}
var resp coverageRollupResp
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("decode: %v", err)
}
if resp.Total != 5 {
t.Errorf("Total = %d, want 5", resp.Total)
}
if resp.WithArt != 2 {
t.Errorf("WithArt = %d, want 2", resp.WithArt)
}
if resp.Pending != 2 {
t.Errorf("Pending = %d, want 2", resp.Pending)
}
if resp.Settled != 1 {
t.Errorf("Settled = %d, want 1", resp.Settled)
}
if resp.PendingNoMbid != 1 {
t.Errorf("PendingNoMbid = %d, want 1", resp.PendingNoMbid)
}
// Invariant: with_art + pending + settled == total.
if resp.WithArt+resp.Pending+resp.Settled != resp.Total {
t.Errorf("invariant violated: %d + %d + %d != %d",
resp.WithArt, resp.Pending, resp.Settled, resp.Total)
}
}
func TestAdminLibraryCoverage_NonAdminReturns403(t *testing.T) {
if os.Getenv("MINSTREL_TEST_DATABASE_URL") == "" {
t.Skip("MINSTREL_TEST_DATABASE_URL not set")
}
h, pool := testHandlers(t)
user := seedUser(t, pool, "covgauge3", "pw", false)
req := httptest.NewRequest(http.MethodGet, "/api/admin/library/coverage", nil)
req = withUser(req, user)
rec := httptest.NewRecorder()
newAdminCoverageRouter(h).ServeHTTP(rec, req)
if rec.Code != http.StatusForbidden {
t.Fatalf("status = %d, want 403; body=%s", rec.Code, rec.Body.String())
}
}