Files
memby/server/internal/library/syncer_test.go
T
2026-07-29 15:26:27 +12:00

97 lines
2.8 KiB
Go

package library
import (
"encoding/json"
"strings"
"testing"
)
func TestToLibraryItemFlattensColumnsAndKeepsPayload(t *testing.T) {
raw := json.RawMessage(`{
"Id":"42","Name":"Arrival","Type":"Movie","ProductionYear":2016,
"CommunityRating":7.9,"Genres":["Science Fiction"," Drama "],
"Studios":[{"Name":"Paramount"},{"Name":" "}],
"DateCreated":"2024-03-01T10:00:00Z",
"ImageTags":{"Primary":"abc"}
}`)
item, ok := toLibraryItem(raw)
if !ok {
t.Fatal("expected the item to parse")
}
if item.ID != "42" || item.Name != "Arrival" || item.Type != "Movie" {
t.Fatalf("unexpected columns: %+v", item)
}
if *item.ProductionYear != 2016 || *item.CommunityRating != 7.9 {
t.Fatalf("unexpected numbers: %+v", item)
}
// Whitespace-only studio names are dropped, real ones trimmed.
if len(item.Studios) != 1 || item.Studios[0] != "Paramount" {
t.Fatalf("unexpected studios: %v", item.Studios)
}
if len(item.Genres) != 2 || item.Genres[1] != "Drama" {
t.Fatalf("genres should be trimmed: %v", item.Genres)
}
if item.DateCreated == nil || item.DateCreated.Year() != 2024 {
t.Fatalf("unexpected date: %v", item.DateCreated)
}
// The payload must survive byte-identical: it is what the TV receives, and it holds
// fields (image tags, overview) that no column models.
if string(item.Payload) != string(raw) {
t.Fatal("payload was altered")
}
}
func TestToLibraryItemRejectsUnusableRows(t *testing.T) {
for name, raw := range map[string]string{
"malformed": `{"Id":`,
"no id": `{"Name":"Nameless"}`,
} {
if _, ok := toLibraryItem(json.RawMessage(raw)); ok {
t.Fatalf("%s should have been rejected", name)
}
}
}
func TestSearchTextIncludesSeriesNameSoEpisodesAreFindable(t *testing.T) {
year := 2022
text := searchText(syncItem{
Name: "Good News About Hell",
Type: "Episode",
SeriesName: "Severance",
ProductionYear: &year,
Genres: []string{"Drama", "Thriller"},
})
for _, want := range []string{"Good News About Hell", "Severance", "2022", "Drama"} {
if !strings.Contains(text, want) {
t.Fatalf("search text %q is missing %q", text, want)
}
}
}
func TestSearchTextIncludesStudiosSoAStudioNameFindsItsTitles(t *testing.T) {
text := searchText(syncItem{
Name: "Everything Everywhere All at Once",
Type: "Movie",
Studios: []struct {
Name string `json:"Name"`
}{{Name: "A24"}, {Name: ""}},
})
if !strings.Contains(text, "A24") {
t.Fatalf("search text %q is missing the studio", text)
}
if strings.Contains(text, " ") {
t.Fatalf("an unnamed studio should be skipped, not joined as a gap: %q", text)
}
}
func TestSearchTextDoesNotRepeatTheTitleForAMovie(t *testing.T) {
text := searchText(syncItem{Name: "Dune", Type: "Movie", SeriesName: "Dune"})
if strings.Count(strings.ToLower(text), "dune") != 1 {
t.Fatalf("title should appear once, got %q", text)
}
}