package store import ( "testing" "time" ) func TestRequestPolicyAllowsOnlyListedUsers(t *testing.T) { policy := RequestPolicy{AllowedUserIDs: []string{"user-2"}} if policy.Allows("user-1") { t.Fatal("unlisted user was allowed") } if !policy.Allows("user-2") { t.Fatal("listed user was denied") } } func TestPlaybackPolicyDefaultsAndClampsDuration(t *testing.T) { defaults := DefaultPlaybackPolicy() if !defaults.PrerollEnabled || defaults.PrerollDurationMs != 6_500 { t.Fatalf("default playback policy = %+v", defaults) } if got := normalizePlaybackPolicy(PlaybackPolicy{PrerollDurationMs: 500}); got.PrerollDurationMs != 1_000 { t.Fatalf("short duration = %d, want 1000", got.PrerollDurationMs) } if got := normalizePlaybackPolicy(PlaybackPolicy{PrerollDurationMs: 60_000}); got.PrerollDurationMs != 30_000 { t.Fatalf("long duration = %d, want 30000", got.PrerollDurationMs) } } func TestHeroPolicyKeepsFourUniqueTrimmedItemIDsInOrder(t *testing.T) { got := normalizeHeroPolicy(HeroPolicy{PinnedItemIDs: []string{ " movie-2 ", "movie-1", "movie-2", "", "movie-3", "movie-4", "movie-5", }, PrimeSubtitle: " Tonight’s pick "}) want := []string{"movie-2", "movie-1", "movie-3", "movie-4"} if len(got.PinnedItemIDs) != len(want) { t.Fatalf("pinned ids = %v, want %v", got.PinnedItemIDs, want) } for index := range want { if got.PinnedItemIDs[index] != want[index] { t.Fatalf("pinned ids = %v, want %v", got.PinnedItemIDs, want) } } if got.PrimeSubtitle != "Tonight’s pick" { t.Fatalf("prime subtitle = %q", got.PrimeSubtitle) } } func TestHeroPolicyReadsTheEarlierMovieOnlyShape(t *testing.T) { got := normalizeHeroPolicy(HeroPolicy{LegacyPinnedMovieIDs: []string{"movie-1"}}) if len(got.PinnedItemIDs) != 1 || got.PinnedItemIDs[0] != "movie-1" { t.Fatalf("legacy pinned ids = %v", got.PinnedItemIDs) } } func TestHeroPolicyMigratesHomeAndKeepsPlacementsIndependent(t *testing.T) { got := normalizeHeroPolicy(HeroPolicy{ PinnedItemIDs: []string{"home-1"}, Placements: map[string]HeroPlacementPolicy{ HeroPlacementMovies: {PinnedItemIDs: []string{"film-1"}}, HeroPlacementTVShows: {PinnedItemIDs: []string{"series-1"}}, }, }) if got.Placement(HeroPlacementHome).PinnedItemIDs[0] != "home-1" { t.Fatalf("legacy Home policy was not migrated: %+v", got.Placements) } if got.Placement(HeroPlacementMovies).PinnedItemIDs[0] != "film-1" || got.Placement(HeroPlacementTVShows).PinnedItemIDs[0] != "series-1" { t.Fatalf("placement policies crossed: %+v", got.Placements) } } func TestHeroSchedulesDefaultToHomeAndNormalisePlacementNames(t *testing.T) { now := time.Now() got := normalizeHeroPolicy(HeroPolicy{Schedules: []HeroSchedule{ {ID: "old", ItemID: "one", StartAt: now, EndAt: now.Add(time.Hour), Enabled: true}, {ID: "new", ItemID: "two", StartAt: now, EndAt: now.Add(time.Hour), Enabled: true, Placements: []string{" MOVIES ", "movies", "bad"}}, }}) if len(got.Schedules[0].Placements) != 1 || got.Schedules[0].Placements[0] != HeroPlacementHome { t.Fatalf("old schedule placements = %v", got.Schedules[0].Placements) } if len(got.Schedules[1].Placements) != 1 || got.Schedules[1].Placements[0] != HeroPlacementMovies { t.Fatalf("new schedule placements = %v", got.Schedules[1].Placements) } } func TestMDBListSettingsAreOptionalAndNormalizeSources(t *testing.T) { defaults := DefaultMDBListSettings() if defaults.Enabled || defaults.APIKey != "" || len(defaults.Sources) == 0 { t.Fatalf("default MDBList settings = %+v", defaults) } got := normalizeMDBListSettings(MDBListSettings{ APIKey: " secret ", Sources: []string{"IMDb", "imdb", "unknown", "letterboxd"}, }) if got.APIKey != "secret" || len(got.Sources) != 2 || got.Sources[0] != "imdb" || got.Sources[1] != "letterboxd" { t.Fatalf("normalised MDBList settings = %+v", got) } } func TestFeaturePolicyDefaultsAreRecoverable(t *testing.T) { policy := normalizeFeaturePolicy(FeaturePolicy{}) if policy.Overrides == nil || policy.SafeMode || policy.Revision != 0 { t.Fatalf("default feature policy = %+v", policy) } policy.Overrides["sonarr_preroll"] = false if policy.Overrides["sonarr_preroll"] { t.Fatal("explicit off override was not retained") } }