package api import ( "encoding/json" "net/http" "strconv" "testing" ) func adminToken(t *testing.T, h http.Handler) string { t.Helper() return loginAs(t, h, "alice", testPW) } func TestUserCRUD(t *testing.T) { _, _, h, _ := setupAPI(t) tok := adminToken(t, h) w := do(h, "POST", "/api/users", tok, map[string]string{"username": "carol", "password": "pw123456", "role": "member"}) if w.Code != 201 { t.Fatalf("create %d %s", w.Code, w.Body) } w = do(h, "GET", "/api/users", tok, nil) var users []map[string]any json.Unmarshal(w.Body.Bytes(), &users) if len(users) != 3 { t.Fatalf("list want 3 got %d: %s", len(users), w.Body) } carolID := findID(users, "carol") // 重名 → 409 w = do(h, "POST", "/api/users", tok, map[string]string{"username": "carol", "password": "pw123456", "role": "member"}) if w.Code != 409 { t.Fatalf("dup want 409 got %d", w.Code) } // 弱密码 → 400 w = do(h, "POST", "/api/users", tok, map[string]string{"username": "dave", "password": "1", "role": "member"}) if w.Code != 400 { t.Fatalf("weak want 400 got %d", w.Code) } // 不能删自己:先 me 拿 id w = do(h, "GET", "/api/auth/me", tok, nil) var me map[string]any json.Unmarshal(w.Body.Bytes(), &me) w = do(h, "DELETE", "/api/users/"+itoa(me["id"]), tok, nil) if w.Code != 400 { t.Fatalf("self-delete want 400 got %d %s", w.Code, w.Body) } // 删 carol → 204,再删 → 404 w = do(h, "DELETE", "/api/users/"+itoa(carolID), tok, nil) if w.Code != 204 { t.Fatalf("delete %d %s", w.Code, w.Body) } w = do(h, "DELETE", "/api/users/"+itoa(carolID), tok, nil) if w.Code != 404 { t.Fatalf("redelete want 404 got %d", w.Code) } } func TestBadRoleRejected(t *testing.T) { _, _, h, _ := setupAPI(t) tok := adminToken(t, h) w := do(h, "POST", "/api/users", tok, map[string]string{"username": "e", "password": "pw123456", "role": "god"}) if w.Code != 400 { t.Fatalf("bad role want 400 got %d", w.Code) } } func findID(rows []map[string]any, name string) float64 { for _, r := range rows { if r["username"] == name { return r["id"].(float64) } } return 0 } func itoa(v any) string { if i, ok := v.(int64); ok { return strconv.FormatInt(i, 10) // DB 行里的 id (如 store.Library.ID) } return strconv.FormatFloat(v.(float64), 'f', 0, 64) // json.Unmarshal 出来的数字 }