package e2e import ( "github.com/navidrome/navidrome/server/subsonic/responses" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) var _ = Describe("Search Endpoints", func() { BeforeEach(func() { setupTestDB() }) Describe("Search2", func() { It("finds artists by name", func() { resp := doReq("search2", "query", "Beatles") Expect(resp.Status).To(Equal(responses.StatusOK)) Expect(resp.SearchResult2).ToNot(BeNil()) Expect(resp.SearchResult2.Artist).ToNot(BeEmpty()) found := false for _, a := range resp.SearchResult2.Artist { if a.Name == "The Beatles" { found = true break } } Expect(found).To(BeTrue(), "expected to find artist 'The Beatles'") }) It("finds albums by name", func() { resp := doReq("search2", "query", "Abbey Road") Expect(resp.SearchResult2).ToNot(BeNil()) Expect(resp.SearchResult2.Album).ToNot(BeEmpty()) found := false for _, a := range resp.SearchResult2.Album { if a.Title == "Abbey Road" { found = true break } } Expect(found).To(BeTrue(), "expected to find album 'Abbey Road'") }) It("finds songs by title", func() { resp := doReq("search2", "query", "Come Together") Expect(resp.SearchResult2).ToNot(BeNil()) Expect(resp.SearchResult2.Song).ToNot(BeEmpty()) found := false for _, s := range resp.SearchResult2.Song { if s.Title == "Come Together" { found = true break } } Expect(found).To(BeTrue(), "expected to find song 'Come Together'") }) It("respects artistCount/albumCount/songCount limits", func() { resp := doReq("search2", "query", "Beatles", "artistCount", "1", "albumCount", "1", "songCount", "1") Expect(resp.SearchResult2).ToNot(BeNil()) Expect(len(resp.SearchResult2.Artist)).To(BeNumerically("<=", 1)) Expect(len(resp.SearchResult2.Album)).To(BeNumerically("<=", 1)) Expect(len(resp.SearchResult2.Song)).To(BeNumerically("<=", 1)) }) It("supports offset parameters", func() { // First get all results for Beatles resp1 := doReq("search2", "query", "Beatles", "songCount", "500") allSongs := resp1.SearchResult2.Song if len(allSongs) > 1 { // Get with offset to skip the first song resp2 := doReq("search2", "query", "Beatles", "songOffset", "1", "songCount", "500") Expect(resp2.SearchResult2).ToNot(BeNil()) Expect(len(resp2.SearchResult2.Song)).To(Equal(len(allSongs) - 1)) } }) It("returns empty results for non-matching query", func() { resp := doReq("search2", "query", "ZZZZNONEXISTENT99999") Expect(resp.SearchResult2).ToNot(BeNil()) Expect(resp.SearchResult2.Artist).To(BeEmpty()) Expect(resp.SearchResult2.Album).To(BeEmpty()) Expect(resp.SearchResult2.Song).To(BeEmpty()) }) }) Describe("Search3", func() { It("returns results in ID3 format", func() { resp := doReq("search3", "query", "Beatles") Expect(resp.Status).To(Equal(responses.StatusOK)) Expect(resp.SearchResult3).ToNot(BeNil()) // Verify ID3 format: Artist should be ArtistID3 with Name and AlbumCount Expect(resp.SearchResult3.Artist).ToNot(BeEmpty()) Expect(resp.SearchResult3.Artist[0].Name).ToNot(BeEmpty()) Expect(resp.SearchResult3.Artist[0].Id).ToNot(BeEmpty()) }) It("finds across all entity types simultaneously", func() { // "Beatles" should match artist, albums, and songs by The Beatles resp := doReq("search3", "query", "Beatles") Expect(resp.SearchResult3).ToNot(BeNil()) // Should find at least the artist "The Beatles" artistFound := false for _, a := range resp.SearchResult3.Artist { if a.Name == "The Beatles" { artistFound = true break } } Expect(artistFound).To(BeTrue(), "expected to find artist 'The Beatles'") // Should find albums by The Beatles (albums contain "Beatles" in artist field) // Albums are returned as AlbumID3 type for _, a := range resp.SearchResult3.Album { Expect(a.Id).ToNot(BeEmpty()) Expect(a.Name).ToNot(BeEmpty()) } // Songs are returned as Child type for _, s := range resp.SearchResult3.Song { Expect(s.Id).ToNot(BeEmpty()) Expect(s.Title).ToNot(BeEmpty()) } }) }) })