package api import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/go-chi/chi/v5" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) func newHomeRouter(h *handlers) chi.Router { r := chi.NewRouter() r.Get("/api/home", h.handleGetHome) return r } func doGetHome(h *handlers, user dbq.User) *httptest.ResponseRecorder { req := httptest.NewRequest(http.MethodGet, "/api/home", nil) req = withUser(req, user) w := httptest.NewRecorder() newHomeRouter(h).ServeHTTP(w, req) return w } func TestHome_EmptyForNewUser(t *testing.T) { h, pool := testHandlers(t) user := seedUser(t, pool, "alice", "pw", false) w := doGetHome(h, user) if w.Code != http.StatusOK { t.Fatalf("status = %d, want 200; body = %s", w.Code, w.Body.String()) } var got HomePayload if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil { t.Fatalf("decode: %v", err) } // All slices must be non-nil so the SPA branches consistently on // length rather than dealing with null. if got.RecentlyAddedAlbums == nil || got.RediscoverAlbums == nil || got.RediscoverArtists == nil || got.MostPlayedTracks == nil || got.LastPlayedArtists == nil { t.Errorf("payload has nil slice: %+v", got) } if len(got.RecentlyAddedAlbums) != 0 { t.Errorf("RecentlyAddedAlbums len = %d, want 0", len(got.RecentlyAddedAlbums)) } } func TestHome_RecentlyAddedSurfacesAlbums(t *testing.T) { h, pool := testHandlers(t) user := seedUser(t, pool, "alice", "pw", false) q := dbq.New(pool) artist, _ := q.UpsertArtist(context.Background(), dbq.UpsertArtistParams{ Name: "ArtistOne", SortName: "ArtistOne", }) _, _ = q.UpsertAlbum(context.Background(), dbq.UpsertAlbumParams{ Title: "Newest", SortTitle: "Newest", ArtistID: artist.ID, }) w := doGetHome(h, user) if w.Code != http.StatusOK { t.Fatalf("status = %d, body = %s", w.Code, w.Body.String()) } var got HomePayload _ = json.Unmarshal(w.Body.Bytes(), &got) if len(got.RecentlyAddedAlbums) != 1 { t.Fatalf("len = %d, want 1", len(got.RecentlyAddedAlbums)) } if got.RecentlyAddedAlbums[0].Title != "Newest" { t.Errorf("title = %q, want Newest", got.RecentlyAddedAlbums[0].Title) } if got.RecentlyAddedAlbums[0].ArtistName != "ArtistOne" { t.Errorf("artist_name = %q, want ArtistOne", got.RecentlyAddedAlbums[0].ArtistName) } } func newHomeIndexRouter(h *handlers) chi.Router { r := chi.NewRouter() r.Get("/api/home/index", h.handleGetHomeIndex) return r } func doGetHomeIndex(h *handlers, user dbq.User) *httptest.ResponseRecorder { req := httptest.NewRequest(http.MethodGet, "/api/home/index", nil) req = withUser(req, user) w := httptest.NewRecorder() newHomeIndexRouter(h).ServeHTTP(w, req) return w } func TestHomeIndex_EmptyForNewUser(t *testing.T) { h, pool := testHandlers(t) user := seedUser(t, pool, "alice", "pw", false) w := doGetHomeIndex(h, user) if w.Code != http.StatusOK { t.Fatalf("status = %d, want 200; body = %s", w.Code, w.Body.String()) } var got HomeIndexPayload if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil { t.Fatalf("decode: %v", err) } // Same non-nil slice contract as /api/home so client parsers can // trust `length == 0` instead of branching on null. if got.RecentlyAddedAlbums == nil || got.RediscoverAlbums == nil || got.RediscoverArtists == nil || got.MostPlayedTracks == nil || got.LastPlayedArtists == nil { t.Errorf("payload has nil slice: %+v", got) } if len(got.RecentlyAddedAlbums) != 0 { t.Errorf("RecentlyAddedAlbums len = %d, want 0", len(got.RecentlyAddedAlbums)) } } func TestHomeIndex_RecentlyAddedReturnsIDs(t *testing.T) { h, pool := testHandlers(t) user := seedUser(t, pool, "alice", "pw", false) q := dbq.New(pool) artist, _ := q.UpsertArtist(context.Background(), dbq.UpsertArtistParams{ Name: "ArtistOne", SortName: "ArtistOne", }) album, _ := q.UpsertAlbum(context.Background(), dbq.UpsertAlbumParams{ Title: "Newest", SortTitle: "Newest", ArtistID: artist.ID, }) w := doGetHomeIndex(h, user) if w.Code != http.StatusOK { t.Fatalf("status = %d, body = %s", w.Code, w.Body.String()) } var got HomeIndexPayload _ = json.Unmarshal(w.Body.Bytes(), &got) if len(got.RecentlyAddedAlbums) != 1 { t.Fatalf("len = %d, want 1", len(got.RecentlyAddedAlbums)) } want := uuidToString(album.ID) if got.RecentlyAddedAlbums[0] != want { t.Errorf("id = %q, want %q", got.RecentlyAddedAlbums[0], want) } }