feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user