package main import ( "maps" "os" "reflect" "testing" ) func TestCSVStorer_LoadSkipSet(t *testing.T) { tests := []struct { name string csv string want map[int]struct{} }{ {name: "empty", csv: "tmdb_id,rating,seen\n", want: map[int]struct{}{}}, {name: "single", csv: "tmdb_id,rating,seen\n123,8,true\n", want: map[int]struct{}{123: {}}}, {name: "multiple", csv: "tmdb_id,rating,seen\n1,,\n2,5,true\n", want: map[int]struct{}{1: {}, 2: {}}}, {name: "skips header", csv: "tmdb_id,rating,seen\n1,,\n", want: map[int]struct{}{1: {}}}, {name: "missing file", csv: "", want: map[int]struct{}{}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var path string if tt.csv == "" { path = "/nonexistent" } else { path = writeTempFile(t, tt.csv) } store := newCSVStorer() got, err := store.LoadSkipSet(path) if err != nil { t.Fatal(err) } if !maps.Equal(got, tt.want) { t.Errorf("got %v, want %v", got, tt.want) } }) } } func TestCSVStorer_ReadWriteRoundtrip(t *testing.T) { tests := []struct { name string entries []Entry }{ {name: "empty", entries: nil}, {name: "seen with rating", entries: []Entry{{ID: 1, Rating: 8, Seen: true}}}, {name: "unseen", entries: []Entry{{ID: 1}}}, {name: "seen no rating", entries: []Entry{{ID: 1, Seen: true}}}, {name: "multiple", entries: []Entry{ {ID: 1, Rating: 7, Seen: true}, {ID: 2, Seen: false}, {ID: 3, Rating: 9, Seen: true}, }}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { f := tempFilePath(t) store := newCSVStorer() if err := store.WriteEntries(f, tt.entries); err != nil { t.Fatal(err) } got, err := store.ReadEntries(f) if err != nil { t.Fatal(err) } if tt.entries == nil && got != nil { t.Fatalf("want nil, got %v", got) } if tt.entries == nil { return } if !reflect.DeepEqual(tt.entries, got) { t.Errorf("mismatch:\n want %+v\n got %+v", tt.entries, got) } }) } } func writeTempFile(t *testing.T, content string) string { t.Helper() f, err := os.CreateTemp("", "popback-test-*.csv") if err != nil { t.Fatal(err) } t.Cleanup(func() { os.Remove(f.Name()) }) if _, err := f.WriteString(content); err != nil { f.Close() t.Fatal(err) } f.Close() return f.Name() } func tempFilePath(t *testing.T) string { t.Helper() f, err := os.CreateTemp("", "popback-test-*.csv") if err != nil { t.Fatal(err) } f.Close() t.Cleanup(func() { os.Remove(f.Name()) }) return f.Name() }