navidrome/core/artwork/reader_folder_test.go
Patrik Wallström 0addb23bf5 Add folder artwork support and SongsByFolder filter
Signed-off-by: Patrik Wallström <pawal@amplitut.de>
2026-03-15 02:58:11 +01:00

135 lines
4.3 KiB
Go

package artwork
import (
"context"
"os"
"path/filepath"
"time"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/conf/configtest"
"github.com/navidrome/navidrome/model"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("folderArtworkReader", func() {
var (
ctx context.Context
a *artwork
tmpDir string
folderRepo *fakeFolderRepo
folder model.Folder
)
BeforeEach(func() {
DeferCleanup(configtest.SetupConfig())
ctx = context.Background()
tmpDir = GinkgoT().TempDir()
conf.Server.CoverArtPriority = "cover.*, front.*, *"
folderRepo = &fakeFolderRepo{}
ds := &fakeDataStore{folderRepo: folderRepo}
a = &artwork{ds: ds}
folder = model.Folder{
ID: "folder-1",
LibraryPath: tmpDir,
Path: ".",
Name: "Jazz",
ImageFiles: []string{"cover.jpg"},
ImagesUpdatedAt: time.Now().Truncate(time.Second),
}
})
createImage := func(name string) {
fullPath := filepath.Join(folder.AbsolutePath(), name)
Expect(os.MkdirAll(filepath.Dir(fullPath), 0755)).To(Succeed())
Expect(os.WriteFile(fullPath, []byte("image data"), 0600)).To(Succeed())
}
Describe("newFolderArtworkReader", func() {
It("returns a reader when the folder is found", func() {
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
Expect(reader).ToNot(BeNil())
})
It("returns an error when the folder is not found", func() {
artID := model.NewArtworkID(model.KindFolderArtwork, "missing", nil)
_, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).To(MatchError(model.ErrNotFound))
})
It("builds absolute image file paths from folder.ImageFiles", func() {
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
Expect(reader.imgFiles).To(ConsistOf(
filepath.Join(folder.AbsolutePath(), "cover.jpg"),
))
})
It("uses ImagesUpdatedAt as the cache key lastUpdate", func() {
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
Expect(reader.LastUpdated()).To(Equal(folder.ImagesUpdatedAt))
})
})
Describe("Reader", func() {
It("returns the matching image file", func() {
createImage("cover.jpg")
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
rc, path, err := reader.Reader(ctx)
Expect(err).ToNot(HaveOccurred())
Expect(rc).ToNot(BeNil())
Expect(path).To(ContainSubstring("cover.jpg"))
rc.Close()
})
It("returns ErrUnavailable when no images match the priority patterns", func() {
conf.Server.CoverArtPriority = "cover.*"
folder.ImageFiles = []string{"other.jpg"}
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
_, _, err = reader.Reader(ctx)
Expect(err).To(MatchError(ErrUnavailable))
})
It("skips embedded and external patterns without error", func() {
conf.Server.CoverArtPriority = "embedded, external, cover.*"
createImage("cover.jpg")
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
rc, _, err := reader.Reader(ctx)
Expect(err).ToNot(HaveOccurred())
Expect(rc).ToNot(BeNil())
rc.Close()
})
It("returns ErrUnavailable when folder has no images and only external/embedded in priority", func() {
conf.Server.CoverArtPriority = "embedded, external"
folder.ImageFiles = []string{}
folderRepo.parentResult = &folder
artID := model.NewArtworkID(model.KindFolderArtwork, "folder-1", nil)
reader, err := newFolderArtworkReader(ctx, a, artID)
Expect(err).ToNot(HaveOccurred())
_, _, err = reader.Reader(ctx)
Expect(err).To(MatchError(ErrUnavailable))
})
})
})