package api import ( "encoding/json" "testing" ) func heroSearchPayload(id, name, itemType string) json.RawMessage { return json.RawMessage(`{"Id":"` + id + `","Name":"` + name + `","Type":"` + itemType + `"}`) } // The picker asks two sources that mostly agree, so one title arriving twice is the // ordinary case rather than a fault, and the catalogue's ranking is the one kept. func TestHeroSearchMergeKeepsTheFirstSighting(t *testing.T) { merged := mergeHeroSearchResults([]json.RawMessage{ heroSearchPayload("1", "Arrival", "Movie"), heroSearchPayload("2", "Severance", "Series"), heroSearchPayload("1", "Arrival", "Movie"), }, 20) if len(merged) != 2 { t.Fatalf("merged %d titles, want 2", len(merged)) } if merged[0].ID != "1" || merged[1].ID != "2" { t.Fatalf("merge reordered the catalogue's answer: %+v", merged) } } // The whole reason Emby is asked: a title imported since the last pass is in one half of // the answer only, and it must survive into the list an operator can pin from. func TestHeroSearchMergeAdoptsATitleTheCatalogueMissed(t *testing.T) { merged := mergeHeroSearchResults([]json.RawMessage{ heroSearchPayload("1", "Arrival", "Movie"), heroSearchPayload("1", "Arrival", "Movie"), heroSearchPayload("9", "Arrival of the Birds", "Movie"), }, 20) if len(merged) != 2 || merged[1].ID != "9" { t.Fatalf("a title only Emby knew about was dropped: %+v", merged) } } // A hero is a film or a show. An episode matching the term, and a synthetic schedule card // that cannot be played at all, are both things the picker must not offer. func TestHeroSearchMergeOffersOnlyPinnableTitles(t *testing.T) { merged := mergeHeroSearchResults([]json.RawMessage{ heroSearchPayload("1", "Severance S01E01", "Episode"), json.RawMessage(`{"Id":"2","Name":"Dune","Type":"Movie","MembySource":"radarr"}`), heroSearchPayload("3", "Dune", "Movie"), }, 20) if len(merged) != 1 || merged[0].ID != "3" { t.Fatalf("picker offered something unpinnable: %+v", merged) } } func TestHeroSearchMergeTrimsToTheLimit(t *testing.T) { items := make([]json.RawMessage, 0, 30) for index := range 30 { items = append(items, heroSearchPayload(string(rune('a'+index)), "Title", "Movie")) } if merged := mergeHeroSearchResults(items, 20); len(merged) != 20 { t.Fatalf("merged %d titles, want the limit of 20", len(merged)) } }