0.2.81
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ponzischeme89/memby/server/internal/store"
|
||||
)
|
||||
|
||||
var heroRevisionZone = time.FixedZone("NZST", 12*60*60)
|
||||
|
||||
func heroRevisionAt(policy store.HeroPolicy, user string, at time.Time) string {
|
||||
return heroRevision(policy, user, at, heroRevisionZone)
|
||||
}
|
||||
|
||||
func pinnedPolicy(placement string, ids ...string) store.HeroPolicy {
|
||||
return store.HeroPolicy{Placements: map[string]store.HeroPlacementPolicy{
|
||||
placement: {PinnedItemIDs: ids},
|
||||
}}
|
||||
}
|
||||
|
||||
func TestHeroRevisionIsStableWithinASlot(t *testing.T) {
|
||||
policy := pinnedPolicy(store.HeroPlacementHome, "film-1")
|
||||
morning := time.Date(2026, 8, 20, 8, 0, 0, 0, heroRevisionZone)
|
||||
if heroRevisionAt(policy, "user-1", morning) != heroRevisionAt(policy, "user-1", morning.Add(90*time.Minute)) {
|
||||
t.Fatal("hero revision moved without anything changing; every poll would refetch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionMovesWhenAnOperatorEditsPins(t *testing.T) {
|
||||
now := time.Date(2026, 8, 20, 8, 0, 0, 0, heroRevisionZone)
|
||||
before := heroRevisionAt(pinnedPolicy(store.HeroPlacementHome, "film-1"), "user-1", now)
|
||||
for name, policy := range map[string]store.HeroPolicy{
|
||||
"added": pinnedPolicy(store.HeroPlacementHome, "film-1", "film-2"),
|
||||
"removed": pinnedPolicy(store.HeroPlacementHome),
|
||||
"replaced": pinnedPolicy(store.HeroPlacementHome, "film-2"),
|
||||
} {
|
||||
if heroRevisionAt(policy, "user-1", now) == before {
|
||||
t.Fatalf("hero revision did not move when a pin was %s", name)
|
||||
}
|
||||
}
|
||||
// Order is the operator's decision about which card leads, so reordering is a change
|
||||
// even though the same titles are pinned.
|
||||
reordered := pinnedPolicy(store.HeroPlacementHome, "film-2", "film-1")
|
||||
if heroRevisionAt(reordered, "user-1", now) ==
|
||||
heroRevisionAt(pinnedPolicy(store.HeroPlacementHome, "film-1", "film-2"), "user-1", now) {
|
||||
t.Fatal("hero revision did not move when pins were reordered")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionSeparatesPlacements(t *testing.T) {
|
||||
now := time.Date(2026, 8, 20, 8, 0, 0, 0, heroRevisionZone)
|
||||
home := heroRevisionAt(pinnedPolicy(store.HeroPlacementHome, "film-1"), "user-1", now)
|
||||
movies := heroRevisionAt(pinnedPolicy(store.HeroPlacementMovies, "film-1"), "user-1", now)
|
||||
if home == movies {
|
||||
t.Fatal("pinning a title to Movies read as the same policy as pinning it to Home")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionIgnoresACosmeticSave(t *testing.T) {
|
||||
now := time.Date(2026, 8, 20, 8, 0, 0, 0, heroRevisionZone)
|
||||
saved := pinnedPolicy(store.HeroPlacementHome, "film-1")
|
||||
// UpdatedAt moves on every write. Hashing the document rather than what it resolves to
|
||||
// would repaint every launcher in the house for a save that changed nothing.
|
||||
resaved := pinnedPolicy(store.HeroPlacementHome, "film-1")
|
||||
resaved.UpdatedAt = now
|
||||
if heroRevisionAt(saved, "user-1", now) != heroRevisionAt(resaved, "user-1", now) {
|
||||
t.Fatal("hero revision moved for a save that changed nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionMovesWhenAScheduleOpensAndCloses(t *testing.T) {
|
||||
policy := store.HeroPolicy{Schedules: []store.HeroSchedule{{
|
||||
ID: "s1", ItemID: "film-9", Enabled: true,
|
||||
Frequency: "daily", StartTime: "20:00", EndTime: "22:00",
|
||||
Placements: []string{store.HeroPlacementHome},
|
||||
}}}
|
||||
before := time.Date(2026, 8, 20, 19, 0, 0, 0, heroRevisionZone)
|
||||
during := time.Date(2026, 8, 20, 21, 0, 0, 0, heroRevisionZone)
|
||||
// Two readings within one rotation slot, so only the schedule can be the difference.
|
||||
if heroRotationSlot(before, heroRevisionZone) != heroRotationSlot(during, heroRevisionZone) {
|
||||
t.Fatal("test times straddle a rotation slot; the schedule is no longer the only variable")
|
||||
}
|
||||
if heroRevisionAt(policy, "user-1", before) == heroRevisionAt(policy, "user-1", during) {
|
||||
t.Fatal("hero revision did not move when a scheduled hero came into force")
|
||||
}
|
||||
empty := store.HeroPolicy{}
|
||||
if heroRevisionAt(policy, "user-1", before) != heroRevisionAt(empty, "user-1", before) {
|
||||
t.Fatal("a schedule that is not yet in force changed the revision; the launcher would repaint for nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionIsPerViewerForAPersonalSchedule(t *testing.T) {
|
||||
now := time.Date(2026, 8, 20, 21, 0, 0, 0, heroRevisionZone)
|
||||
policy := store.HeroPolicy{Schedules: []store.HeroSchedule{{
|
||||
ID: "s1", ItemID: "film-9", Enabled: true, UserID: "user-1",
|
||||
Frequency: "daily", StartTime: "20:00", EndTime: "22:00",
|
||||
Placements: []string{store.HeroPlacementHome},
|
||||
}}}
|
||||
if heroRevisionAt(policy, "user-1", now) == heroRevisionAt(policy, "user-2", now) {
|
||||
t.Fatal("one viewer's scheduled hero moved another viewer's revision")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeroRevisionMovesWithTheRotationSlot(t *testing.T) {
|
||||
policy := pinnedPolicy(store.HeroPlacementHome, "film-1")
|
||||
morning := time.Date(2026, 8, 20, 8, 0, 0, 0, heroRevisionZone)
|
||||
evening := time.Date(2026, 8, 20, 20, 0, 0, 0, heroRevisionZone)
|
||||
if heroRevisionAt(policy, "user-1", morning) == heroRevisionAt(policy, "user-1", evening) {
|
||||
t.Fatal("hero revision did not move across rotation slots; the day's draw would never be refetched")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user