package importer import ( "fmt" "reflect" "testing" "github.com/cdnutter/canon/internal/providers" ) func TestParseText(t *testing.T) { got, err := Parse([]byte("1. Heat (1995)\n2) 2001: A Space Odyssey\n\n4 - Alien [1979]\n"), "list.txt") if err != nil { t.Fatal(err) } want := []Row{{Place: 1, Title: "Heat", Year: "1995"}, {Place: 2, Title: "2001: A Space Odyssey"}, {Place: 4, Title: "Alien", Year: "1979"}} if !reflect.DeepEqual(got, want) { t.Fatalf("got %+v", got) } // Not every line is numbered, so nothing is stripped; line numbers are // the places, and a blank line leaves one empty. got, _ = Parse([]byte("2001: A Space Odyssey\nHeat\n\n1917\n"), "x.txt") if got[0].Title != "2001: A Space Odyssey" || got[2].Title != "1917" || got[2].Place != 4 { t.Fatalf("got %+v", got) } // Numbers win over line numbers when every line has one. got, _ = Parse([]byte("1. Super Mario Sunshine\n38. Super Mario World\n"), "games.txt") if got[0].Place != 1 || got[1].Place != 38 || got[1].Title != "Super Mario World" { t.Fatalf("got %+v", got) } // A repeated number takes the next free place, keeping the file's order. got, _ = Parse([]byte("3. A\n3. B\n1. C\n"), "x.txt") if fmt.Sprint(got) != fmt.Sprint([]Row{{Place: 1, Title: "C"}, {Place: 3, Title: "A"}, {Place: 4, Title: "B"}}) { t.Fatalf("got %+v", got) } } func TestParseCSV(t *testing.T) { csv := "\xef\xbb\xbfRank,Title,Year,Director,Why\n2,Alien,1979,Ridley Scott,\"Tense, perfect\"\n1,Heat,1995,Michael Mann,\n" got, err := Parse([]byte(csv), "films.csv") if err != nil { t.Fatal(err) } want := []Row{ {Place: 1, Title: "Heat", Year: "1995", Subtitle: "Michael Mann"}, {Place: 2, Title: "Alien", Year: "1979", Subtitle: "Ridley Scott", Note: "Tense, perfect"}, } if !reflect.DeepEqual(got, want) { t.Fatalf("got %+v", got) } // Canon's own export: one column, no header, a blank line for an empty // place. got, _ = Parse([]byte("\xef\xbb\xbfHeat\r\n\r\n\"Crouching Tiger, Hidden Dragon\"\r\n"), "films.csv") if len(got) != 2 || got[1].Title != "Crouching Tiger, Hidden Dragon" || got[1].Place != 3 { t.Fatalf("got %+v", got) } // With a header, the first row after it is #1. got, _ = Parse([]byte("Title\nHeat\n\nAlien\n"), "x.csv") if got[0].Place != 1 || got[1].Place != 3 { t.Fatalf("got %+v", got) } // Headerless rank,title,year. got, _ = Parse([]byte("1,Heat,1995\n5,Alien,1979\n"), "x.csv") if got[1] != (Row{Place: 5, Title: "Alien", Year: "1979"}) { t.Fatalf("got %+v", got) } if _, err := Parse([]byte("\n \n"), "x.txt"); err != ErrEmpty { t.Fatalf("empty file: %v", err) } } func res(title, year, sub string) providers.Result { return providers.Result{Provider: "t", ProviderID: title + year + sub, Title: title, Year: year, Subtitle: sub} } func TestRank(t *testing.T) { cases := []struct { name string row Row category string results []providers.Result status string top string }{ {"exact and alone", Row{Title: "Alien"}, "movie", []providers.Result{res("Alien", "1979", ""), res("Aliens", "1986", "")}, Matched, "Alien1979"}, {"remake, no year", Row{Title: "Heat"}, "movie", []providers.Result{res("Heat", "1995", ""), res("Heat", "1986", "")}, Review, "Heat1995"}, {"remake, year given", Row{Title: "Heat", Year: "1986"}, "movie", []providers.Result{res("Heat", "1995", ""), res("Heat", "1986", "")}, Matched, "Heat1986"}, {"loose title", Row{Title: "Star Wars"}, "movie", []providers.Result{res("Star Wars: A New Hope", "1977", "")}, Review, "Star Wars: A New Hope1977"}, {"punctuation and accents", Row{Title: "amelie"}, "movie", []providers.Result{res("Amélie", "2001", "")}, Matched, "Amélie2001"}, {"wikipedia qualifier", Row{Title: "The Matrix", Year: "1999"}, "custom", []providers.Result{res("The Matrix (1999 film)", "1999", "")}, Matched, "The Matrix (1999 film)1999"}, {"artist - title", Row{Title: "Radiohead - Creep"}, "song", []providers.Result{res("Creep", "1992", "TLC"), res("Creep", "1992", "Radiohead")}, Matched, "Creep1992Radiohead"}, {"title, no artist", Row{Title: "Creep"}, "song", []providers.Result{res("Creep", "1992", "TLC"), res("Creep", "1992", "Radiohead")}, Review, "Creep1992TLC"}, {"same album twice", Row{Title: "OK Computer"}, "album", []providers.Result{res("OK Computer", "1997", "Radiohead"), res("OK Computer", "1997", "Radiohead")}, Matched, "OK Computer1997Radiohead"}, {"wrong year", Row{Title: "Alien", Year: "1990"}, "movie", []providers.Result{res("Alien", "1979", "")}, Review, "Alien1979"}, {"exact beats a bracketed version", Row{Title: "Radiohead - Creep"}, "song", []providers.Result{res("Creep (Acoustic)", "", "Radiohead"), res("Creep", "", "Radiohead")}, Matched, "CreepRadiohead"}, {"only bracketed versions", Row{Title: "Hey Jude"}, "song", []providers.Result{res("Hey Jude (Remastered 2015)", "", "The Beatles")}, Matched, "Hey Jude (Remastered 2015)The Beatles"}, {"year beats no year", Row{Title: "The Matrix", Year: "1999"}, "custom", []providers.Result{res("The Matrix", "", "American media franchise"), res("The Matrix", "1999", "Film by the Wachowskis")}, Matched, "The Matrix1999Film by the Wachowskis"}, {"artist confirmed beats a literal title", Row{Title: "Radiohead - Creep"}, "song", []providers.Result{res("Radiohead - Creep", "", "Klangsberg"), res("Creep", "", "Radiohead")}, Matched, "CreepRadiohead"}, {"custom needs confirming", Row{Title: "Heat"}, "custom", []providers.Result{res("Heat", "", "Type of energy transfer")}, Review, "HeatType of energy transfer"}, {"nothing", Row{Title: "zzz"}, "movie", nil, None, ""}, } for _, c := range cases { status, scored := Rank(c.row, c.category, c.results) if status != c.status { t.Errorf("%s: status %s, want %s", c.name, status, c.status) } if len(scored) > 0 && scored[0].ProviderID != c.top { t.Errorf("%s: top %s, want %s", c.name, scored[0].ProviderID, c.top) } } }