feat: the Wanted view becomes Collection, shaped like Lidarr: an artist catalogue first, the state sections down a left rail (M502 #5577)
release / govulncheck (push) Successful in 21s
release / web (push) Successful in 1m39s
release / go (push) Successful in 1m54s
release / integration (push) Successful in 5m33s
release / android (push) Successful in 5m40s
release / Build signed APK (releases and dev) (push) Successful in 5m56s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 25s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 21s
release / web (push) Successful in 1m39s
release / go (push) Successful in 1m54s
release / integration (push) Successful in 5m33s
release / android (push) Successful in 5m40s
release / Build signed APK (releases and dev) (push) Successful in 5m56s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 25s
release / Verify release artifacts (tag releases only) (push) Skipped
The section opens on a catalogue of every artist on the list, A–Z with a letter rail, each card showing how many of their albums are held. An artist opens on their page: every album of theirs, held or not, with its status, search, releases and tracks. Wanted, Missing files, Activity, Following and Blocked sit down a left rail as the sections that show state; Held is gone, the catalogue shows it. The section moves from /wanted to /collection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ func doWantedReq(t *testing.T, h *handlers, path string, user dbq.User) *httptes
|
||||
r.Route("/api/admin", func(admin chi.Router) {
|
||||
admin.Use(auth.RequireAdmin())
|
||||
admin.Get("/wanted", h.handleListWants)
|
||||
admin.Get("/wanted/artists", h.handleListWantArtists)
|
||||
admin.Get("/wanted/{id}/tracks", h.handleWantTracks)
|
||||
})
|
||||
w := httptest.NewRecorder()
|
||||
@@ -98,6 +99,75 @@ func TestListWants_ArtistsAToZThenTheirAlbumsByDate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// The Collection's catalogue (#5572): every artist on the list A–Z, each
|
||||
// with how many of their albums are held; an artist's page lists every album
|
||||
// of theirs, held or not, under that artist.
|
||||
func TestListWantArtists_CatalogueAndAnArtistsPage(t *testing.T) {
|
||||
h, _ := testHandlersWithClientFn(t)
|
||||
admin := seedUser(t, h.pool, "admin", "pw", true)
|
||||
ctx := context.Background()
|
||||
q := dbq.New(h.pool)
|
||||
beatles := "a0000000-0000-4000-8000-000000000002"
|
||||
camel := "a0000000-0000-4000-8000-000000000001"
|
||||
if _, err := q.UpsertArtist(ctx, dbq.UpsertArtistParams{Name: "The Beatles", SortName: "Beatles, The", Mbid: &beatles}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
seedWant(t, h, "g0000000-0000-4000-8000-000000000002", beatles, "The Beatles", "Abbey Road", "1969")
|
||||
held := seedWant(t, h, "g0000000-0000-4000-8000-000000000003", beatles, "The Beatles", "Please Please Me", "1963")
|
||||
if _, err := h.pool.Exec(ctx, `UPDATE wants SET fulfilled_at = now() WHERE id = $1`, held.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
seedWant(t, h, "g0000000-0000-4000-8000-000000000004", camel, "Camel", "Moonmadness", "1976")
|
||||
if _, err := h.pool.Exec(ctx, `INSERT INTO follows (artist_mbid, artist_name, profile_id)
|
||||
SELECT $1, 'Camel', id FROM release_type_profiles WHERE is_default`, camel); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
w := doWantedReq(t, h, "/api/admin/wanted/artists", admin)
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d; body = %s", w.Code, w.Body.String())
|
||||
}
|
||||
var page wantArtistsPage
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &page); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(page.Items) != 2 || page.Total != 2 || page.Counts.Artists != 2 {
|
||||
t.Fatalf("catalogue = %+v, total %d, artists %d", page.Items, page.Total, page.Counts.Artists)
|
||||
}
|
||||
b, c := page.Items[0], page.Items[1]
|
||||
if b.ArtistName != "The Beatles" || b.SortName != "Beatles, The" || b.Albums != 2 || b.Held != 1 || b.Wanted != 1 ||
|
||||
b.ArtistID == "" || b.Following || b.ImageURL == "" {
|
||||
t.Errorf("Beatles = %+v", b)
|
||||
}
|
||||
if c.ArtistName != "Camel" || c.Albums != 1 || c.Held != 0 || !c.Following || c.ArtistID != "" {
|
||||
t.Errorf("Camel = %+v", c)
|
||||
}
|
||||
|
||||
// q finds an artist by an album's title.
|
||||
w = doWantedReq(t, h, "/api/admin/wanted/artists?q=moon", admin)
|
||||
page = wantArtistsPage{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &page); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(page.Items) != 1 || page.Items[0].ArtistName != "Camel" {
|
||||
t.Errorf("q=moon: %+v", page.Items)
|
||||
}
|
||||
|
||||
// The Beatles' page: both albums, held or not, headed by the artist.
|
||||
w = doWantedReq(t, h, "/api/admin/wanted?state=all&artist="+beatles, admin)
|
||||
var albums wantsPage
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &albums); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(albums.Items) != 2 || albums.Items[0].Title != "Please Please Me" || albums.Items[0].HeldAt == nil ||
|
||||
albums.Artist == nil || albums.Artist.Held != 1 {
|
||||
t.Errorf("artist page = %+v, head %+v", albums.Items, albums.Artist)
|
||||
}
|
||||
if w := doWantedReq(t, h, "/api/admin/wanted?state=all&artist=nobody", admin); w.Code != http.StatusNotFound {
|
||||
t.Errorf("an artist with nothing on the list: status %d, want 404", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// fakeEditions is a MusicBrainz holding one group with two editions, the
|
||||
// shorter official one the standard, or 503 when down is set.
|
||||
func fakeEditions(t *testing.T, group string, down bool) *httptest.Server {
|
||||
|
||||
Reference in New Issue
Block a user