package metadata_test import ( "context" "os" "testing" "time" "git.vakhrushev.me/av/jellybit/internal/metadata" ) // TestIntegration_TVMaze бьётся в реальный TVMaze (без ключа). Сетевой, по // умолчанию пропускается; включается флагом: // // JELLYBIT_LIVE=1 go test ./internal/metadata/ -run Integration -v func TestIntegration_TVMaze(t *testing.T) { if os.Getenv("JELLYBIT_LIVE") == "" { t.Skip("set JELLYBIT_LIVE=1 to run network tests") } c, err := metadata.NewTVMaze(metadata.TVMazeConfig{Timeout: 20 * time.Second}, nil) if err != nil { t.Fatalf("NewTVMaze: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() cands, err := c.Search(ctx, metadata.Query{Type: metadata.Series, Title: "Fargo", Year: 2014}) if err != nil { t.Fatalf("Search: %v", err) } if len(cands) == 0 { t.Fatal("ожидался хотя бы один кандидат") } top := cands[0] t.Logf("top: id=%s title=%q year=%d tag=%s/%s", top.ID, top.Title, top.Year, top.TagProvider, top.TagID) if top.TagProvider != "tvdb" || top.TagID == "" { t.Errorf("ожидался TVDB-тег из externals, got %s/%s", top.TagProvider, top.TagID) } counts, err := c.SeasonEpisodeCounts(ctx, top.ID) if err != nil { t.Fatalf("SeasonEpisodeCounts: %v", err) } t.Logf("season counts: %v", counts) if counts[1] == 0 { t.Error("ожидались серии в первом сезоне") } } // TestIntegration_TVDB бьётся в реальный TheTVDB v4. По умолчанию // пропускается; включается ключом: // // TVDB_API_KEY=... go test ./internal/metadata/ -run Integration -v // // Он же — единственный оракул на форму блока переводов в выдаче поиска: // docs/research/tvdb-search-translations.md записан по документации, живым // прогоном не подтверждён. Прогон под русской локалью печатает Title и // OriginalTitle: у movie 131155 «Нэчжа» ожидается в Title, а иероглифический // primary name — в OriginalTitle. Совпадение Title с OriginalTitle у иноязычной // записи означает, что перевод не доехал и предположение о форме неверно. func TestIntegration_TVDB(t *testing.T) { key := os.Getenv("TVDB_API_KEY") if key == "" { t.Skip("set TVDB_API_KEY to run") } c, err := metadata.NewTVDB(metadata.TVDBConfig{ APIKey: key, Timeout: 20 * time.Second, Language: "ru", }, nil) if err != nil { t.Fatalf("NewTVDB: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() cands, err := c.Search(ctx, metadata.Query{Type: metadata.Series, Title: "Fargo", Year: 2014}) if err != nil { t.Fatalf("Search: %v", err) } t.Logf("candidates (%d):", len(cands)) for i, cd := range cands { if i >= 5 { break } t.Logf(" id=%s title=%q original=%q year=%d", cd.ID, cd.Title, cd.OriginalTitle, cd.Year) } if len(cands) == 0 { t.Fatal("ожидался хотя бы один кандидат для Fargo") } if cands[0].OriginalTitle == "" { t.Error("OriginalTitle пуст: primary name в кандидат не доехал") } if cands[0].Title == "" { t.Error("Title пуст: фолбэк на primary name не сработал") } // Иноязычная запись — тот случай, ради которого задача заводилась. // Расхождение Title и OriginalTitle подтверждает форму блока переводов. film, err := c.Search(ctx, metadata.Query{Type: metadata.Movie, Title: "Ne Zha", Year: 2019}) if err != nil { t.Fatalf("Search(Ne Zha): %v", err) } for i, cd := range film { if i >= 5 { break } t.Logf(" ne zha: id=%s title=%q original=%q year=%d", cd.ID, cd.Title, cd.OriginalTitle, cd.Year) } // Берём первого с непустым id и тянем число серий по сезонам. id := cands[0].ID counts, err := c.SeasonEpisodeCounts(ctx, id) if err != nil { t.Fatalf("SeasonEpisodeCounts(%s): %v", id, err) } t.Logf("season episode counts for id=%s: %v", id, counts) if len(counts) == 0 { t.Error("ожидались данные о числе серий по сезонам") } }