Something went wrong. Try again.
let's backfill your watched movies on popfeed
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282package main
import ( "context" "fmt" "slices" "testing"
tea "github.com/charmbracelet/bubbletea")
func TestHandleAction(t *testing.T) { tests := []struct { name string movies []Movie pos int results map[int]Entry key string wantOK bool wantEntry Entry }{ { name: "skip with n", movies: []Movie{{ID: 1, Title: "Alpha"}}, pos: 0, results: map[int]Entry{}, key: "n", wantOK: true, wantEntry: Entry{ID: 1, Seen: false}, }, { name: "seen with s", movies: []Movie{{ID: 2, Title: "Beta"}}, pos: 0, results: map[int]Entry{}, key: "s", wantOK: true, wantEntry: Entry{ID: 2, Seen: true}, }, { name: "rate with 8", movies: []Movie{{ID: 3, Title: "Gamma"}}, pos: 0, results: map[int]Entry{}, key: "8", wantOK: true, wantEntry: Entry{ID: 3, Rating: 8, Seen: true}, }, { name: "rate 1", movies: []Movie{{ID: 4, Title: "Delta"}}, pos: 0, results: map[int]Entry{}, key: "1", wantOK: true, wantEntry: Entry{ID: 4, Rating: 1, Seen: true}, }, { name: "rate 9", movies: []Movie{{ID: 5, Title: "Epsilon"}}, pos: 0, results: map[int]Entry{}, key: "9", wantOK: true, wantEntry: Entry{ID: 5, Rating: 9, Seen: true}, }, { name: "zero maps to rating 10", movies: []Movie{{ID: 6, Title: "Zero"}}, pos: 0, results: map[int]Entry{}, key: "0", wantOK: true, wantEntry: Entry{ID: 6, Rating: 10, Seen: true}, }, { name: "invalid key returns false", movies: []Movie{{ID: 6, Title: "Zeta"}}, pos: 0, results: map[int]Entry{}, key: "x", wantOK: false, }, { name: "empty key not accepted", movies: []Movie{{ID: 7, Title: "Theta"}}, pos: 0, results: map[int]Entry{}, key: "", wantOK: false, }, { name: "overwrite existing result", movies: []Movie{{ID: 9, Title: "Iota"}}, pos: 0, results: map[int]Entry{9: {ID: 9, Seen: false}}, key: "s", wantOK: true, wantEntry: Entry{ID: 9, Seen: true}, }, { name: "multiple movies, second position", movies: []Movie{{ID: 10, Title: "Kappa"}, {ID: 11, Title: "Lambda"}}, pos: 1, results: map[int]Entry{}, key: "5", wantOK: true, wantEntry: Entry{ID: 11, Rating: 5, Seen: true}, }, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { m := tuiModel{ movies: tt.movies, pos: tt.pos, results: tt.results, } got, ok := m.handleAction(tt.key) if ok != tt.wantOK { t.Fatalf("handleAction(%q) = %v, wantOK %v", tt.key, ok, tt.wantOK) } if !ok { return } gotEntry, exists := got.results[tt.movies[tt.pos].ID] if !exists { t.Fatal("result not stored for movie id") } if gotEntry != tt.wantEntry { t.Errorf("result = %+v, want %+v", gotEntry, tt.wantEntry) } }) }}
func TestAdvance(t *testing.T) { tests := []struct { name string model tuiModel wantPos int wantQuit bool wantFetch bool }{ { name: "advances within movies", model: tuiModel{ movies: []Movie{{ID: 1}, {ID: 2}, {ID: 3}}, pos: 0, exhausted: true, }, wantPos: 1, }, { name: "hits end exhausted quits", model: tuiModel{ movies: []Movie{{ID: 1}}, pos: 0, exhausted: true, }, wantPos: 1, wantQuit: true, }, { name: "hits end while fetching waits", model: tuiModel{ movies: []Movie{{ID: 1}}, pos: 0, fetching: true, }, wantPos: 1, }, { name: "exhausted skips pre-fetch", model: tuiModel{ movies: []Movie{{ID: 1}, {ID: 2}}, pos: 0, exhausted: true, }, wantPos: 1, }, { name: "fetching skips pre-fetch", model: tuiModel{ movies: []Movie{{ID: 1}, {ID: 2}}, pos: 0, fetching: true, }, wantPos: 1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { nm, cmd := tt.model.advanceCmd() if nm.pos != tt.wantPos { t.Errorf("pos = %d, want %d", nm.pos, tt.wantPos) } gotQuit := cmd != nil && fmt.Sprintf("%p", cmd) == fmt.Sprintf("%p", tea.Quit) if gotQuit != tt.wantQuit { t.Errorf("quit = %v, want %v", gotQuit, tt.wantQuit) } gotFetch := cmd != nil && !gotQuit if gotFetch != tt.wantFetch { t.Errorf("fetch cmd = %v, want %v", gotFetch, tt.wantFetch) } }) }}
func TestRunViewed(t *testing.T) { tests := []struct { name string skipSet map[int]struct{} skipErr error tuiResults map[int]Entry tuiErr error tuiQuit bool existing []Entry wantErr bool wantWrite []Entry }{ { name: "success with ratings", skipSet: map[int]struct{}{}, tuiResults: map[int]Entry{1: {ID: 1, Rating: 8, Seen: true}, 2: {ID: 2, Rating: 5, Seen: true}}, tuiQuit: true, wantWrite: []Entry{ {ID: 1, Rating: 8, Seen: true}, {ID: 2, Rating: 5, Seen: true}, }, }, { name: "no movies fetched", tuiResults: nil, tuiQuit: true, wantWrite: nil, }, { name: "load skip set error", skipErr: fmt.Errorf("file error"), wantErr: true, }, { name: "tui error", tuiErr: fmt.Errorf("tui error"), tuiResults: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { store := &mockStorer{ entries: tt.existing, skipSet: tt.skipSet, skipErr: tt.skipErr, } tui := &mockTUIRunner{ results: tt.tuiResults, err: tt.tuiErr, quit: tt.tuiQuit, } err := runViewed(context.Background(), tmdbClient{}, store, tui, "test.csv") if (err != nil) != tt.wantErr { t.Fatalf("runViewed() = %v, wantErr %v", err, tt.wantErr) } if !slices.Equal(store.WrittenEntries, tt.wantWrite) { t.Errorf("written entries = %+v, want %+v", store.WrittenEntries, tt.wantWrite) } }) }}
type mockTUIRunner struct { results map[int]Entry err error quit bool}
func (m *mockTUIRunner) Run(_ *tmdbMovieStream, _ context.Context) (map[int]Entry, bool, error) { return m.results, m.quit, m.err}