Files
arrman/cmd/tv_test.go
T
2026-03-12 22:13:57 +00:00

239 lines
5.4 KiB
Go

package cmd
import (
"bytes"
"io"
"os"
"strings"
"testing"
"gitea.dcglab.co.uk/steve/arrman/sonarr"
)
type mockSonarr struct {
series []sonarr.Series
added *sonarr.Series
profiles []sonarr.QualityProfile
folders []sonarr.RootFolder
lookupFn func(term string) ([]sonarr.Series, error)
addErr error
}
func (m *mockSonarr) List() ([]sonarr.Series, error) {
return m.series, nil
}
func (m *mockSonarr) Lookup(term string) ([]sonarr.Series, error) {
if m.lookupFn != nil {
return m.lookupFn(term)
}
return m.series, nil
}
func (m *mockSonarr) Get(id int) (*sonarr.Series, error) {
for _, s := range m.series {
if s.ID == id {
return &s, nil
}
}
return nil, nil
}
func (m *mockSonarr) QualityProfiles() ([]sonarr.QualityProfile, error) {
return m.profiles, nil
}
func (m *mockSonarr) RootFolders() ([]sonarr.RootFolder, error) {
return m.folders, nil
}
func (m *mockSonarr) Add(s sonarr.Series) (*sonarr.Series, error) {
if m.addErr != nil {
return nil, m.addErr
}
m.added = &s
s.ID = 1
return &s, nil
}
func captureOutput(fn func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
fn()
w.Close()
os.Stdout = old
var buf bytes.Buffer
io.Copy(&buf, r)
return buf.String()
}
func TestTVListEmpty(t *testing.T) {
mock := &mockSonarr{}
out := captureOutput(func() {
TVList(mock, "", false, false)
})
if !strings.Contains(out, "No series found") {
t.Errorf("expected 'No series found', got: %s", out)
}
}
func TestTVListWithItems(t *testing.T) {
mock := &mockSonarr{
series: []sonarr.Series{
{
Title: "Breaking Bad",
Year: 2008,
Status: "ended",
Statistics: &sonarr.Statistics{
EpisodeFileCount: 62,
EpisodeCount: 62,
},
},
},
}
out := captureOutput(func() {
TVList(mock, "", false, false)
})
if !strings.Contains(out, "Breaking Bad (2008)") {
t.Errorf("expected series in output, got: %s", out)
}
if !strings.Contains(out, "62/62") {
t.Errorf("expected episode count, got: %s", out)
}
}
func TestTVAddByID(t *testing.T) {
mock := &mockSonarr{
lookupFn: func(term string) ([]sonarr.Series, error) {
if term == "tvdb:448176" {
return []sonarr.Series{{Title: "Test Show", Year: 2024, TvdbID: 448176}}, nil
}
return nil, nil
},
}
out := captureOutput(func() {
err := TVAdd(mock, []string{"448176", "--profile", "1", "--rootfolder", "/tv"}, false)
if err != nil {
t.Fatal(err)
}
})
if !strings.Contains(out, "Added: Test Show") {
t.Errorf("expected confirmation, got: %s", out)
}
if mock.added == nil {
t.Fatal("expected Add to be called")
}
if mock.added.QualityProfileID != 1 {
t.Errorf("expected profile 1, got %d", mock.added.QualityProfileID)
}
if mock.added.RootFolderPath != "/tv" {
t.Errorf("expected rootfolder /tv, got %s", mock.added.RootFolderPath)
}
}
func TestTVAddMissingFlags(t *testing.T) {
mock := &mockSonarr{}
err := TVAdd(mock, []string{"448176"}, false)
if err == nil {
t.Fatal("expected error for missing flags")
}
}
func TestTVAddNoResult(t *testing.T) {
mock := &mockSonarr{
lookupFn: func(term string) ([]sonarr.Series, error) {
return nil, nil
},
}
err := TVAdd(mock, []string{"999999", "--profile", "1", "--rootfolder", "/tv"}, false)
if err == nil {
t.Fatal("expected error")
}
if !strings.Contains(err.Error(), "No series found with TVDB ID 999999") {
t.Errorf("unexpected error: %v", err)
}
}
func TestTVAddByTitle(t *testing.T) {
mock := &mockSonarr{
lookupFn: func(term string) ([]sonarr.Series, error) {
return []sonarr.Series{
{Title: "Breaking Bad", Year: 2008, TvdbID: 81189},
}, nil
},
}
out := captureOutput(func() {
err := TVAdd(mock, []string{"Breaking Bad", "--profile", "1", "--rootfolder", "/tv"}, false)
if err != nil {
t.Fatal(err)
}
})
if !strings.Contains(out, "Added: Breaking Bad") {
t.Errorf("expected confirmation, got: %s", out)
}
}
func TestTVAddFuzzyMatch(t *testing.T) {
mock := &mockSonarr{
lookupFn: func(term string) ([]sonarr.Series, error) {
return []sonarr.Series{
{Title: "Breaking Bad", Year: 2008, TvdbID: 81189},
{Title: "Better Call Saul", Year: 2015, TvdbID: 273181},
}, nil
},
}
out := captureOutput(func() {
err := TVAdd(mock, []string{"Breaking", "Bad", "--profile", "1", "--rootfolder", "/tv"}, false)
if err != nil {
t.Fatal(err)
}
})
if !strings.Contains(out, "Added: Breaking Bad") {
t.Errorf("expected fuzzy match to Breaking Bad, got: %s", out)
}
}
func TestTVAddNoMatch(t *testing.T) {
mock := &mockSonarr{
lookupFn: func(term string) ([]sonarr.Series, error) {
return []sonarr.Series{
{Title: "Something Completely Different", Year: 2020, TvdbID: 99999},
}, nil
},
}
err := TVAdd(mock, []string{"xyz", "--profile", "1", "--rootfolder", "/tv"}, false)
if err == nil {
t.Fatal("expected error for no match")
}
}
func TestTVProfiles(t *testing.T) {
mock := &mockSonarr{
profiles: []sonarr.QualityProfile{
{ID: 1, Name: "HD-1080p"},
{ID: 4, Name: "Ultra-HD"},
},
}
out := captureOutput(func() {
TVProfiles(mock, false)
})
if !strings.Contains(out, "ID: 1 — Name: HD-1080p") {
t.Errorf("expected profile output, got: %s", out)
}
}
func TestTVRootFolders(t *testing.T) {
mock := &mockSonarr{
folders: []sonarr.RootFolder{
{ID: 1, Path: "/tv", FreeSpace: 107374182400},
},
}
out := captureOutput(func() {
TVRootFolders(mock, false)
})
if !strings.Contains(out, "Path: /tv") {
t.Errorf("expected folder output, got: %s", out)
}
}