package integration import ( "encoding/json" "fmt" "testing" "time" "github.com/gofiber/fiber/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/response" "github.com/break/junhong_cmp_fiber/tests/testutils/integ" ) // TestAccountAPI_Create 测试创建账号 API func TestAccountAPI_Create(t *testing.T) { env := integ.NewIntegrationTestEnv(t) t.Run("成功创建平台账号", func(t *testing.T) { username := fmt.Sprintf("platform_user_%d", time.Now().UnixNano()) phone := fmt.Sprintf("138%08d", time.Now().UnixNano()%100000000) reqBody := dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "Password123", UserType: constants.UserTypePlatform, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", jsonBody) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) // 验证数据库中账号已创建 var count int64 env.RawDB().Model(&model.Account{}).Where("username = ?", username).Count(&count) assert.Equal(t, int64(1), count) }) t.Run("用户名重复时返回错误", func(t *testing.T) { // 先创建一个账号 existingUsername := fmt.Sprintf("existing_user_%d", time.Now().UnixNano()) existingAccount := env.CreateTestAccount(existingUsername, "password123", constants.UserTypePlatform, nil, nil) // 尝试创建同名账号 phone := fmt.Sprintf("138%08d", time.Now().UnixNano()%100000000) reqBody := dto.CreateAccountRequest{ Username: existingAccount.Username, Phone: phone, Password: "Password123", UserType: constants.UserTypePlatform, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", jsonBody) require.NoError(t, err) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, errors.CodeUsernameExists, result.Code) }) // TODO: 当前代码允许平台账号不提供 parent_id,此测试预期的业务规则已变更 // t.Run("非root用户缺少parent_id时返回错误", func(t *testing.T) { ... }) } // TestAccountAPI_Get 测试获取账号详情 API func TestAccountAPI_Get(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建测试账号 testAccount := env.CreateTestAccount("test_user", "password123", constants.UserTypePlatform, nil, nil) t.Run("成功获取账号详情", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) }) t.Run("账号不存在时返回错误", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts/99999", nil) require.NoError(t, err) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, errors.CodeAccountNotFound, result.Code) }) t.Run("无效ID返回错误", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts/invalid", nil) require.NoError(t, err) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, errors.CodeInvalidParam, result.Code) }) } // TestAccountAPI_Update 测试更新账号 API func TestAccountAPI_Update(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建测试账号 testAccount := env.CreateTestAccount("update_test", "password123", constants.UserTypePlatform, nil, nil) t.Run("成功更新账号", func(t *testing.T) { newUsername := "updated_user" reqBody := dto.UpdateAccountRequest{ Username: &newUsername, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("PUT", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), jsonBody) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) // 验证数据库已更新 var updated model.Account env.RawDB().First(&updated, testAccount.ID) assert.Equal(t, newUsername, updated.Username) }) } // TestAccountAPI_Delete 测试删除账号 API func TestAccountAPI_Delete(t *testing.T) { env := integ.NewIntegrationTestEnv(t) t.Run("成功软删除账号", func(t *testing.T) { // 创建测试账号 testAccount := env.CreateTestAccount("delete_test", "password123", constants.UserTypePlatform, nil, nil) resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) // 验证账号已软删除 var deleted model.Account err = env.RawDB().Unscoped().First(&deleted, testAccount.ID).Error require.NoError(t, err) assert.NotNil(t, deleted.DeletedAt) }) } // TestAccountAPI_List 测试账号列表 API func TestAccountAPI_List(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建多个测试账号 for i := 1; i <= 5; i++ { env.CreateTestAccount(fmt.Sprintf("list_test_%d", i), "password123", constants.UserTypePlatform, nil, nil) } t.Run("成功获取账号列表", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=1&page_size=10", nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) }) t.Run("分页功能正常", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=1&page_size=2", nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) }) } // TestAccountAPI_AssignRoles 测试分配角色 API func TestAccountAPI_AssignRoles(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建测试账号 testAccount := env.CreateTestAccount("role_test", "password123", constants.UserTypePlatform, nil, nil) // 创建测试角色 testRole := env.CreateTestRole("测试角色", constants.RoleTypePlatform) t.Run("成功分配角色", func(t *testing.T) { reqBody := dto.AssignRolesRequest{ RoleIDs: []uint{testRole.ID}, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", fmt.Sprintf("/api/admin/accounts/%d/roles", testAccount.ID), jsonBody) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) // 验证关联已创建 var count int64 env.RawDB().Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).Count(&count) assert.Equal(t, int64(1), count) }) } // TestAccountAPI_GetRoles 测试获取账号角色 API func TestAccountAPI_GetRoles(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建测试账号 testAccount := env.CreateTestAccount("get_roles_test", "password123", constants.UserTypePlatform, nil, nil) // 创建并分配角色 testRole := env.CreateTestRole("获取角色测试", constants.RoleTypePlatform) accountRole := &model.AccountRole{ AccountID: testAccount.ID, RoleID: testRole.ID, Status: constants.StatusEnabled, Creator: 1, Updater: 1, } env.TX.Create(accountRole) t.Run("成功获取账号角色", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d/roles", testAccount.ID), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) }) } // TestAccountAPI_RemoveRole 测试移除角色 API func TestAccountAPI_RemoveRole(t *testing.T) { env := integ.NewIntegrationTestEnv(t) // 创建测试账号 testAccount := env.CreateTestAccount("remove_role_test", "password123", constants.UserTypePlatform, nil, nil) // 创建并分配角色 testRole := env.CreateTestRole("移除角色测试", constants.RoleTypePlatform) accountRole := &model.AccountRole{ AccountID: testAccount.ID, RoleID: testRole.ID, Status: constants.StatusEnabled, Creator: 1, Updater: 1, } env.TX.Create(accountRole) t.Run("成功移除角色", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/accounts/%d/roles/%d", testAccount.ID, testRole.ID), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) // 验证关联已软删除 var ar model.AccountRole err = env.RawDB().Unscoped().Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).First(&ar).Error require.NoError(t, err) assert.NotNil(t, ar.DeletedAt) }) }