package persistenceimport ("time""github.com/Masterminds/squirrel""github.com/navidrome/navidrome/conf""github.com/navidrome/navidrome/conf/configtest". "github.com/onsi/ginkgo/v2". "github.com/onsi/gomega")var _ = Describe("Helpers", func() {Describe("toSnakeCase", func() {It("converts camelCase", func() {Expect(toSnakeCase("camelCase")).To(Equal("camel_case"))})It("converts PascalCase", func() {Expect(toSnakeCase("PascalCase")).To(Equal("pascal_case"))})It("converts ALLCAPS", func() {Expect(toSnakeCase("ALLCAPS")).To(Equal("allcaps"))})It("does not converts snake_case", func() {Expect(toSnakeCase("snake_case")).To(Equal("snake_case"))})})Describe("toCamelCase", func() {It("converts snake_case", func() {Expect(toCamelCase("snake_case")).To(Equal("snakeCase"))})It("converts PascalCase", func() {Expect(toCamelCase("PascalCase")).To(Equal("PascalCase"))})It("converts camelCase", func() {Expect(toCamelCase("camelCase")).To(Equal("camelCase"))})It("converts ALLCAPS", func() {Expect(toCamelCase("ALLCAPS")).To(Equal("ALLCAPS"))})})Describe("toSQLArgs", func() {type Embed struct{}type Model struct {Embed `structs:"-"`ID string `structs:"id" json:"id"`AlbumId string `structs:"album_id" json:"albumId"`PlayCount int `structs:"play_count" json:"playCount"`UpdatedAt *time.Time `structs:"updated_at"`CreatedAt time.Time `structs:"created_at"`}It("returns a map with snake_case keys", func() {now := time.Now()m := &Model{ID: "123", AlbumId: "456", CreatedAt: now, UpdatedAt: &now, PlayCount: 2}args, err := toSQLArgs(m)Expect(err).To(BeNil())Expect(args).To(SatisfyAll(HaveKeyWithValue("id", "123"),HaveKeyWithValue("album_id", "456"),HaveKeyWithValue("play_count", 2),HaveKeyWithValue("updated_at", BeTemporally("~", now)),HaveKeyWithValue("created_at", BeTemporally("~", now)),Not(HaveKey("Embed")),))})})Describe("Exists", func() {It("constructs the correct EXISTS query", func() {e := Exists("album", squirrel.Eq{"id": 1})sql, args, err := e.ToSql()Expect(sql).To(Equal("exists (select 1 from album where id = ?)"))Expect(args).To(ConsistOf(1))Expect(err).To(BeNil())})})Describe("NotExists", func() {It("constructs the correct NOT EXISTS query", func() {e := NotExists("artist", squirrel.ConcatExpr("id = artist_id"))sql, args, err := e.ToSql()Expect(sql).To(Equal("not exists (select 1 from artist where id = artist_id)"))Expect(args).To(BeEmpty())Expect(err).To(BeNil())})})Describe("mapSortOrder", func() {BeforeEach(func() {DeferCleanup(configtest.SetupConfig())})It("does not change the sort string if there are no order columns", func() {Expect(mapSortOrder("album", "album_name asc")).To(Equal("album_name asc"))})DescribeTable("maps order columns to a collated expression",func(preferSortTags, naturalSorting bool, expected string) {conf.Server.PreferSortTags = preferSortTagsconf.Server.EnableNaturalSorting = naturalSortingExpect(mapSortOrder("album", "ORDER_ALBUM_NAME asc")).To(Equal(expected))},Entry("qualified column", false, false,"(album.order_album_name collate nocase) asc"),Entry("natural collation", false, true,"(album.order_album_name collate NATSORT) asc"),Entry("sort tags preferred", true, false,`(coalesce(nullif(album.sort_album_name,''),album.order_album_name) collate nocase) asc`),Entry("sort tags preferred, natural collation", true, true,`(coalesce(nullif(album.sort_album_name,''),album.order_album_name) collate NATSORT) asc`),)It("changes multiple order columns to sort expressions", func() {conf.Server.PreferSortTags = truesort := "compilation, order_title asc, order_album_artist_name desc, year desc"Expect(mapSortOrder("album", sort)).To(Equal(`compilation, (coalesce(nullif(album.sort_title,''),album.order_title) collate nocase) asc,` +` (coalesce(nullif(album.sort_album_artist_name,''),album.order_album_artist_name) collate nocase) desc, year desc`))})})Describe("naturalSort", func() {BeforeEach(func() {DeferCleanup(configtest.SetupConfig())})It("leaves the column alone by default, keeping its declared collation", func() {Expect(naturalSort("media_file.title")).To(Equal("media_file.title"))})It("applies the natural collation when enabled", func() {conf.Server.EnableNaturalSorting = trueExpect(naturalSort("media_file.title")).To(Equal("(media_file.title collate NATSORT)"))})})})