Files
cms-server/api/user/user_handler_test.go
Asai Neko 82c412d839
All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Add more tests for modules co worked by claude
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-03-26 23:36:40 +08:00

228 lines
6.5 KiB
Go

package user
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"nixcn-cms/data"
"nixcn-cms/internal/authtoken"
"nixcn-cms/testutil"
)
func init() { gin.SetMode(gin.TestMode) }
func issueToken(t *testing.T, userId uuid.UUID) string {
t.Helper()
tok := &authtoken.Token{Application: viper.GetString("server.application")}
access, _, err := tok.IssueTokens(context.Background(), testutil.TestClientID, userId)
require.NoError(t, err)
return access
}
func newUserRouter(t *testing.T) *gin.Engine {
t.Helper()
r := gin.New()
ApiHandler(r.Group("/user"))
return r
}
func getWithBearer(t *testing.T, r *gin.Engine, path, token string) *httptest.ResponseRecorder {
t.Helper()
req := httptest.NewRequest(http.MethodGet, path, nil)
req.Header.Set("Authorization", "Bearer "+token)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func patchWithBearer(t *testing.T, r *gin.Engine, path, token string, body any) *httptest.ResponseRecorder {
t.Helper()
b, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func patchJSON(t *testing.T, r *gin.Engine, path string, body any) *httptest.ResponseRecorder {
t.Helper()
b, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(b))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func getRequest(t *testing.T, r *gin.Engine, path string) *httptest.ResponseRecorder {
t.Helper()
req := httptest.NewRequest(http.MethodGet, path, nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
// ---- Info ----
func TestUserInfoHandlerSelf(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, "selfinfo@example.com", 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/info", token)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
data, ok := resp["data"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "selfinfo@example.com", data["email"])
}
func TestUserInfoHandlerOtherNotFound(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, "caller@example.com", 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/info/00000000-0000-0000-0000-000000000099", token)
assert.Equal(t, http.StatusNotFound, w.Code)
}
// ---- Update ----
func TestUserUpdateHandlerEmptyNickname(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, "update@example.com", 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := patchWithBearer(t, r, "/user/update", token, map[string]any{
"nickname": "",
})
assert.Equal(t, http.StatusBadRequest, w.Code)
}
func TestUserUpdateHandlerSuccess(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, "update2@example.com", 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := patchWithBearer(t, r, "/user/update", token, map[string]any{
"nickname": "New Nickname",
})
assert.Equal(t, http.StatusOK, w.Code)
}
// ---- List (admin) ----
func TestUserListHandlerRequiresOffset(t *testing.T) {
testutil.SetupWithAuth(t)
admin := testutil.SeedUser(t, "admin@example.com", 40)
token := issueToken(t, admin.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/list", token)
assert.Equal(t, http.StatusBadRequest, w.Code)
}
func TestUserListHandlerSuccess(t *testing.T) {
testutil.SetupWithAuth(t)
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
for i := 0; i < 3; i++ {
testutil.SeedUser(t, testutil.RandomEmail(), 10)
}
token := issueToken(t, admin.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/list?offset=0&limit=10", token)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
assert.NotNil(t, resp["data"])
}
func TestUserListHandlerLowPermission(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/list?offset=0", token)
assert.Equal(t, http.StatusForbidden, w.Code)
}
// ---- Other (info by user_id) ----
func TestUserInfoHandlerOtherSuccess(t *testing.T) {
testutil.SetupWithAuth(t)
caller := testutil.SeedUser(t, testutil.RandomEmail(), 10)
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
require.NoError(t, new(data.User).PatchByUserId(context.Background(), target.UserId, data.WithAllowPublic(true)))
token := issueToken(t, caller.UserId)
r := newUserRouter(t)
w := getWithBearer(t, r, "/user/info/"+target.UserId.String(), token)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
d, ok := resp["data"].(map[string]any)
require.True(t, ok)
assert.Equal(t, target.Email, d["email"])
}
// ---- AdminUpdate ----
func TestUserAdminUpdateHandlerSuccess(t *testing.T) {
testutil.SetupWithAuth(t)
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
token := issueToken(t, admin.UserId)
r := newUserRouter(t)
w := patchWithBearer(t, r, "/user/update/"+target.UserId.String(), token, map[string]any{
"nickname": "Admin Set Nickname",
})
assert.Equal(t, http.StatusOK, w.Code)
}
func TestUserAdminUpdateHandlerInvalidUserId(t *testing.T) {
testutil.SetupWithAuth(t)
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
token := issueToken(t, admin.UserId)
r := newUserRouter(t)
w := patchWithBearer(t, r, "/user/update/not-a-uuid", token, map[string]any{
"nickname": "Test",
})
assert.Equal(t, http.StatusBadRequest, w.Code)
}
func TestUserAdminUpdateHandlerLowPermission(t *testing.T) {
testutil.SetupWithAuth(t)
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
token := issueToken(t, user.UserId)
r := newUserRouter(t)
w := patchWithBearer(t, r, "/user/update/"+target.UserId.String(), token, map[string]any{
"nickname": "Hacked",
})
assert.Equal(t, http.StatusForbidden, w.Code)
}