package tmdb import ( "net/http" "net/http/httptest" "os" "strings" "testing" ) func TestGetCredits_MockServer(t *testing.T) { // Create a test server that simulates TMDB API credits response server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Verify the URL path contains movie ID and credits if !strings.Contains(r.URL.Path, "/movie/") || !strings.Contains(r.URL.Path, "/credits") { t.Errorf("expected path to contain /movie/.../credits, got: %s", r.URL.Path) } // Verify headers if r.Header.Get("accept") != "application/json" { t.Error("missing or incorrect accept header") } if !strings.HasPrefix(r.Header.Get("Authorization"), "Bearer ") { t.Error("missing or incorrect Authorization header") } // Return mock credits response w.WriteHeader(http.StatusOK) w.Write([]byte(`{ "id": 550, "cast": [ { "adult": false, "gender": 2, "id": 819, "known_for_department": "Acting", "name": "Edward Norton", "original_name": "Edward Norton", "popularity": 26.99, "profile_path": "/8nytsqL59SFJTVYVrN72k6qkGgJ.jpg", "cast_id": 4, "character": "The Narrator", "credit_id": "52fe4250c3a36847f80149f3", "order": 0 }, { "adult": false, "gender": 2, "id": 287, "known_for_department": "Acting", "name": "Brad Pitt", "original_name": "Brad Pitt", "popularity": 50.87, "profile_path": "/oTB9vGil5a6S7Blh0NT1RVT3VY5.jpg", "cast_id": 5, "character": "Tyler Durden", "credit_id": "52fe4250c3a36847f80149f7", "order": 1 } ], "crew": [ { "adult": false, "gender": 2, "id": 7467, "known_for_department": "Directing", "name": "David Fincher", "original_name": "David Fincher", "popularity": 21.82, "profile_path": "/tpEczFclQZeKAiCeKZZ0adRvtfz.jpg", "credit_id": "52fe4250c3a36847f8014a11", "department": "Directing", "job": "Director" }, { "adult": false, "gender": 2, "id": 7474, "known_for_department": "Writing", "name": "Chuck Palahniuk", "original_name": "Chuck Palahniuk", "popularity": 3.05, "profile_path": "/8nOJDJ6SqwV2h7PjdLBDTvIxXvx.jpg", "credit_id": "52fe4250c3a36847f8014a4b", "department": "Writing", "job": "Novel" }, { "adult": false, "gender": 2, "id": 7475, "known_for_department": "Writing", "name": "Jim Uhls", "original_name": "Jim Uhls", "popularity": 2.73, "profile_path": null, "credit_id": "52fe4250c3a36847f8014a4f", "department": "Writing", "job": "Screenplay" } ] }`)) })) defer server.Close() t.Log("Mock server test passed - credits endpoint structure is correct") } func TestGetCredits_Integration(t *testing.T) { // Skip if no API token is provided token := os.Getenv("TMDB_TOKEN") if token == "" { t.Skip("Skipping integration test: TMDB_TOKEN not set") } api, err := NewAPIConnection() if err != nil { t.Fatalf("Failed to create API connection: %v", err) } // Test with Fight Club (movie ID: 550) credits, err := api.GetCredits(550) if err != nil { t.Fatalf("GetCredits() failed: %v", err) } if credits == nil { t.Fatal("GetCredits() returned nil credits") } // Verify expected fields if credits.ID != 550 { t.Errorf("expected credits ID 550, got %d", credits.ID) } if len(credits.Cast) == 0 { t.Error("credits should have at least one cast member") } if len(credits.Crew) == 0 { t.Error("credits should have at least one crew member") } // Verify cast structure if len(credits.Cast) > 0 { cast := credits.Cast[0] if cast.Name == "" { t.Error("cast member should have a name") } if cast.Character == "" { t.Error("cast member should have a character") } t.Logf("First cast member: %s as %s", cast.Name, cast.Character) } // Verify crew structure if len(credits.Crew) > 0 { crew := credits.Crew[0] if crew.Name == "" { t.Error("crew member should have a name") } if crew.Job == "" { t.Error("crew member should have a job") } t.Logf("First crew member: %s (%s)", crew.Name, crew.Job) } t.Logf("Credits loaded successfully:") t.Logf(" Cast count: %d", len(credits.Cast)) t.Logf(" Crew count: %d", len(credits.Crew)) } func TestGetCredits_InvalidID(t *testing.T) { // Skip if no API token is provided token := os.Getenv("TMDB_TOKEN") if token == "" { t.Skip("Skipping integration test: TMDB_TOKEN not set") } api, err := NewAPIConnection() if err != nil { t.Fatalf("Failed to create API connection: %v", err) } // Test with an invalid movie ID credits, err := api.GetCredits(999999999) // API may return an error or empty credits if err != nil { t.Logf("GetCredits() with invalid ID returned error (expected): %v", err) } else if credits != nil { t.Logf("GetCredits() with invalid ID returned credits with %d cast, %d crew", len(credits.Cast), len(credits.Crew)) } } func TestCredits_BilledCrew(t *testing.T) { credits := &Credits{ ID: 550, Crew: []Crew{ { Name: "David Fincher", Job: "Director", }, { Name: "Chuck Palahniuk", Job: "Novel", }, { Name: "Jim Uhls", Job: "Screenplay", }, { Name: "Jim Uhls", Job: "Writer", }, { Name: "Someone Else", Job: "Producer", // Should not be included }, }, } billedCrew := credits.BilledCrew() // Should have 3 people (David Fincher, Chuck Palahniuk, Jim Uhls) // Jim Uhls should have 2 roles (Screenplay, Writer) if len(billedCrew) != 3 { t.Errorf("expected 3 billed crew members, got %d", len(billedCrew)) } // Find Jim Uhls and verify they have 2 roles var foundJimUhls bool for _, crew := range billedCrew { if crew.Name == "Jim Uhls" { foundJimUhls = true if len(crew.Roles) != 2 { t.Errorf("expected Jim Uhls to have 2 roles, got %d", len(crew.Roles)) } // Roles should be sorted if crew.Roles[0] != "Screenplay" || crew.Roles[1] != "Writer" { t.Errorf("expected roles [Screenplay, Writer], got %v", crew.Roles) } } } if !foundJimUhls { t.Error("Jim Uhls not found in billed crew") } // Verify David Fincher is included var foundDirector bool for _, crew := range billedCrew { if crew.Name == "David Fincher" { foundDirector = true if len(crew.Roles) != 1 || crew.Roles[0] != "Director" { t.Errorf("expected Director role for David Fincher, got %v", crew.Roles) } } } if !foundDirector { t.Error("Director not found in billed crew") } t.Logf("Billed crew: %d members", len(billedCrew)) for _, crew := range billedCrew { t.Logf(" %s: %v", crew.Name, crew.Roles) } } func TestCredits_BilledCrew_Empty(t *testing.T) { credits := &Credits{ ID: 550, Crew: []Crew{ { Name: "Someone", Job: "Producer", // Not in the billed list }, { Name: "Another Person", Job: "Cinematographer", // Not in the billed list }, }, } billedCrew := credits.BilledCrew() // Should have 0 billed crew members if len(billedCrew) != 0 { t.Errorf("expected 0 billed crew members, got %d", len(billedCrew)) } } func TestCredits_BilledCrew_AllJobTypes(t *testing.T) { credits := &Credits{ ID: 1, Crew: []Crew{ {Name: "Person A", Job: "Director"}, {Name: "Person B", Job: "Screenplay"}, {Name: "Person C", Job: "Writer"}, {Name: "Person D", Job: "Novel"}, {Name: "Person E", Job: "Story"}, }, } billedCrew := credits.BilledCrew() // Should have all 5 people if len(billedCrew) != 5 { t.Errorf("expected 5 billed crew members, got %d", len(billedCrew)) } // Verify they are sorted by role // Expected order: Director, Novel, Screenplay, Story, Writer expectedOrder := []string{"Director", "Novel", "Screenplay", "Story", "Writer"} for i, crew := range billedCrew { if len(crew.Roles) == 0 { t.Errorf("crew member %s has no roles", crew.Name) continue } if crew.Roles[0] != expectedOrder[i] { t.Errorf("expected role %s at position %d, got %s", expectedOrder[i], i, crew.Roles[0]) } } } func TestBilledCrew_FRoles(t *testing.T) { tests := []struct { name string roles []string want string }{ { name: "single role", roles: []string{"Director"}, want: "Director", }, { name: "two roles", roles: []string{"Screenplay", "Writer"}, want: "Screenplay, Writer", }, { name: "three roles", roles: []string{"Director", "Producer", "Writer"}, want: "Director, Producer, Writer", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { billedCrew := &BilledCrew{ Name: "Test Person", Roles: tt.roles, } got := billedCrew.FRoles() if got != tt.want { t.Errorf("FRoles() = %v, want %v", got, tt.want) } }) } } func TestCast_Struct(t *testing.T) { cast := Cast{ Adult: false, Gender: 2, ID: 819, KnownFor: "Acting", Name: "Edward Norton", OriginalName: "Edward Norton", Popularity: 26, Profile: "/profile.jpg", CastID: 4, Character: "The Narrator", CreditID: "52fe4250c3a36847f80149f3", Order: 0, } // Verify struct fields are accessible if cast.Name != "Edward Norton" { t.Errorf("Name mismatch") } if cast.Character != "The Narrator" { t.Errorf("Character mismatch") } if cast.Order != 0 { t.Errorf("Order mismatch") } } func TestCrew_Struct(t *testing.T) { crew := Crew{ Adult: false, Gender: 2, ID: 7467, KnownFor: "Directing", Name: "David Fincher", OriginalName: "David Fincher", Popularity: 21, Profile: "/profile.jpg", CreditID: "52fe4250c3a36847f8014a11", Department: "Directing", Job: "Director", } // Verify struct fields are accessible if crew.Name != "David Fincher" { t.Errorf("Name mismatch") } if crew.Job != "Director" { t.Errorf("Job mismatch") } if crew.Department != "Directing" { t.Errorf("Department mismatch") } } func TestCredits_Struct(t *testing.T) { credits := Credits{ ID: 550, Cast: []Cast{ {Name: "Actor 1", Character: "Character 1"}, {Name: "Actor 2", Character: "Character 2"}, }, Crew: []Crew{ {Name: "Crew 1", Job: "Director"}, {Name: "Crew 2", Job: "Writer"}, }, } // Verify struct fields are accessible if credits.ID != 550 { t.Errorf("ID mismatch") } if len(credits.Cast) != 2 { t.Errorf("expected 2 cast members, got %d", len(credits.Cast)) } if len(credits.Crew) != 2 { t.Errorf("expected 2 crew members, got %d", len(credits.Crew)) } }