81 lines
3.1 KiB
Go
81 lines
3.1 KiB
Go
package api
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func airedItem(id, name, availability string, airsAt time.Time) sonarrScheduleItem {
|
||
|
|
return sonarrScheduleItem{
|
||
|
|
ID: id,
|
||
|
|
Name: name,
|
||
|
|
MembyEpisodeCode: "S02E04",
|
||
|
|
MembyEpisodeTitle: "The Crossing",
|
||
|
|
MembyAirsAt: airsAt.Format(time.RFC3339),
|
||
|
|
MembyAvailability: availability,
|
||
|
|
MembyAvailabilityText: availability,
|
||
|
|
ImageTags: map[string]string{"Primary": "sonarr"},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBuildSonarrAlertsAnnouncesOnlyEpisodesNotYetInEmby(t *testing.T) {
|
||
|
|
location := time.FixedZone("NZST", 12*60*60)
|
||
|
|
now := time.Date(2026, 7, 27, 21, 30, 0, 0, location)
|
||
|
|
aired := now.Add(-30 * time.Minute)
|
||
|
|
|
||
|
|
alerts := buildSonarrAlerts([]sonarrScheduleItem{
|
||
|
|
airedItem("sonarr:7:42", "Northbound", "awaiting", aired),
|
||
|
|
airedItem("sonarr:8:43", "Grabbed Show", "downloading", aired.Add(-time.Minute)),
|
||
|
|
airedItem("sonarr:9:44", "Already Here", "available", aired),
|
||
|
|
airedItem("sonarr:10:45", "Not Watched", "unmonitored", aired),
|
||
|
|
airedItem("sonarr:11:46", "Later Tonight", "upcoming", now.Add(90*time.Minute)),
|
||
|
|
airedItem("sonarr:12:47", "This Morning", "awaiting", now.Add(-8*time.Hour)),
|
||
|
|
}, now, 3*time.Hour)
|
||
|
|
|
||
|
|
if len(alerts) != 2 {
|
||
|
|
t.Fatalf("expected 2 alerts, got %d: %+v", len(alerts), alerts)
|
||
|
|
}
|
||
|
|
first := alerts[0]
|
||
|
|
if first.ID != "sonarr:7:42:aired" || first.Kind != alertKindSonarrAired {
|
||
|
|
t.Fatalf("unexpected alert identity: %+v", first)
|
||
|
|
}
|
||
|
|
if first.Title != "Northbound" || first.ItemID != "sonarr:7:42" || first.ImageTag != "sonarr" {
|
||
|
|
t.Fatalf("unexpected alert payload: %+v", first)
|
||
|
|
}
|
||
|
|
if !strings.Contains(first.Message, "S02E04 — The Crossing aired at 9:00 PM") ||
|
||
|
|
!strings.Contains(first.Message, "in Emby soon") {
|
||
|
|
t.Fatalf("unexpected awaiting message: %q", first.Message)
|
||
|
|
}
|
||
|
|
if !strings.Contains(alerts[1].Message, "downloading now") {
|
||
|
|
t.Fatalf("unexpected downloading message: %q", alerts[1].Message)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBuildSonarrAlertsSortsNewestFirstAndCaps(t *testing.T) {
|
||
|
|
location := time.FixedZone("NZST", 12*60*60)
|
||
|
|
now := time.Date(2026, 7, 27, 22, 0, 0, 0, location)
|
||
|
|
|
||
|
|
items := []sonarrScheduleItem{
|
||
|
|
airedItem("sonarr:1:1", "Oldest", "awaiting", now.Add(-100*time.Minute)),
|
||
|
|
airedItem("sonarr:2:2", "Newest", "awaiting", now.Add(-5*time.Minute)),
|
||
|
|
airedItem("sonarr:3:3", "Middle", "awaiting", now.Add(-40*time.Minute)),
|
||
|
|
airedItem("sonarr:4:4", "Older", "awaiting", now.Add(-80*time.Minute)),
|
||
|
|
}
|
||
|
|
alerts := buildSonarrAlerts(items, now, 3*time.Hour)
|
||
|
|
if len(alerts) != maxAlerts {
|
||
|
|
t.Fatalf("expected the list capped at %d, got %d", maxAlerts, len(alerts))
|
||
|
|
}
|
||
|
|
if alerts[0].Title != "Newest" || alerts[1].Title != "Middle" || alerts[2].Title != "Older" {
|
||
|
|
t.Fatalf("alerts are not newest-first: %+v", alerts)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBuildSonarrAlertsDisabledByZeroWindow(t *testing.T) {
|
||
|
|
now := time.Date(2026, 7, 27, 22, 0, 0, 0, time.UTC)
|
||
|
|
items := []sonarrScheduleItem{airedItem("sonarr:1:1", "Northbound", "awaiting", now.Add(-time.Minute))}
|
||
|
|
if alerts := buildSonarrAlerts(items, now, 0); alerts != nil {
|
||
|
|
t.Fatalf("a zero window must disable alerts, got %+v", alerts)
|
||
|
|
}
|
||
|
|
}
|