From 99ea8d24281c08b27bdfe7ca3e2520998b023d88 Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 26 Jul 2026 20:48:16 -0400 Subject: [PATCH] test(artwork): pin that a request never fetches or samples album art resolveItemLocal's guard against the remote ExternalImageURL fetch and the 2x2 grid had no coverage: deleting it left the whole suite green while putting synchronous network calls on the request path. The worker resolving the same playlist is asserted alongside, so the spec cannot pass by simply resolving nothing. --- core/artwork/resolve_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core/artwork/resolve_test.go b/core/artwork/resolve_test.go index 63637240f..6a78dbf45 100644 --- a/core/artwork/resolve_test.go +++ b/core/artwork/resolve_test.go @@ -10,6 +10,7 @@ import ( "net/http/httptest" "os" "path/filepath" + "sync/atomic" "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/conf/configtest" @@ -507,6 +508,36 @@ var _ = Describe("resolveItem", func() { Expect(res.extError).To(BeFalse()) }) + // The request path must never reach the network nor sample album art synchronously. The + // worker resolving the same playlist is asserted alongside, so this cannot pass vacuously. + It("resolves a playlist locally without fetching remotely or building the grid", func() { + conf.Server.EnableM3UExternalAlbumArt = true + var hits atomic.Int32 + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + hits.Add(1) + w.WriteHeader(http.StatusNotFound) + })) + defer srv.Close() + + plRepo := tests.CreateMockPlaylistRepo() + plRepo.SetData(model.Playlists{{ID: "pllocal", Name: "Playlist", ExternalImageURL: srv.URL}}) + plRepo.TracksRepo = &tests.MockPlaylistTrackRepo{AlbumIDs: []string{"t1"}} + ds.MockedPlaylist = plRepo + item := model.ArtworkQueueItem{ItemKind: "pl", ItemID: "pllocal"} + + res, err := resolveItemLocal(ctx, ds, ffm, item) + Expect(err).ToNot(HaveOccurred()) + Expect(res.reader).To(BeNil(), "no local source, and the grid is worker-only") + Expect(hits.Load()).To(BeZero(), "a request must never reach the network") + + worker, err := resolveItem(ctx, ds, ag, ffm, item, nil) + Expect(err).ToNot(HaveOccurred()) + Expect(worker.reader).ToNot(BeNil()) + defer worker.reader.Close() + Expect(worker.source).To(Equal("generated"), "the worker does build the grid") + Expect(hits.Load()).To(Equal(int32(1)), "and the worker does fetch") + }) + It("treats an ExternalImageURL 500 as a transient failure and sets extError", func() { conf.Server.EnableM3UExternalAlbumArt = true folderRepo.result = nil // no grid tiles, so the external failure is what surfaces