Files
memby/server/internal/api/radarr_detail_test.go
T
2026-08-19 06:57:59 +12:00

193 lines
6.9 KiB
Go

package api
import (
"testing"
"time"
"github.com/ponzischeme89/memby/server/internal/radarr"
)
func radarrDetailDay(year int, month time.Month, day int) time.Time {
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
}
func TestRadarrMovieID(t *testing.T) {
for _, testCase := range []struct {
raw string
want int
ok bool
}{
{raw: "radarr:412", want: 412, ok: true},
{raw: " radarr:412 ", want: 412, ok: true},
{raw: "412", want: 412, ok: true},
{raw: "", ok: false},
{raw: "radarr:", ok: false},
{raw: "radarr:0", ok: false},
{raw: "radarr:-3", ok: false},
{raw: "abc123", ok: false},
} {
id, ok := radarrMovieID(testCase.raw)
if ok != testCase.ok || id != testCase.want {
t.Fatalf("radarrMovieID(%q) = %d, %v; want %d, %v",
testCase.raw, id, ok, testCase.want, testCase.ok)
}
}
}
// A published digital date is named to the day; the schedule row's cinema-plus-a-month
// estimate is named only to the month, because it is a guess and a guess printed as
// "14 November" is one somebody plans an evening around.
func TestRadarrExpectedLabelPrecision(t *testing.T) {
now := radarrDetailDay(2026, time.August, 19)
published := radarrRelease{at: radarrDetailDay(2026, time.November, 14)}
estimated := radarrRelease{at: radarrDetailDay(2026, time.November, 14), estimated: true}
past := radarrRelease{at: radarrDetailDay(2026, time.March, 3)}
if got := radarrExpectedLabel(published, true, now, time.UTC); got != "Expected 14 November 2026" {
t.Fatalf("published: %q", got)
}
if got := radarrExpectedLabel(estimated, true, now, time.UTC); got != "Expected November 2026" {
t.Fatalf("estimated: %q", got)
}
if got := radarrExpectedLabel(past, true, now, time.UTC); got != "Released 3 March 2026" {
t.Fatalf("past: %q", got)
}
if got := radarrExpectedLabel(radarrRelease{}, false, now, time.UTC); got != "Release date not yet announced" {
t.Fatalf("unknown: %q", got)
}
}
func TestRadarrMovieStateReadsTheHouseholdsCopy(t *testing.T) {
now := radarrDetailDay(2026, time.August, 19)
future := radarrRelease{at: radarrDetailDay(2026, time.November, 14)}
past := radarrRelease{at: radarrDetailDay(2026, time.March, 3)}
for _, testCase := range []struct {
name string
movie radarr.Movie
release radarrRelease
hasRelease bool
want string
}{
{name: "coming soon", movie: radarr.Movie{Monitored: true}, release: future, hasRelease: true, want: "Coming Soon"},
{name: "out but not here", movie: radarr.Movie{Monitored: true}, release: past, hasRelease: true, want: "Not Yet Available"},
{name: "no date", movie: radarr.Movie{Monitored: true}, want: "Awaiting Release"},
{name: "unmonitored", movie: radarr.Movie{}, release: future, hasRelease: true, want: "Not Tracked"},
{
name: "downloaded but unscanned",
movie: radarr.Movie{Monitored: true, HasFile: true},
release: past,
hasRelease: true,
want: "Almost Ready",
},
} {
label, detail := radarrMovieState(testCase.movie, testCase.release, testCase.hasRelease, now)
if label != testCase.want {
t.Fatalf("%s: state = %q, want %q", testCase.name, label, testCase.want)
}
if detail == "" {
t.Fatalf("%s: a state with no explanation under it", testCase.name)
}
}
}
func TestBuildRadarrMovieDetail(t *testing.T) {
cinema := radarrDetailDay(2026, time.October, 2)
digital := radarrDetailDay(2026, time.November, 14)
movie := radarr.Movie{
ID: 412,
TMDBID: 9001,
Title: "The Quiet Coast",
OriginalTitle: "The Quiet Coast",
Overview: " A harbour town in winter. ",
Year: 2026,
Runtime: 118,
Genres: []string{"Drama", "Mystery"},
Studio: "Kōwhai Pictures",
Certification: "M",
Status: "announced",
Monitored: true,
YouTubeTrailerID: "abc123",
InCinemas: &cinema,
DigitalRelease: &digital,
Images: []radarr.Image{{CoverType: "poster"}, {CoverType: "fanart"}},
}
detail := buildRadarrMovieDetail(movie, radarrDetailDay(2026, time.August, 19), time.UTC)
if detail.ID != "radarr:412" {
t.Fatalf("id: %q", detail.ID)
}
if detail.Overview != "A harbour town in winter." {
t.Fatalf("overview: %q", detail.Overview)
}
// The same title twice is the common case and reads as a mistake when printed.
if detail.OriginalTitle != "" {
t.Fatalf("original title repeated: %q", detail.OriginalTitle)
}
if detail.ExpectedLabel != "Expected 14 November 2026" {
t.Fatalf("expected label: %q", detail.ExpectedLabel)
}
if detail.StateLabel != "Coming Soon" {
t.Fatalf("state: %q", detail.StateLabel)
}
if detail.LifecycleText != "ANNOUNCED" || detail.Lifecycle != "announced" {
t.Fatalf("lifecycle: %q/%q", detail.Lifecycle, detail.LifecycleText)
}
if !detail.TrailerAvailable {
t.Fatalf("a film with a trailer id must offer the action: %+v", detail)
}
if detail.AvailabilityNotice == "" {
t.Fatal("the page must say it cannot be watched here")
}
if len(detail.ReleaseDates) != 2 ||
detail.ReleaseDates[0].Kind != "cinema" || detail.ReleaseDates[0].Value != "2 October 2026" ||
detail.ReleaseDates[1].Kind != "digital" || detail.ReleaseDates[1].Value != "14 November 2026" {
t.Fatalf("release dates: %+v", detail.ReleaseDates)
}
// Never null on the wire: the television decodes these as lists.
if detail.Genres == nil || detail.Ratings == nil {
t.Fatalf("nil collections: %+v", detail)
}
}
// A film with nothing but a cinema date is the case the precision rule exists for: the
// schedule row places it a month later, and the page must not present that as a fact.
func TestBuildRadarrMovieDetailCinemaOnly(t *testing.T) {
cinema := radarrDetailDay(2026, time.October, 2)
detail := buildRadarrMovieDetail(
radarr.Movie{ID: 7, Title: "Harbour Lights", InCinemas: &cinema, Monitored: true, Status: "inCinemas"},
radarrDetailDay(2026, time.August, 19),
time.UTC,
)
if detail.ExpectedLabel != "Expected November 2026" {
t.Fatalf("expected label: %q", detail.ExpectedLabel)
}
if len(detail.ReleaseDates) != 1 || detail.ReleaseDates[0].Kind != "cinema" {
t.Fatalf("release dates: %+v", detail.ReleaseDates)
}
if detail.TrailerAvailable {
t.Fatal("a film with no trailer id must not offer the action")
}
}
func TestBuildRadarrMovieDetailUnannounced(t *testing.T) {
detail := buildRadarrMovieDetail(
radarr.Movie{ID: 9, Title: "Untitled", OriginalTitle: "Sans Titre", Monitored: true, Status: "tba"},
radarrDetailDay(2026, time.August, 19),
time.UTC,
)
if detail.ExpectedLabel != "Release date not yet announced" {
t.Fatalf("expected label: %q", detail.ExpectedLabel)
}
if detail.StateLabel != "Awaiting Release" {
t.Fatalf("state: %q", detail.StateLabel)
}
if len(detail.ReleaseDates) != 0 {
t.Fatalf("release dates: %+v", detail.ReleaseDates)
}
if detail.OriginalTitle != "Sans Titre" {
t.Fatalf("a differing original title is worth printing: %q", detail.OriginalTitle)
}
}