feat(web): "In library, not followed" section on the Artists page
Adds a section at the bottom of the Artists overview listing artists you own music by (LibraryItem) but don't follow (WatchedArtist), each with a Follow action — so you can start monitoring artists already in your library. - /api/artists GET now also returns `ownedNotFollowed`: distinct LibraryItem artist names not matching the watched roster (case-insensitive; the known have-via-scan name-match caveat, #18). - Follow resolves the library name → MBID (/api/mb/artists) then POST /api/artists with the canonical MB name (mirrors the Last.fm/discover follow flow); a no-match surfaces a toast. Followed names hide immediately via a session set, even if the MB canonical name differs from the library name. web 153 tests (owned-not-followed + case-insensitive match asserted), tsc + build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,6 +84,20 @@ describe("artists collection API", () => {
|
||||
expect(after).toMatchObject({ showAllTypes: true, releaseCount: 2, monitoredCount: 2, haveCount: 2 });
|
||||
});
|
||||
|
||||
it("GET lists owned artists that are not followed (case-insensitive)", async () => {
|
||||
// one owned + followed, one owned + not followed, one owned matching a followed name by case
|
||||
await prisma.watchedArtist.create({ data: { mbid: "wf", name: "Followed Artist" } });
|
||||
for (const [artist, album] of [["Followed Artist", "A"], ["Unfollowed Artist", "B"], ["followed artist", "C"]] as const) {
|
||||
await prisma.libraryItem.create({
|
||||
data: { artist, album, path: `/${album}`, source: "scan", format: "FLAC", qualityClass: 2 },
|
||||
});
|
||||
}
|
||||
const body = await (await GET(listReq())).json();
|
||||
expect(body.ownedNotFollowed).toContain("Unfollowed Artist");
|
||||
expect(body.ownedNotFollowed).not.toContain("Followed Artist");
|
||||
expect(body.ownedNotFollowed).not.toContain("followed artist"); // case-insensitive match
|
||||
});
|
||||
|
||||
it("GET ?mbid= returns the follow state for a single artist", async () => {
|
||||
await prisma.watchedArtist.create({ data: { mbid: "followed-1", name: "Followed" } });
|
||||
expect((await (await GET(listReq("?mbid=followed-1"))).json()).followed).toBe(true);
|
||||
|
||||
Reference in New Issue
Block a user