From 13e3d53b9a744e332990060aaa9b6da909020a50 Mon Sep 17 00:00:00 2001 From: ranokay Date: Sat, 17 Oct 2026 12:12:05 +0300 Subject: [PATCH] test(lyrics): pin multi-source variant passthrough and serialization Signed-off-by: ranokay --- core/lyrics/lyrics_test.go | 40 ++++++++++++++++++++++++++++ server/subsonic/lyrics_test.go | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/core/lyrics/lyrics_test.go b/core/lyrics/lyrics_test.go index e76cc5469..a2b013e7c 100644 --- a/core/lyrics/lyrics_test.go +++ b/core/lyrics/lyrics_test.go @@ -362,6 +362,46 @@ var _ = Describe("Lyrics", func() { }) }) + It("returns every source-tagged variant in order", func() { + conf.Server.LyricsPriority = "test-lyrics-plugin" + mockLoader.lyrics = model.LyricList{ + { + Lang: "eng", + Synced: true, + Line: []model.Line{{Value: "first"}}, + Source: &model.LyricsSource{ + Type: model.LyricsSourcePlugin, Name: "test-lyrics-plugin", + Provider: "NetEase", Format: "elrc", + }, + }, + { + Lang: "eng", + Synced: true, + Line: []model.Line{{Value: "second"}}, + Source: &model.LyricsSource{ + Type: model.LyricsSourcePlugin, Name: "test-lyrics-plugin", + Provider: "LRCLib", Format: "lrc", + }, + }, + } + svc := lyrics.NewLyrics(nil, mockLoader) + list, err := svc.GetLyrics(ctx, &mf) + Expect(err).To(BeNil()) + Expect(list).To(HaveLen(2)) + Expect(*list[0].Source).To(Equal(model.LyricsSource{ + Type: model.LyricsSourcePlugin, Name: "test-lyrics-plugin", + Provider: "NetEase", Format: "elrc", + })) + Expect(*list[1].Source).To(Equal(model.LyricsSource{ + Type: model.LyricsSourcePlugin, Name: "test-lyrics-plugin", + Provider: "LRCLib", Format: "lrc", + })) + // Legacy single-lyric consumers keep serving the first variant. + main, ok := list.Main() + Expect(ok).To(BeTrue()) + Expect(main.Line[0].Value).To(Equal("first")) + }) + It("should skip unknown plugin names gracefully", func() { conf.Server.LyricsPriority = "nonexistent-plugin,embedded" mockLoader.notFound = true diff --git a/server/subsonic/lyrics_test.go b/server/subsonic/lyrics_test.go index 8d97aa5f3..74fb5292d 100644 --- a/server/subsonic/lyrics_test.go +++ b/server/subsonic/lyrics_test.go @@ -156,6 +156,54 @@ var _ = Describe("GetLyricsBySongId", func() { }) }) + It("should return every variant with its own source", func() { + lineStart := int64(1000) + lyricsJSON, err := json.Marshal(model.LyricList{ + { + Kind: "main", Lang: "eng", Synced: true, + Line: []model.Line{{Start: &lineStart, Value: "alpha line"}}, + Source: &model.LyricsSource{Type: model.LyricsSourcePlugin, Name: "Better Lyrics", Provider: "NetEase", Format: "elrc"}, + }, + { + Kind: "main", Lang: "eng", Synced: true, + Line: []model.Line{{Start: &lineStart, Value: "beta line"}}, + Source: &model.LyricsSource{Type: model.LyricsSourcePlugin, Name: "Better Lyrics", Provider: "LRCLib", Format: "lrc"}, + }, + }) + Expect(err).ToNot(HaveOccurred()) + + mockRepo.SetData(model.MediaFiles{ + { + ID: "1", + Artist: "Rick Astley", + Title: "Never Gonna Give You Up", + Lyrics: string(lyricsJSON), + }, + }) + + response, err := router.GetLyricsBySongId(newGetRequest("id=1&enhanced=true")) + Expect(err).ToNot(HaveOccurred()) + Expect(response.LyricsList.StructuredLyrics).To(HaveLen(2)) + Expect(response.LyricsList.StructuredLyrics[0].Kind).To(Equal("main")) + Expect(response.LyricsList.StructuredLyrics[0].Source).To(Equal(&responses.LyricsSource{ + Type: "plugin", Name: "Better Lyrics", Provider: "NetEase", Format: "elrc", + })) + Expect(response.LyricsList.StructuredLyrics[1].Kind).To(Equal("main")) + Expect(response.LyricsList.StructuredLyrics[1].Source).To(Equal(&responses.LyricsSource{ + Type: "plugin", Name: "Better Lyrics", Provider: "LRCLib", Format: "lrc", + })) + + // The v1 (non-enhanced) shape still returns the entries, without any + // enhanced fields: no source, no kind. + v1, err := router.GetLyricsBySongId(newGetRequest("id=1")) + Expect(err).ToNot(HaveOccurred()) + Expect(v1.LyricsList.StructuredLyrics).To(HaveLen(2)) + for _, lyric := range v1.LyricsList.StructuredLyrics { + Expect(lyric.Source).To(BeNil()) + Expect(lyric.Kind).To(BeEmpty()) + } + }) + It("should parse lrc metadata", func() { r := newGetRequest("id=1") syncedList, _ := model.ParseLyrics(GinkgoT().Context(), ".lrc", "eng", []byte(metadata+"\n"+syncedLyrics))