Files
ds2api/internal/httpapi/admin/accounts/handler_accounts_crud_test.go
2026-04-26 06:58:20 +08:00

119 lines
3.8 KiB
Go

package accounts
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/go-chi/chi/v5"
)
func TestListAccountsPageSizeCapIs5000(t *testing.T) {
accounts := make([]string, 0, 150)
for i := range 150 {
accounts = append(accounts, fmt.Sprintf(`{"email":"u%d@example.com","password":"pwd"}`, i))
}
raw := fmt.Sprintf(`{"accounts":[%s]}`, strings.Join(accounts, ","))
router := newHTTPAdminHarness(t, raw, &testingDSMock{})
rec := httptest.NewRecorder()
router.ServeHTTP(rec, adminReq(http.MethodGet, "/accounts?page=1&page_size=200", nil))
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String())
}
var payload map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("decode response: %v", err)
}
items, _ := payload["items"].([]any)
if len(items) != 150 {
t.Fatalf("expected all 150 accounts with page_size=200, got %d", len(items))
}
if ps, _ := payload["page_size"].(float64); ps != 200 {
t.Fatalf("expected page_size=200 in response, got %v", payload["page_size"])
}
}
func TestListAccountsPageSizeAbove5000ClampedTo5000(t *testing.T) {
router := newHTTPAdminHarness(t, `{"accounts":[{"email":"u@example.com","password":"pwd"}]}`, &testingDSMock{})
rec := httptest.NewRecorder()
router.ServeHTTP(rec, adminReq(http.MethodGet, "/accounts?page=1&page_size=9999", nil))
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String())
}
var payload map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("decode response: %v", err)
}
if ps, _ := payload["page_size"].(float64); ps != 5000 {
t.Fatalf("expected page_size clamped to 5000, got %v", payload["page_size"])
}
}
func TestUpdateAccountMetadataPreservesCredentials(t *testing.T) {
h := newAdminTestHandler(t, `{
"accounts":[{"email":"u@example.com","name":"old name","remark":"old remark","password":"secret"}]
}`)
r := chi.NewRouter()
r.Put("/admin/accounts/{identifier}", h.updateAccount)
body := []byte(`{"name":"new name","remark":"new remark"}`)
req := httptest.NewRequest(http.MethodPut, "/admin/accounts/u@example.com", strings.NewReader(string(body)))
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String())
}
snap := h.Store.Snapshot()
if len(snap.Accounts) != 1 {
t.Fatalf("unexpected accounts after update: %#v", snap.Accounts)
}
acc := snap.Accounts[0]
if acc.Email != "u@example.com" {
t.Fatalf("identifier changed unexpectedly: %#v", acc)
}
if acc.Name != "new name" || acc.Remark != "new remark" {
t.Fatalf("metadata update did not persist: %#v", acc)
}
if acc.Password != "secret" {
t.Fatalf("password should be preserved, got %#v", acc)
}
}
func TestListAccountsMasksTokenPreview(t *testing.T) {
h := newAdminTestHandler(t, `{
"accounts":[{"email":"u@example.com","password":"pwd"}]
}`)
if err := h.Store.UpdateAccountToken("u@example.com", "abcdefgh"); err != nil {
t.Fatalf("seed runtime token: %v", err)
}
req := httptest.NewRequest(http.MethodGet, "/admin/accounts?page=1&page_size=10", nil)
rec := httptest.NewRecorder()
h.listAccounts(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String())
}
var payload map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("decode response failed: %v", err)
}
items, _ := payload["items"].([]any)
if len(items) != 1 {
t.Fatalf("expected 1 item, got %d", len(items))
}
first, _ := items[0].(map[string]any)
if got, _ := first["token_preview"].(string); got != "ab****gh" {
t.Fatalf("expected masked token preview, got %q", got)
}
}