Files
arr-tui/internal/ui/format_test.go
T
2026-10-20 21:47:50 +02:00

158 lines
5.1 KiB
Go

package ui
import (
"strings"
"testing"
"time"
"git.stinnesbeck.com/nils/arr-tui/internal/arr"
"git.stinnesbeck.com/nils/arr-tui/internal/radarr"
"git.stinnesbeck.com/nils/arr-tui/internal/sonarr"
)
func TestMovieLabel(t *testing.T) {
if got := movieLabel(radarr.Movie{Title: "Alien", Year: 1979}); got != "Alien (1979)" {
t.Errorf("got %q", got)
}
if got := movieLabel(radarr.Movie{ID: 3, Title: "Alien", Year: 1979}); !strings.Contains(got, "✓") {
t.Errorf("in-library marker missing: %q", got)
}
// tview color tags in titles must be escaped
if got := movieLabel(radarr.Movie{Title: "[red]x"}); strings.Contains(got, "[red]x") {
t.Errorf("title not escaped: %q", got)
}
}
func TestMovieDetails(t *testing.T) {
got := movieDetails(radarr.Movie{
ID: 1, Title: "Alien", Year: 1979, Runtime: 117, Genres: []string{"Horror", "Sci-Fi"},
Overview: "In space...", Ratings: radarr.Ratings{IMDB: &radarr.Rating{Value: 8.5}},
})
for _, want := range []string{"Alien (1979)", "★ 8.5", "1h57m", "Horror, Sci-Fi", "In library, not downloaded", "In space..."} {
if !strings.Contains(got, want) {
t.Errorf("details missing %q:\n%s", want, got)
}
}
}
func TestDefaultIndexes(t *testing.T) {
profiles := []arr.QualityProfile{{Name: "Any"}, {Name: "HD-1080p"}}
if profileIndex(profiles, "hd-1080p") != 1 || profileIndex(profiles, "nope") != 0 {
t.Error("profileIndex")
}
folders := []arr.RootFolder{{Path: "/a"}, {Path: "/movies/"}}
if folderIndex(folders, "/movies") != 1 || folderIndex(folders, "") != 0 {
t.Error("folderIndex")
}
}
func TestSeriesLabelAndDetails(t *testing.T) {
s := sonarr.Series{
Title: "Breaking Bad", Year: 2008, Network: "AMC", Status: "ended", Runtime: 47,
Genres: []string{"Crime"},
Ratings: sonarr.Rating{Value: 9.3},
Seasons: []sonarr.Season{{SeasonNumber: 0}, {SeasonNumber: 1}},
}
if got := seriesLabel(s); got != "Breaking Bad (2008)" {
t.Errorf("label = %q", got)
}
got := seriesDetails(s)
for _, want := range []string{"Breaking Bad (2008)", "★ 9.3", "1 season ·", "47 min", "Network: AMC", "Status: ended"} {
if !strings.Contains(got, want) {
t.Errorf("details missing %q:\n%s", want, got)
}
}
s.ID = 1
s.Statistics = sonarr.Statistics{EpisodeCount: 10, EpisodeFileCount: 4}
if got := seriesDetails(s); !strings.Contains(got, "4/10 episodes") {
t.Errorf("progress missing:\n%s", got)
}
s.Statistics.EpisodeFileCount = 10
if got := seriesDetails(s); !strings.Contains(got, "all episodes downloaded") {
t.Errorf("complete marker missing:\n%s", got)
}
}
func TestResultKeysAndWithID(t *testing.T) {
var r result = movieResult{Movie: radarr.Movie{TMDBID: 603, Title: "x"}}
if r.key() != "tmdb:603" || r.inLibrary() {
t.Fatalf("movie key/inLibrary: %q %v", r.key(), r.inLibrary())
}
if added := r.withID(5); !added.inLibrary() || r.inLibrary() {
t.Error("withID must return a flagged copy and leave the original alone")
}
r = seriesResult{Series: sonarr.Series{TVDBID: 81189}}
if r.key() != "tvdb:81189" {
t.Errorf("series key = %q", r.key())
}
}
func TestFormatSpeed(t *testing.T) {
tests := map[float64]string{0: "0 KB/s", 0.4: "0 KB/s", 512: "512 KB/s", 1536: "1.5 MB/s"}
for in, want := range tests {
if got := formatSpeed(in); got != want {
t.Errorf("formatSpeed(%v) = %q, want %q", in, got, want)
}
}
}
func TestProgressBar(t *testing.T) {
if got := progressBar(50, 10); got != "█████░░░░░ 50%" {
t.Errorf("got %q", got)
}
if got := progressBar(150, 4); got != "████ 100%" {
t.Errorf("clamp high: %q", got)
}
if got := progressBar(-5, 4); got != "░░░░ 0%" {
t.Errorf("clamp low: %q", got)
}
}
func TestFormatAge(t *testing.T) {
now := time.Unix(1_000_000, 0)
tests := map[int64]string{
0: "",
now.Unix() - 10: "just now",
now.Unix() - 5*60: "5m ago",
now.Unix() - 3*3600: "3h ago",
now.Unix() - 3*24*3600: "3d ago",
}
for in, want := range tests {
if got := formatAge(in, now); got != want {
t.Errorf("formatAge(%d) = %q, want %q", in, got, want)
}
}
}
func TestTruncate(t *testing.T) {
if got := truncate("short", 10); got != "short" {
t.Errorf("got %q", got)
}
if got := truncate("Aborted, cannot be completed", 10); got != "Aborted, …" {
t.Errorf("got %q", got)
}
if got := truncate("äöüäöü", 4); got != "äöü…" {
t.Errorf("rune handling: %q", got)
}
}
func TestArrStatusText(t *testing.T) {
tests := []struct {
name string
item arr.QueueItem
want string
}{
{"downloading", arr.QueueItem{TrackedDownloadState: "downloading", TrackedDownloadStatus: "ok"}, "Downloading"},
{"blocked", arr.QueueItem{TrackedDownloadState: "importBlocked", TrackedDownloadStatus: "warning"}, "[red]Import blocked[-]"},
{"warning", arr.QueueItem{TrackedDownloadState: "importPending", TrackedDownloadStatus: "warning"}, "[yellow]Import pending[-]"},
{"error", arr.QueueItem{Status: "failed", TrackedDownloadStatus: "error"}, "[red]Failed[-]"},
{"fallback to status", arr.QueueItem{Status: "queued"}, "Queued"},
}
for _, tc := range tests {
if got := arrStatusText(tc.item); got != tc.want {
t.Errorf("%s: got %q, want %q", tc.name, got, tc.want)
}
}
}