package prowlarr import ( "context" "errors" "net/http" "net/http/httptest" "testing" "git.fabledsword.com/bvandeusen/minstrel/internal/indexer" ) const sampleResults = `[ {"title": "Radiohead - In Rainbows (2007) [FLAC]", "infoHash": "AABBCCDDEEFF00112233445566778899AABBCCDD", "downloadUrl": "http://prowlarr/1/download?link=x", "size": 400000000, "seeders": 30, "leechers": 4, "indexer": "RED", "publishDate": "2026-10-01T12:00:00Z", "categories": [{"id": 3040}]}, {"title": "Radiohead - Amnesiac", "guid": "magnet:?xt=urn:btih:ffeeddccbbaa99887766554433221100ffeeddcc"}, {"title": ""} ]` func TestSearch_AsksTheNativeAPIWithTheKeyInAHeader(t *testing.T) { reqs := make(chan *http.Request, 1) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { reqs <- r _, _ = w.Write([]byte(sampleResults)) })) defer srv.Close() c := &Client{Config: Config{Code: "prowlarr", BaseURL: srv.URL + "/", APIKey: "secret"}} results, err := c.Search(context.Background(), indexer.Query{Text: "radiohead", Categories: []int{3000}}) if err != nil { t.Fatalf("search: %v", err) } got := <-reqs if got.URL.Path != SearchPath || got.URL.Query().Get("type") != "search" || got.URL.Query().Get("categories") != "3000" { t.Errorf("request = %s, want %s with type=search and the categories", got.URL, SearchPath) } if got.Header.Get("X-Api-Key") != "secret" || got.URL.Query().Get("apikey") != "" { t.Error("the key belongs in X-Api-Key, never in the URL") } if len(results) != 2 { t.Fatalf("results = %d, want 2", len(results)) } if r := results[0]; r.InfoHash != "aabbccddeeff00112233445566778899aabbccdd" || r.Peers != 4 || r.Category != 3040 || r.Source != "prowlarr" || r.Published.IsZero() { t.Errorf("first = %+v", r) } if r := results[1]; r.Magnet == "" || r.InfoHash != "ffeeddccbbaa99887766554433221100ffeeddcc" { t.Errorf("second = %+v, want the GUID's magnet and its hash", r) } } func TestSearch_Refusals(t *testing.T) { for name, tc := range map[string]struct { status int want error }{ "a refused key": {http.StatusUnauthorized, indexer.ErrAuth}, "an outage": {http.StatusBadGateway, indexer.ErrUnreachable}, } { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(tc.status) })) c := &Client{Config: Config{BaseURL: srv.URL, APIKey: "k"}} _, err := c.Search(context.Background(), indexer.Query{Text: "x"}) srv.Close() if !errors.Is(err, tc.want) { t.Errorf("%s: err = %v, want %v", name, err, tc.want) } } } func TestSearch_NoKeyIsUnconfigured(t *testing.T) { c := &Client{Config: Config{BaseURL: "http://prowlarr:9696"}} if _, err := c.Search(context.Background(), indexer.Query{Text: "x"}); !errors.Is(err, indexer.ErrUnconfigured) { t.Fatalf("err = %v, want ErrUnconfigured", err) } }