feat(api): add GET /api/artists/{id}/tracks handler
Wires ListArtistTracksForUser (Task 3 SQL) to a new handler that returns all quarantine-filtered tracks for an artist as a flat TrackRef list. 404 when the artist doesn't exist. Route registered in Mount(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/config"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/playevents"
|
||||
)
|
||||
|
||||
@@ -465,3 +467,103 @@ func TestRoutesRegisteredInMount(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetArtistTracks_HappyPath(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: "ArtistA", SortName: "ArtistA",
|
||||
})
|
||||
album, _ := q.UpsertAlbum(context.Background(), dbq.UpsertAlbumParams{
|
||||
Title: "AlbumA", SortTitle: "AlbumA", ArtistID: artist.ID,
|
||||
})
|
||||
_, _ = q.UpsertTrack(context.Background(), dbq.UpsertTrackParams{
|
||||
Title: "T1", AlbumID: album.ID, ArtistID: artist.ID,
|
||||
DurationMs: 1000, FilePath: "/tmp/m6a-T1.mp3",
|
||||
FileSize: 1, FileFormat: "mp3",
|
||||
})
|
||||
_, _ = q.UpsertTrack(context.Background(), dbq.UpsertTrackParams{
|
||||
Title: "T2", AlbumID: album.ID, ArtistID: artist.ID,
|
||||
DurationMs: 1000, FilePath: "/tmp/m6a-T2.mp3",
|
||||
FileSize: 1, FileFormat: "mp3",
|
||||
})
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Get("/api/artists/{id}/tracks", h.handleGetArtistTracks)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/artists/"+uuidToString(artist.ID)+"/tracks", nil)
|
||||
req = withUser(req, user)
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, body = %s", w.Code, w.Body.String())
|
||||
}
|
||||
var got []TrackRef
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("len = %d, want 2", len(got))
|
||||
}
|
||||
if got[0].ArtistName != "ArtistA" || got[0].AlbumTitle != "AlbumA" {
|
||||
t.Errorf("got = %+v", got[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetArtistTracks_HonorsQuarantine(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: "ArtistB", SortName: "ArtistB",
|
||||
})
|
||||
album, _ := q.UpsertAlbum(context.Background(), dbq.UpsertAlbumParams{
|
||||
Title: "AlbumB", SortTitle: "AlbumB", ArtistID: artist.ID,
|
||||
})
|
||||
track, _ := q.UpsertTrack(context.Background(), dbq.UpsertTrackParams{
|
||||
Title: "Q", AlbumID: album.ID, ArtistID: artist.ID,
|
||||
DurationMs: 1000, FilePath: "/tmp/m6a-Q.mp3",
|
||||
FileSize: 1, FileFormat: "mp3",
|
||||
})
|
||||
if _, err := pool.Exec(context.Background(),
|
||||
`INSERT INTO lidarr_quarantine (user_id, track_id, reason) VALUES ($1, $2, 'bad_rip')`,
|
||||
user.ID, track.ID,
|
||||
); err != nil {
|
||||
t.Fatalf("quarantine insert: %v", err)
|
||||
}
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Get("/api/artists/{id}/tracks", h.handleGetArtistTracks)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/artists/"+uuidToString(artist.ID)+"/tracks", nil)
|
||||
req = withUser(req, user)
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d", w.Code)
|
||||
}
|
||||
var got []TrackRef
|
||||
_ = json.Unmarshal(w.Body.Bytes(), &got)
|
||||
if len(got) != 0 {
|
||||
t.Errorf("len = %d, want 0 (quarantined)", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetArtistTracks_NotFound(t *testing.T) {
|
||||
h, pool := testHandlers(t)
|
||||
user := seedUser(t, pool, "alice", "pw", false)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Get("/api/artists/{id}/tracks", h.handleGetArtistTracks)
|
||||
// Random UUID — no such artist exists.
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/artists/00000000-0000-0000-0000-000000000000/tracks", nil)
|
||||
req = withUser(req, user)
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusNotFound {
|
||||
t.Errorf("status = %d, want 404", w.Code)
|
||||
}
|
||||
_ = pool
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user