test(server/admin): cover new test endpoint response shape

- Updates the happy-path test stub to handle the three list endpoints
  Lidarr exposes (qualityprofile / metadataprofile / rootfolder) and
  asserts profiles + folders make it through to the response.
- Adds a partial-failure case where one list endpoint 5xxs; verifies
  ok=true, the failing list is omitted, and list_errors carries its
  bucket code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 23:07:47 -04:00
parent 0bc17a85fb
commit 22f03a5fe8
+77 -2
View File
@@ -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