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" ) func TestPermissionAPI_Create(t *testing.T) { env := integ.NewIntegrationTestEnv(t) t.Run("成功创建权限", func(t *testing.T) { // 权限编码必须符合 module:action 格式(两边都以小写字母开头) permCode := fmt.Sprintf("test:action%d", time.Now().UnixNano()) reqBody := dto.CreatePermissionRequest{ PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: permCode, PermType: constants.PermissionTypeMenu, URL: "/admin/users", } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/permissions", 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.Permission{}).Where("perm_code = ?", permCode).Count(&count) assert.Equal(t, int64(1), count) }) t.Run("权限编码重复时返回错误", func(t *testing.T) { existingPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), fmt.Sprintf("test:dup%d", time.Now().UnixNano()), constants.PermissionTypeMenu, ) reqBody := dto.CreatePermissionRequest{ PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: existingPerm.PermCode, PermType: constants.PermissionTypeMenu, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/permissions", jsonBody) require.NoError(t, err) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, errors.CodePermCodeExists, result.Code) }) t.Run("创建子权限", func(t *testing.T) { parentPermCode := fmt.Sprintf("test:parent%d", time.Now().UnixNano()) parentPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), parentPermCode, constants.PermissionTypeMenu, ) childPermCode := fmt.Sprintf("test:child%d", time.Now().UnixNano()) reqBody := dto.CreatePermissionRequest{ PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: childPermCode, PermType: constants.PermissionTypeButton, ParentID: &parentPerm.ID, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/permissions", jsonBody) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var child model.Permission err = env.RawDB().Where("perm_code = ?", childPermCode).First(&child).Error require.NoError(t, err, "子权限应该已创建") require.NotNil(t, child.ParentID, "子权限的 ParentID 应该已设置") assert.Equal(t, parentPerm.ID, *child.ParentID) }) } func TestPermissionAPI_Get(t *testing.T) { env := integ.NewIntegrationTestEnv(t) testPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), fmt.Sprintf("test:get%d", time.Now().UnixNano()), constants.PermissionTypeMenu, ) t.Run("成功获取权限详情", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/permissions/%d", testPerm.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/permissions/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.CodePermissionNotFound, result.Code) }) } func TestPermissionAPI_Update(t *testing.T) { env := integ.NewIntegrationTestEnv(t) testPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), fmt.Sprintf("test:upd%d", time.Now().UnixNano()), constants.PermissionTypeMenu, ) t.Run("成功更新权限", func(t *testing.T) { newName := "更新后权限" reqBody := dto.UpdatePermissionRequest{ PermName: &newName, } jsonBody, _ := json.Marshal(reqBody) resp, err := env.AsSuperAdmin().Request("PUT", fmt.Sprintf("/api/admin/permissions/%d", testPerm.ID), jsonBody) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var updated model.Permission env.RawDB().First(&updated, testPerm.ID) assert.Equal(t, newName, updated.PermName) }) } func TestPermissionAPI_Delete(t *testing.T) { env := integ.NewIntegrationTestEnv(t) t.Run("成功软删除权限", func(t *testing.T) { testPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), fmt.Sprintf("test:del%d", time.Now().UnixNano()), constants.PermissionTypeMenu, ) resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/permissions/%d", testPerm.ID), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) var deleted model.Permission err = env.RawDB().Unscoped().First(&deleted, testPerm.ID).Error require.NoError(t, err) assert.NotNil(t, deleted.DeletedAt) }) } func TestPermissionAPI_List(t *testing.T) { env := integ.NewIntegrationTestEnv(t) for i := 1; i <= 5; i++ { env.CreateTestPermission(fmt.Sprintf("列表测试权限_%d", i), fmt.Sprintf("list:perm%d", i), constants.PermissionTypeMenu) } t.Run("成功获取权限列表", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/permissions?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", fmt.Sprintf("/api/admin/permissions?perm_type=%d", constants.PermissionTypeMenu), nil) require.NoError(t, err) assert.Equal(t, fiber.StatusOK, resp.StatusCode) }) } func TestPermissionAPI_GetTree(t *testing.T) { env := integ.NewIntegrationTestEnv(t) rootPerm := env.CreateTestPermission( fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), fmt.Sprintf("test:root%d", time.Now().UnixNano()), constants.PermissionTypeMenu, ) childPermCode := fmt.Sprintf("test:child%d", time.Now().UnixNano()) childPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: childPermCode, PermType: constants.PermissionTypeMenu, ParentID: &rootPerm.ID, Status: constants.StatusEnabled, } env.TX.Create(childPerm) grandchildPermCode := fmt.Sprintf("test:grand%d", time.Now().UnixNano()) grandchildPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: grandchildPermCode, PermType: constants.PermissionTypeButton, ParentID: &childPerm.ID, Status: constants.StatusEnabled, } env.TX.Create(grandchildPerm) t.Run("成功获取权限树", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/permissions/tree", 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) }) } func TestPermissionAPI_GetTreeByRoleType(t *testing.T) { env := integ.NewIntegrationTestEnv(t) platformPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:plat%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "1", Status: constants.StatusEnabled, } env.TX.Create(platformPerm) customerPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:cust%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "2", Status: constants.StatusEnabled, } env.TX.Create(customerPerm) commonPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:comm%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "1,2", Status: constants.StatusEnabled, } env.TX.Create(commonPerm) t.Run("按角色类型过滤权限树-平台角色", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/permissions/tree?available_for_role_type=%d", constants.RoleTypePlatform), 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/permissions/tree?available_for_role_type=2", 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/permissions/tree?platform=all&available_for_role_type=1", 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) }) } func TestPermissionAPI_FilterByAvailableForRoleTypes(t *testing.T) { env := integ.NewIntegrationTestEnv(t) platformPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:fplat%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "1", Status: constants.StatusEnabled, } env.TX.Create(platformPerm) customerPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:fcust%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "2", Status: constants.StatusEnabled, } env.TX.Create(customerPerm) commonPerm := &model.Permission{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, PermName: fmt.Sprintf("test_permission_%d", time.Now().UnixNano()), PermCode: fmt.Sprintf("test:fcomm%d", time.Now().UnixNano()), PermType: constants.PermissionTypeMenu, AvailableForRoleTypes: "1,2", Status: constants.StatusEnabled, } env.TX.Create(commonPerm) t.Run("过滤平台角色可用权限", func(t *testing.T) { resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/permissions?available_for_role_type=1", 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", fmt.Sprintf("/api/admin/permissions/tree?available_for_role_type=%d", constants.RoleTypePlatform), 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) }) }