| package accounts |
|
|
| import ( |
| "bytes" |
| "encoding/json" |
| "net/http" |
| "net/http/httptest" |
| "net/url" |
| "testing" |
|
|
| "github.com/go-chi/chi/v5" |
|
|
| "ds2api/internal/account" |
| "ds2api/internal/config" |
| ) |
|
|
| func newAdminTestHandler(t *testing.T, raw string) *Handler { |
| t.Helper() |
| t.Setenv("DS2API_CONFIG_JSON", raw) |
| store := config.LoadStore() |
| return &Handler{ |
| Store: store, |
| Pool: account.NewPool(store), |
| } |
| } |
|
|
| func TestListAccountsUsesEmailIdentifier(t *testing.T) { |
| h := newAdminTestHandler(t, `{ |
| "accounts":[{"email":"u@example.com","password":"pwd"}] |
| }`) |
|
|
| 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) |
| identifier, _ := first["identifier"].(string) |
| if identifier != "u@example.com" { |
| t.Fatalf("expected email identifier, got %q", identifier) |
| } |
| } |
|
|
| func TestDeleteAccountSupportsMobileAlias(t *testing.T) { |
| h := newAdminTestHandler(t, `{ |
| "accounts":[{"email":"u@example.com","mobile":"13800138000","password":"pwd"}] |
| }`) |
|
|
| r := chi.NewRouter() |
| r.Delete("/admin/accounts/{identifier}", h.deleteAccount) |
| req := httptest.NewRequest(http.MethodDelete, "/admin/accounts/13800138000", nil) |
| rec := httptest.NewRecorder() |
| r.ServeHTTP(rec, req) |
|
|
| if rec.Code != http.StatusOK { |
| t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String()) |
| } |
| if got := len(h.Store.Accounts()); got != 0 { |
| t.Fatalf("expected account removed, remaining=%d", got) |
| } |
| } |
|
|
| func TestDeleteAccountSupportsEncodedPlusMobile(t *testing.T) { |
| h := newAdminTestHandler(t, `{ |
| "accounts":[{"mobile":"+8613800138000","password":"pwd"}] |
| }`) |
|
|
| r := chi.NewRouter() |
| r.Delete("/admin/accounts/{identifier}", h.deleteAccount) |
| req := httptest.NewRequest(http.MethodDelete, "/admin/accounts/"+url.PathEscape("+8613800138000"), nil) |
| rec := httptest.NewRecorder() |
| r.ServeHTTP(rec, req) |
|
|
| if rec.Code != http.StatusOK { |
| t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String()) |
| } |
| if got := len(h.Store.Accounts()); got != 0 { |
| t.Fatalf("expected account removed, remaining=%d", got) |
| } |
| } |
|
|
| func TestAddAccountRejectsCanonicalMobileDuplicate(t *testing.T) { |
| h := newAdminTestHandler(t, `{ |
| "accounts":[{"mobile":"+8613800138000","password":"pwd"}] |
| }`) |
|
|
| r := chi.NewRouter() |
| r.Post("/admin/accounts", h.addAccount) |
| body := []byte(`{"mobile":"13800138000","password":"pwd2"}`) |
| req := httptest.NewRequest(http.MethodPost, "/admin/accounts", bytes.NewReader(body)) |
| rec := httptest.NewRecorder() |
| r.ServeHTTP(rec, req) |
|
|
| if rec.Code != http.StatusBadRequest { |
| t.Fatalf("unexpected status: %d body=%s", rec.Code, rec.Body.String()) |
| } |
| if got := len(h.Store.Accounts()); got != 1 { |
| t.Fatalf("expected no duplicate insert, got=%d", got) |
| } |
| } |
|
|
| func TestFindAccountByIdentifierSupportsMobile(t *testing.T) { |
| h := newAdminTestHandler(t, `{ |
| "accounts":[ |
| {"email":"u@example.com","mobile":"13800138000","password":"pwd"} |
| ] |
| }`) |
|
|
| accByMobile, ok := findAccountByIdentifier(h.Store, "13800138000") |
| if !ok { |
| t.Fatal("expected find by mobile") |
| } |
| if accByMobile.Email != "u@example.com" { |
| t.Fatalf("unexpected account by mobile: %#v", accByMobile) |
| } |
| accByMobileWithCountryCode, ok := findAccountByIdentifier(h.Store, "+8613800138000") |
| if !ok { |
| t.Fatal("expected find by +86 mobile") |
| } |
| if accByMobileWithCountryCode.Email != "u@example.com" { |
| t.Fatalf("unexpected account by +86 mobile: %#v", accByMobileWithCountryCode) |
| } |
|
|
| } |
|
|