package integration_test import ( "encoding/json" "net/http" "testing" ) func TestOpsContentPhaseC(t *testing.T) { r, _ := setupAPI(t) env, _ := doJSON(t, r, http.MethodGet, "/api/v1/home/tools", nil, "") var home struct { Items []map[string]any `json:"items"` } if err := json.Unmarshal(env.Data, &home); err != nil || len(home.Items) < 6 { t.Fatalf("home tools seed: %v len=%d", err, len(home.Items)) } loginEnv, code := doAdminJSON(t, r, http.MethodPost, "/api/v1/admin/auth/login", map[string]string{ "username": "admin", "password": "change-me", }, "") if code != http.StatusOK { t.Fatalf("login http=%d", code) } var login struct { Token string `json:"token"` } _ = json.Unmarshal(loginEnv.Data, &login) adminTools, code := doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/home/tools", nil, login.Token) if code != http.StatusOK || adminTools.Code != 0 { t.Fatalf("admin tools http=%d code=%d", code, adminTools.Code) } var all struct { Items []map[string]any `json:"items"` } _ = json.Unmarshal(adminTools.Data, &all) if len(all.Items) == 0 { t.Fatal("expected seeded tools") } // disable first tool all.Items[0]["enabled"] = false putEnv, code := doAdminJSON(t, r, http.MethodPut, "/api/v1/admin/home/tools", map[string]any{ "items": all.Items, }, login.Token) if code != http.StatusOK || putEnv.Code != 0 { t.Fatalf("put tools http=%d code=%d msg=%s", code, putEnv.Code, putEnv.Message) } auditEnv, code := doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/audit-logs?limit=5", nil, login.Token) if code != http.StatusOK { t.Fatalf("audit http=%d", code) } var audits struct { Items []struct { Action string `json:"action"` } `json:"items"` } _ = json.Unmarshal(auditEnv.Data, &audits) foundAudit := false for _, a := range audits.Items { if a.Action == "home_tools.replace" { foundAudit = true break } } if !foundAudit { t.Fatalf("expected home_tools.replace audit, got %+v", audits.Items) } env, _ = doJSON(t, r, http.MethodGet, "/api/v1/home/tools", nil, "") _ = json.Unmarshal(env.Data, &home) enabledN := len(home.Items) if enabledN >= len(all.Items) { t.Fatalf("expected fewer enabled tools after disable, pub=%d admin=%d", enabledN, len(all.Items)) } // restore all enabled for shared DB for i := range all.Items { all.Items[i]["enabled"] = true } _, _ = doAdminJSON(t, r, http.MethodPut, "/api/v1/admin/home/tools", map[string]any{"items": all.Items}, login.Token) scalesEnv, code := doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/scales", nil, login.Token) if code != http.StatusOK { t.Fatalf("scales http=%d", code) } var scales struct { Items []struct { ID string `json:"id"` Slug string `json:"slug"` Status string `json:"status"` } `json:"items"` } _ = json.Unmarshal(scalesEnv.Data, &scales) if len(scales.Items) == 0 { t.Fatal("no scales") } target := scales.Items[0] patch, code := doAdminJSON(t, r, http.MethodPatch, "/api/v1/admin/scales/"+target.ID, map[string]string{ "status": "draft", }, login.Token) if code != http.StatusOK || patch.Code != 0 { t.Fatalf("patch http=%d code=%d msg=%s", code, patch.Code, patch.Message) } // published list should not include draft slug — needs registered user key := mustRegister(t, r) listEnv, _ := doJSON(t, r, http.MethodGet, "/api/v1/scales", nil, key) var pub struct { Items []struct { Slug string `json:"slug"` } `json:"items"` } _ = json.Unmarshal(listEnv.Data, &pub) for _, it := range pub.Items { if it.Slug == target.Slug { t.Fatalf("draft scale %s still in published list", target.Slug) } } // restore published so other tests aren't flaky if shared DB _, _ = doAdminJSON(t, r, http.MethodPatch, "/api/v1/admin/scales/"+target.ID, map[string]string{ "status": "published", }, login.Token) }