Add library view and series drill-down (M8)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 19:31:12 +02:00
co-authored by Claude Sonnet 5.5
parent a469eca871
commit 61373bbe45
11 changed files with 1080 additions and 18 deletions
+92
View File
@@ -0,0 +1,92 @@
package ui
import (
"strings"
"testing"
"git.stinnesbeck.com/nils/arr-tui/internal/radarr"
"git.stinnesbeck.com/nils/arr-tui/internal/sonarr"
)
func TestMovieItemStatus(t *testing.T) {
tests := []struct {
name string
m radarr.Movie
want string
have, miss bool
}{
{"missing", radarr.Movie{ID: 1, Title: "A", Monitored: true, IsAvailable: true}, "missing", false, true},
{"unreleased", radarr.Movie{ID: 2, Title: "B", Monitored: true}, "not released", false, false},
{"unmonitored", radarr.Movie{ID: 3, Title: "C", IsAvailable: true}, "unmonitored", false, false},
{"downloaded", radarr.Movie{ID: 4, Title: "D", Monitored: true, HasFile: true, IsAvailable: true}, "✓", true, false},
}
for _, tc := range tests {
it := newMovieItem(tc.m)
if !strings.Contains(it.status, tc.want) || it.have != tc.have || it.missing != tc.miss {
t.Errorf("%s: status=%q have=%v missing=%v", tc.name, it.status, it.have, it.missing)
}
}
}
func TestSeriesItemStatus(t *testing.T) {
s := sonarr.Series{ID: 1, Title: "S", Year: 2008, Monitored: true,
Statistics: sonarr.Statistics{EpisodeFileCount: 3, EpisodeCount: 10}}
it := newSeriesItem(s)
if !it.have || !it.missing || !strings.Contains(it.status, "3/10") || it.label != "S (2008)" {
t.Errorf("item = %+v", it)
}
s.Statistics.EpisodeFileCount = 10
if it := newSeriesItem(s); it.missing || !strings.Contains(it.status, "green") {
t.Errorf("complete series: %+v", it)
}
}
func TestFilterItems(t *testing.T) {
items := []libItem{
{id: 1, title: "Zulu", monitored: true, missing: true},
{id: 2, title: "alpha", monitored: true, have: true},
{id: 3, title: "Beta"},
}
ids := func(f int, text string) string {
var s string
for _, it := range filterItems(items, f, text) {
s += itoa(it.id)
}
return s
}
for _, tc := range []struct {
filter int
text string
want string
}{
{0, "", "231"}, // sorted case-insensitively by title
{1, "", "1"},
{2, "", "2"},
{3, "", "21"},
{4, "", "3"},
{0, " ALP ", "2"},
{1, "alpha", ""},
} {
if got := ids(tc.filter, tc.text); got != tc.want {
t.Errorf("filter %d %q = %q, want %q", tc.filter, tc.text, got, tc.want)
}
}
}
func TestEpisodeStatus(t *testing.T) {
const today = "2026-06-01"
for _, tc := range []struct {
e sonarr.Episode
want string
}{
{sonarr.Episode{HasFile: true}, "downloaded"},
{sonarr.Episode{AirDate: "2027-01-01", Monitored: true}, "unaired"},
{sonarr.Episode{Monitored: true}, "unaired"},
{sonarr.Episode{AirDate: "2020-01-01"}, "unmonitored"},
{sonarr.Episode{AirDate: "2020-01-01", Monitored: true}, "missing"},
} {
if got := episodeStatus(tc.e, today); !strings.Contains(got, tc.want) {
t.Errorf("%+v = %q, want %q", tc.e, got, tc.want)
}
}
}