package arr import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "testing" "bellhop/internal/config" ) func TestRadarrSearch(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if got := r.Header.Get("X-Api-Key"); got != "secret" { t.Errorf("api key header = %q, want secret", got) } if r.URL.Path != "/api/v3/movie/lookup" { t.Errorf("path = %q", r.URL.Path) } if r.URL.Query().Get("term") != "dune" { t.Errorf("term = %q", r.URL.Query().Get("term")) } w.Header().Set("Content-Type", "application/json") _, _ = io.WriteString(w, `[ {"title":"Dune","year":2021,"tmdbId":438631,"titleSlug":"dune-2021"}, {"title":"Dune: Part Two","year":2024,"tmdbId":693134,"titleSlug":"dune-part-two-2024"} ]`) })) defer srv.Close() r := NewRadarr(&config.ArrConfig{URL: srv.URL, APIKey: "secret", QualityProfileID: 6, RootFolder: "/movies"}) results, err := r.Search(context.Background(), "dune") if err != nil { t.Fatalf("search: %v", err) } if len(results) != 2 { t.Fatalf("got %d results, want 2", len(results)) } if results[0].Title != "Dune" || results[0].Year != 2021 { t.Errorf("first result = %+v", results[0]) } } func TestRadarrAdd(t *testing.T) { var got map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost || r.URL.Path != "/api/v3/movie" { t.Errorf("unexpected %s %s", r.Method, r.URL.Path) } if err := json.NewDecoder(r.Body).Decode(&got); err != nil { t.Fatalf("decode body: %v", err) } w.WriteHeader(http.StatusCreated) _, _ = io.WriteString(w, `{"id":42}`) })) defer srv.Close() r := NewRadarr(&config.ArrConfig{URL: srv.URL, APIKey: "k", QualityProfileID: 6, RootFolder: "/movies"}) res := makeResult("Dune", 2021, `{"title":"Dune","year":2021,"tmdbId":438631,"titleSlug":"dune-2021"}`) if err := r.Add(context.Background(), res); err != nil { t.Fatalf("add: %v", err) } if got["qualityProfileId"].(float64) != 6 { t.Errorf("qualityProfileId = %v", got["qualityProfileId"]) } if got["rootFolderPath"] != "/movies" { t.Errorf("rootFolderPath = %v", got["rootFolderPath"]) } if got["monitored"] != true { t.Errorf("monitored = %v", got["monitored"]) } if got["tmdbId"].(float64) != 438631 { t.Errorf("tmdbId not preserved from lookup: %v", got["tmdbId"]) } opts := got["addOptions"].(map[string]any) if opts["searchForMovie"] != true { t.Errorf("addOptions.searchForMovie = %v", opts["searchForMovie"]) } } func TestRadarrAddError(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = io.WriteString(w, `{"error":"already exists"}`) })) defer srv.Close() r := NewRadarr(&config.ArrConfig{URL: srv.URL, APIKey: "k", QualityProfileID: 1, RootFolder: "/m"}) err := r.Add(context.Background(), makeResult("X", 0, `{"title":"X"}`)) if err == nil { t.Fatal("expected error, got nil") } }