diff --git a/internal/api/admin_lidarr_test.go b/internal/api/admin_lidarr_test.go index d0e882b5..f5b1618e 100644 --- a/internal/api/admin_lidarr_test.go +++ b/internal/api/admin_lidarr_test.go @@ -216,9 +216,20 @@ func TestHandleTestLidarrConnection_HappyPath(t *testing.T) { resetLidarrState(t, h) admin := seedAdminUser(t, h) - stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - _, _ = w.Write([]byte(`{"version":"2.0.5"}`)) + switch r.URL.Path { + case "/api/v1/system/status": + _, _ = w.Write([]byte(`{"version":"2.0.5"}`)) + case "/api/v1/qualityprofile": + _, _ = w.Write([]byte(`[{"id":1,"name":"FLAC"},{"id":2,"name":"MP3-320"}]`)) + case "/api/v1/metadataprofile": + _, _ = w.Write([]byte(`[{"id":1,"name":"Standard"}]`)) + case "/api/v1/rootfolder": + _, _ = w.Write([]byte(`[{"path":"/music","accessible":true,"freeSpace":12345}]`)) + default: + http.NotFound(w, r) + } })) t.Cleanup(stub.Close) @@ -243,6 +254,70 @@ func TestHandleTestLidarrConnection_HappyPath(t *testing.T) { if resp["version"] != "2.0.5" { t.Errorf("version = %v, want 2.0.5", resp["version"]) } + qp, ok := resp["quality_profiles"].([]any) + if !ok || len(qp) != 2 { + t.Errorf("quality_profiles = %v, want 2 entries", resp["quality_profiles"]) + } + mp, ok := resp["metadata_profiles"].([]any) + if !ok || len(mp) != 1 { + t.Errorf("metadata_profiles = %v, want 1 entry", resp["metadata_profiles"]) + } + rf, ok := resp["root_folders"].([]any) + if !ok || len(rf) != 1 { + t.Errorf("root_folders = %v, want 1 entry", resp["root_folders"]) + } + if _, present := resp["list_errors"]; present { + t.Errorf("list_errors should be omitted when all lists succeed; got %v", resp["list_errors"]) + } +} + +// TestHandleTestLidarrConnection_PartialListFailure verifies that POST /test +// against a Lidarr that responds OK to the ping + two of three lists still +// reports ok=true with the failing list omitted and named in list_errors. +func TestHandleTestLidarrConnection_PartialListFailure(t *testing.T) { + h, _ := testHandlers(t) + resetLidarrState(t, h) + admin := seedAdminUser(t, h) + + stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.URL.Path { + case "/api/v1/system/status": + _, _ = w.Write([]byte(`{"version":"2.0.5"}`)) + case "/api/v1/qualityprofile": + _, _ = w.Write([]byte(`[{"id":1,"name":"FLAC"}]`)) + case "/api/v1/metadataprofile": + http.Error(w, "boom", http.StatusInternalServerError) + case "/api/v1/rootfolder": + _, _ = w.Write([]byte(`[{"path":"/music","accessible":true,"freeSpace":12345}]`)) + default: + http.NotFound(w, r) + } + })) + t.Cleanup(stub.Close) + + body := []byte(`{"base_url":"` + stub.URL + `","api_key":"k"}`) + w := doAdminReq(t, h, http.MethodPost, "/api/admin/lidarr/test", body, admin) + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200; body = %s", w.Code, w.Body.String()) + } + var resp map[string]any + if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { + t.Fatalf("decode: %v; body = %s", err, w.Body.String()) + } + if resp["ok"] != true { + t.Errorf("ok = %v, want true", resp["ok"]) + } + if _, present := resp["metadata_profiles"]; present { + t.Errorf("metadata_profiles should be omitted on failure; got %v", resp["metadata_profiles"]) + } + listErrs, ok := resp["list_errors"].(map[string]any) + if !ok { + t.Fatalf("list_errors missing or wrong shape: %v", resp["list_errors"]) + } + if _, present := listErrs["metadata_profiles"]; !present { + t.Errorf("list_errors.metadata_profiles should be present, got %v", listErrs) + } } // TestHandleTestLidarrConnection_Unreachable verifies that POST /test against