package integration_test import ( "encoding/json" "net/http" "testing" "time" ) func TestMembershipPlans(t *testing.T) { r, _ := setupAPIPool(t) tok := adminLogin(t, r, "admin", "change-me") _, code := doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/membership-plans", nil, "") if code != http.StatusUnauthorized { t.Fatalf("expected 401, got %d", code) } start := time.Now() env, code := doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/membership-plans", nil, tok) if code != 200 || time.Since(start) > 500*time.Millisecond { t.Fatalf("list plans http=%d dur=%v msg=%s", code, time.Since(start), env.Message) } var list struct { Items []struct { Code string `json:"code"` DurationDays int `json:"duration_days"` AmountCents int `json:"amount_cents"` } `json:"items"` } _ = json.Unmarshal(env.Data, &list) if len(list.Items) < 3 { t.Fatalf("expected 3 plans, got %#v", list.Items) } env, code = doAdminJSON(t, r, http.MethodPut, "/api/v1/admin/membership-plans/month", map[string]any{ "title": "月卡测", "duration_days": 30, "amount_cents": 2600, "active": true, }, tok) if code != 200 { t.Fatalf("put failed %d %s", code, env.Message) } var plan struct { DurationDays int `json:"duration_days"` AmountCents int `json:"amount_cents"` } _ = json.Unmarshal(env.Data, &plan) if plan.DurationDays != 30 || plan.AmountCents != 2600 { t.Fatalf("unexpected plan %#v", plan) } env, code = doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/membership-plans/month", nil, tok) if code != 200 { t.Fatalf("get %d", code) } _ = json.Unmarshal(env.Data, &plan) if plan.DurationDays != 30 { t.Fatalf("get mismatch %#v", plan) } _ = mustRegister(t, r) env, code = doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/users", nil, tok) var users struct { Items []struct { ID string `json:"id"` } `json:"items"` } _ = json.Unmarshal(env.Data, &users) if len(users.Items) == 0 { t.Fatal("need user") } env, code = doAdminJSON(t, r, http.MethodPost, "/api/v1/admin/users/"+users.Items[0].ID+"/membership/grant", map[string]string{"plan": "month"}, tok) if code != 200 { t.Fatalf("grant %d %s", code, env.Message) } env, code = doAdminJSON(t, r, http.MethodGet, "/api/v1/admin/audit-logs", nil, tok) if code != 200 { t.Fatalf("audit %d", code) } var audit struct { Items []struct { Action string `json:"action"` } `json:"items"` } _ = json.Unmarshal(env.Data, &audit) found := false for _, it := range audit.Items { if it.Action == "membership.plans.update" { found = true break } } if !found { t.Fatal("missing membership.plans.update audit") } }