Files
memby/server/internal/api/extras_test.go
T

91 lines
2.9 KiB
Go

package api
import (
"encoding/json"
"strings"
"testing"
)
// The two lists Emby answers with can name the same file, and the television renders the
// result into a keyed grid — which throws on a repeated key rather than merely looking
// wrong. First-seen order is kept, so the trailer stays at the front where the join put it.
func TestDedupeExtrasKeepsFirstOfEachID(t *testing.T) {
items := []json.RawMessage{
json.RawMessage(`{"Id":"trailer-1","Name":"Official Trailer","Type":"Trailer"}`),
json.RawMessage(`{"Id":"feature-1","Name":"Four Winters","Type":"Featurette"}`),
json.RawMessage(`{"Id":"trailer-1","Name":"Official Trailer","Type":"Trailer"}`),
json.RawMessage(`{"Id":"feature-2","Name":"Deleted: The Crossing","Type":"DeletedScene"}`),
}
got := dedupeExtras(items)
if len(got) != 3 {
t.Fatalf("expected 3 extras after deduplication, got %d", len(got))
}
ids := extraIDs(t, got)
want := []string{"trailer-1", "feature-1", "feature-2"}
for index, id := range want {
if ids[index] != id {
t.Fatalf("extra %d was %q, want %q (order: %v)", index, ids[index], id, ids)
}
}
}
// An entry the television could not key is dropped rather than passed on. Nothing
// downstream can tell one blank id from another.
func TestDedupeExtrasDropsUnidentifiableEntries(t *testing.T) {
items := []json.RawMessage{
json.RawMessage(`{"Name":"Nameless","Type":"Clip"}`),
json.RawMessage(`{"Id":"","Name":"Blank","Type":"Clip"}`),
json.RawMessage(`not json at all`),
json.RawMessage(`{"Id":"clip-1","Name":"A Clip","Type":"Clip"}`),
}
got := dedupeExtras(items)
if len(got) != 1 {
t.Fatalf("expected only the identified extra to survive, got %d", len(got))
}
if ids := extraIDs(t, got); ids[0] != "clip-1" {
t.Fatalf("survivor was %q, want clip-1", ids[0])
}
}
func TestDedupeExtrasOnNothing(t *testing.T) {
if got := dedupeExtras(nil); len(got) != 0 {
t.Fatalf("expected no extras, got %d", len(got))
}
}
// The Details tab is the only reader of these, and every one of them is absent from Emby's
// response unless it is asked for by name — so a field quietly dropped from the query is a
// row that silently stops appearing rather than anything that fails.
func TestDetailFieldsCarryTheDetailsTabVocabulary(t *testing.T) {
fields := make(map[string]bool)
for _, field := range strings.Split(fieldsDetail, ",") {
fields[field] = true
}
for _, required := range []string{
"Studios", "Taglines", "PremiereDate", "OriginalTitle", "ProductionLocations",
} {
if !fields[required] {
t.Errorf("detail responses must request %q for the Details tab", required)
}
}
}
func extraIDs(t *testing.T, items []json.RawMessage) []string {
t.Helper()
ids := make([]string, 0, len(items))
for _, raw := range items {
var identified struct {
ID string `json:"Id"`
}
if err := json.Unmarshal(raw, &identified); err != nil {
t.Fatalf("could not read back an extra: %v", err)
}
ids = append(ids, identified.ID)
}
return ids
}