Files
opencloud/services/search/pkg/mapping/deserialize_string_test.go
Dominik Schmidt 431c97e712 test(search): convert mapping package tests to ginkgo
New package, so use the repo's standard test framework.
2026-07-05 16:56:10 +02:00

99 lines
3.6 KiB
Go

package mapping
import (
"reflect"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"google.golang.org/protobuf/types/known/timestamppb"
)
type stringFacet struct {
Artist *string `json:"artist,omitempty"`
Year *int32 `json:"year,omitempty"`
Duration *int64 `json:"duration,omitempty"`
Rating *float64 `json:"rating,omitempty"`
Explicit *bool `json:"explicit,omitempty"`
Taken *time.Time `json:"takenDateTime,omitempty"`
}
var _ = Describe("DeserializeStringsAt", func() {
It("errors on an unsupported target kind", func() {
v := reflect.New(reflect.TypeFor[[]int]()).Elem() // settable slice
Expect(setValueFromString(v, "x")).To(HaveOccurred(), "expected error for unsupported target kind (slice)")
})
It("parses basic types", func() {
r := DeserializeStringsAt[stringFacet](map[string]string{
"libre.graph.audio.artist": "Queen",
"libre.graph.audio.year": "1975",
"libre.graph.audio.duration": "354000",
"libre.graph.audio.rating": "4.9",
"libre.graph.audio.explicit": "true",
"libre.graph.audio.takenDateTime": "2024-01-02T03:04:05Z",
}, "libre.graph.audio.")
Expect(r).ToNot(BeNil())
Expect(r.Artist).ToNot(BeNil())
Expect(*r.Artist).To(Equal("Queen"))
Expect(r.Year).ToNot(BeNil())
Expect(*r.Year).To(Equal(int32(1975)))
Expect(r.Duration).ToNot(BeNil())
Expect(*r.Duration).To(Equal(int64(354000)))
Expect(r.Rating).ToNot(BeNil())
Expect(*r.Rating).To(Equal(4.9))
Expect(r.Explicit).ToNot(BeNil())
Expect(*r.Explicit).To(BeTrue())
Expect(r.Taken).ToNot(BeNil())
Expect(r.Taken.Equal(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC))).To(BeTrue(), "Taken: %#v", r.Taken)
})
It("returns nil when nothing matches the prefix", func() {
r := DeserializeStringsAt[stringFacet](map[string]string{
"libre.graph.image.width": "1200",
}, "libre.graph.audio.")
Expect(r).To(BeNil())
})
It("parses into a timestamppb.Timestamp", func() {
type photoFacet struct {
Taken *timestamppb.Timestamp `json:"takenDateTime,omitempty"`
}
r := DeserializeStringsAt[photoFacet](map[string]string{
"libre.graph.photo.takenDateTime": "2024-05-06T07:08:09Z",
}, "libre.graph.photo.")
Expect(r).ToNot(BeNil())
Expect(r.Taken).ToNot(BeNil())
want := time.Date(2024, 5, 6, 7, 8, 9, 0, time.UTC)
Expect(r.Taken.AsTime().Equal(want)).To(BeTrue(), "Taken: got %v, want %v", r.Taken.AsTime(), want)
})
It("is fail-soft on malformed fields", func() {
// A single malformed field (year is unparseable as int) must not drop
// the whole facet. The bad field stays at zero value, the rest of the
// facet still populates. Mirrors the bleve-hit Deserialize behavior.
r := DeserializeStringsAt[stringFacet](map[string]string{
"libre.graph.audio.artist": "Iron Maiden",
"libre.graph.audio.year": "not-a-number",
"libre.graph.audio.duration": "354000",
"libre.graph.audio.explicit": "not-a-bool",
"libre.graph.audio.rating": "4.9",
}, "libre.graph.audio.")
Expect(r).ToNot(BeNil())
Expect(r.Artist).ToNot(BeNil())
Expect(*r.Artist).To(Equal("Iron Maiden"), "Artist should still be populated")
Expect(r.Duration).ToNot(BeNil())
Expect(*r.Duration).To(Equal(int64(354000)), "Duration should still be populated")
Expect(r.Rating).ToNot(BeNil())
Expect(*r.Rating).To(Equal(4.9), "Rating should still be populated")
Expect(r.Year).To(BeNil(), "Year should stay nil for bad int")
Expect(r.Explicit).To(BeNil(), "Explicit should stay nil for bad bool")
})
It("panics for a non-struct T", func() {
Expect(func() {
DeserializeStringsAt[int](nil, "")
}).To(Panic())
})
})