fix(web): artistPlays via user.getTop{Tracks,Albums} (getArtistTracks deprecated)
Last.fm returns error 27 "Deprecated" for user.getArtistTracks, so the per-artist plays modal was 502ing for every artist. Pivot to filtering the user's supported all-time top tracks + top albums (which carry real per-item play counts) to the artist — exact personal counts, cheaper, and the clicked artists are the user's top artists so their items cluster near the front. Adds topTracks(); route + modal return shape unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,15 +18,13 @@ async function seedConfig() {
|
||||
await prisma.config.create({ data: { key: "lastfm.api_key", value: encryptSecret("real-key"), secret: true } });
|
||||
}
|
||||
|
||||
function mockLfmArtistTracks(tracks: unknown[], totalPages = 1) {
|
||||
vi.spyOn(global, "fetch").mockResolvedValue(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
artisttracks: { track: tracks, "@attr": { totalPages: String(totalPages), page: "1" } },
|
||||
}),
|
||||
{ status: 200 },
|
||||
),
|
||||
);
|
||||
function mockTopEndpoints(tracks: unknown[], albums: unknown[]) {
|
||||
vi.spyOn(global, "fetch").mockImplementation((url: any) => {
|
||||
const body = String(url).includes("gettoptracks")
|
||||
? { toptracks: { track: tracks, "@attr": { totalPages: "1", page: "1" } } }
|
||||
: { topalbums: { album: albums, "@attr": { totalPages: "1", page: "1" } } };
|
||||
return Promise.resolve(new Response(JSON.stringify(body), { status: 200 }));
|
||||
});
|
||||
}
|
||||
|
||||
describe("GET /api/lastfm/artist-plays", () => {
|
||||
@@ -43,22 +41,28 @@ describe("GET /api/lastfm/artist-plays", () => {
|
||||
expect(blank.status).toBe(400);
|
||||
});
|
||||
|
||||
it("returns the tally on the happy path", async () => {
|
||||
it("returns the artist's top tracks + albums (filtered to the artist, real counts)", async () => {
|
||||
await seedConfig();
|
||||
mockLfmArtistTracks([
|
||||
{ name: "Billie Jean", album: { "#text": "Thriller" } },
|
||||
{ name: "Billie Jean", album: { "#text": "Thriller" } },
|
||||
{ name: "Beat It", album: { "#text": "Thriller" } },
|
||||
]);
|
||||
mockTopEndpoints(
|
||||
[
|
||||
{ name: "Billie Jean", playcount: "50", artist: { name: "Michael Jackson" } },
|
||||
{ name: "Wonderwall", playcount: "99", artist: { name: "Oasis" } }, // different artist — excluded
|
||||
{ name: "Beat It", playcount: "30", artist: { name: "Michael Jackson" } },
|
||||
],
|
||||
[
|
||||
{ name: "Thriller", playcount: "120", artist: { name: "Michael Jackson" } },
|
||||
{ name: "Definitely Maybe", playcount: "80", artist: { name: "Oasis" } }, // excluded
|
||||
],
|
||||
);
|
||||
const res = await GET(req("?artist=Michael+Jackson"));
|
||||
expect(res.status).toBe(200);
|
||||
const body = await res.json();
|
||||
expect(body).toEqual({
|
||||
topTracks: [
|
||||
{ name: "Billie Jean", plays: 2 },
|
||||
{ name: "Beat It", plays: 1 },
|
||||
{ name: "Billie Jean", plays: 50 },
|
||||
{ name: "Beat It", plays: 30 },
|
||||
],
|
||||
topAlbums: [{ name: "Thriller", plays: 3 }],
|
||||
topAlbums: [{ name: "Thriller", plays: 120 }],
|
||||
sampled: false,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user