package web import ( "testing" "time" "git.zio.sh/cs2/simpleadmin-web/internal/store" ) func TestPenaltyNotification(t *testing.T) { for _, c := range []struct { e store.PenaltyEvent typ, title, body, url string }{ {store.PenaltyEvent{ID: 56, Kind: "ban", Name: "teabag_tim", SteamID: "76561198012345622", AdminSteamID: "76561198000000001", AdminName: "mossy", Reason: "Toxicity after warnings", Duration: 4320}, "ban", "Ban added: teabag_tim", "mossy · 3 days · Toxicity after warnings", "/#bans?q=76561198012345622"}, {store.PenaltyEvent{ID: 7, Kind: "comm", Type: "GAG", Name: "noodlearm", SteamID: "765", AdminName: "Kestrel", Reason: "Spam", Duration: 30}, "gag", "Gag added: noodlearm", "Kestrel · 30 min · Spam", "/#comms?q=765"}, {store.PenaltyEvent{ID: 8, Kind: "comm", Type: "SILENCE", SteamID: "765", AdminName: "Console", Duration: 0}, "silence", "Silence added: 765", "Console · Permanent", "/#comms?q=765"}, {store.PenaltyEvent{ID: 3, Kind: "unban", Name: "mika", SteamID: "765", AdminName: "astra", Reason: "Appeal accepted"}, "unban", "Ban lifted: mika", "astra · Appeal accepted", "/#bans?q=765"}, {store.PenaltyEvent{ID: 4, Kind: "unmute", Type: "MUTE", Name: "pip", SteamID: "765"}, "unmute", "Mute lifted: pip", "Console", "/#comms?q=765"}, } { n, ok := penaltyNotification(c.e) if !ok || n.Type != c.typ || n.Title != c.title || n.Body != c.body || n.URL != c.url { t.Errorf("%+v:\n got %v %q %q %q %q", c.e, ok, n.Type, n.Title, n.Body, n.URL) } if n.Actor != c.e.AdminSteamID || len(n.Actions) != 1 || n.Actions[0].Title != "View player" { t.Errorf("%+v: actor %q actions %v", c.e, n.Actor, n.Actions) } } if _, ok := penaltyNotification(store.PenaltyEvent{Kind: "comm", Type: "OTHER"}); ok { t.Error("unknown comm type should be skipped") } } func TestQuietHours(t *testing.T) { at := func(h, m int) time.Time { return time.Date(2026, 10, 3, h, m, 0, 0, time.UTC) } night := store.PushPrefs{QuietEnabled: true, QuietStart: 23 * 60, QuietEnd: 8 * 60, Timezone: "UTC"} day := store.PushPrefs{QuietEnabled: true, QuietStart: 9 * 60, QuietEnd: 17 * 60, Timezone: "UTC"} for _, c := range []struct { p store.PushPrefs t time.Time want bool }{ {night, at(23, 0), true}, {night, at(3, 0), true}, {night, at(7, 59), true}, {night, at(8, 0), false}, {night, at(12, 0), false}, {day, at(9, 0), true}, {day, at(17, 0), false}, {day, at(8, 59), false}, {store.PushPrefs{QuietEnabled: false, QuietStart: 0, QuietEnd: 1439}, at(12, 0), false}, {store.PushPrefs{QuietEnabled: true, QuietStart: 600, QuietEnd: 600}, at(10, 0), false}, // 23:30 UTC is 00:30 in London (BST), inside 00:00-06:00 there. {store.PushPrefs{QuietEnabled: true, QuietStart: 0, QuietEnd: 360, Timezone: "Europe/London"}, at(23, 30), true}, } { if got := inQuietHours(c.p, c.t); got != c.want { t.Errorf("%+v at %s: got %v", c.p, c.t.Format("15:04"), got) } } } func TestHHMM(t *testing.T) { for _, m := range []int{0, 59, 60, 480, 1380, 1439} { if got, ok := parseHHMM(hhmm(m)); !ok || got != m { t.Errorf("%d -> %s -> %d", m, hhmm(m), got) } } for _, s := range []string{"24:00", "7:00", "12:60", "", "12:00:00"} { if _, ok := parseHHMM(s); ok { t.Errorf("%q parsed", s) } } }