155 lines
6.2 KiB
Go
155 lines
6.2 KiB
Go
package store
|
||
|
||
import (
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
func TestQuietTimeActiveHandlesDaytimeAndOvernightWindows(t *testing.T) {
|
||
location := time.FixedZone("NZST", 12*60*60)
|
||
at := func(hour, minute int) time.Time {
|
||
return time.Date(2026, time.August, 17, hour, minute, 0, 0, location)
|
||
}
|
||
tests := []struct {
|
||
name string
|
||
policy QuietTime
|
||
now time.Time
|
||
want bool
|
||
}{
|
||
{"disabled", QuietTime{StartTime: "23:00", EndTime: "07:00"}, at(23, 30), false},
|
||
{"overnight evening", QuietTime{Enabled: true, StartTime: "23:00", EndTime: "07:00"}, at(23, 0), true},
|
||
{"overnight morning", QuietTime{Enabled: true, StartTime: "23:00", EndTime: "07:00"}, at(6, 59), true},
|
||
{"overnight end exclusive", QuietTime{Enabled: true, StartTime: "23:00", EndTime: "07:00"}, at(7, 0), false},
|
||
{"daytime inside", QuietTime{Enabled: true, StartTime: "09:00", EndTime: "17:00"}, at(12, 0), true},
|
||
{"daytime outside", QuietTime{Enabled: true, StartTime: "09:00", EndTime: "17:00"}, at(18, 0), false},
|
||
{"equal endpoints are safe", QuietTime{Enabled: true, StartTime: "09:00", EndTime: "09:00"}, at(9, 0), false},
|
||
}
|
||
for _, test := range tests {
|
||
t.Run(test.name, func(t *testing.T) {
|
||
if got := QuietTimeActive(test.policy, test.now, location); got != test.want {
|
||
t.Fatalf("QuietTimeActive() = %v, want %v", got, test.want)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
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 TestHeroPolicyKeepsRecurringSchedulesWithoutAbsoluteDates(t *testing.T) {
|
||
got := normalizeHeroPolicy(HeroPolicy{Schedules: []HeroSchedule{
|
||
{ID: "daily", ItemID: "one", Frequency: "DAILY", StartTime: " 18:00 ", EndTime: "22:30", Enabled: true},
|
||
{ID: "weekly", ItemID: "two", Frequency: "weekly", StartTime: "22:00", EndTime: "02:00", Weekdays: []int{5, 5, 7}, Enabled: true},
|
||
}})
|
||
if len(got.Schedules) != 2 {
|
||
t.Fatalf("recurring schedules = %+v", got.Schedules)
|
||
}
|
||
if got.Schedules[0].Frequency != "daily" || len(got.Schedules[0].Weekdays) != 0 {
|
||
t.Fatalf("daily schedule = %+v", got.Schedules[0])
|
||
}
|
||
if got.Schedules[1].StartTime != "22:00" || len(got.Schedules[1].Weekdays) != 1 || got.Schedules[1].Weekdays[0] != 5 {
|
||
t.Fatalf("weekly schedule = %+v", got.Schedules[1])
|
||
}
|
||
}
|
||
|
||
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")
|
||
}
|
||
}
|