app-cloudep-permission-server/pkg/repository/role_test.go

543 lines
12 KiB
Go

package repository
import (
"context"
"fmt"
"testing"
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/permission"
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func SetupTestRoleRepository(db string) (repository.RoleRepository, func(), error) {
h, p, tearDown, err := startMongoContainer()
if err != nil {
return nil, nil, err
}
conf := &mgo.Conf{
Schema: Schema,
Host: fmt.Sprintf("%s:%s", h, p),
Database: db,
MaxStaleness: 300,
MaxPoolSize: 100,
MinPoolSize: 100,
MaxConnIdleTime: 300,
Compressors: []string{},
EnableStandardReadWriteSplitMode: false,
ConnectTimeoutMs: 3000,
}
param := RoleRepositoryParam{
Conf: conf,
}
repo := NewRoleRepository(param)
_, _ = repo.Index20250224UP(context.Background())
return repo, tearDown, nil
}
func TestRoleRepository_Create(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
testCases := []struct {
name string
input *entity.Role
expectErr bool
}{
{
name: "成功建立新的角色",
input: &entity.Role{
Name: "Admin",
UID: "user123",
ClientID: "client456",
Status: 1,
},
expectErr: false,
},
{
name: "自動生成 ID 及時間戳",
input: &entity.Role{
Name: "User",
UID: "user789",
ClientID: "client987",
Status: 1,
},
expectErr: false,
},
{
name: "當角色為 nil 時應返回錯誤",
input: nil,
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Create(context.Background(), tc.input)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.NotEqual(t, primitive.NilObjectID, tc.input.ID, "應該自動生成 ObjectID")
assert.True(t, tc.input.CreateAt > 0, "應該自動設定 CreateAt")
assert.True(t, tc.input.UpdateAt > 0, "應該自動設定 UpdateAt")
}
})
}
}
func TestRoleRepository_Update(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 預先建立一個角色
existingRole := &entity.Role{
Name: "Old Name",
UID: "old_uid",
ClientID: "old_client_id",
Status: 1,
}
err = repo.Create(context.Background(), existingRole)
assert.NoError(t, err)
newName := "New Name"
newStatus := permission.Close
newUID := "new_uid"
newClientID := "new_client_id"
testCases := []struct {
name string
input repository.UpdateReq
expectErr bool
}{
{
name: "成功更新角色",
input: repository.UpdateReq{
ID: existingRole.ID.Hex(),
Name: &newName,
Status: &newStatus,
UID: &newUID,
ClientID: &newClientID,
},
expectErr: false,
},
{
name: "更新部分欄位",
input: repository.UpdateReq{
ID: existingRole.ID.Hex(),
Name: &newName,
Status: &newStatus,
},
expectErr: false,
},
{
name: "無效的 ObjectID 應返回錯誤",
input: repository.UpdateReq{
ID: "invalid_object_id",
},
expectErr: true,
},
{
name: "當 UpdateOne 失敗時應返回錯誤",
input: repository.UpdateReq{
ID: primitive.NewObjectID().Hex(), // 模擬一個不存在的 ID
},
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Update(context.Background(), tc.input)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
// 驗證更新結果
updatedRole, err := repo.GetByID(context.Background(), existingRole.ID.Hex())
assert.NoError(t, err)
if tc.input.Name != nil {
assert.Equal(t, *tc.input.Name, updatedRole.Name, "名稱應該被更新")
}
if tc.input.Status != nil {
assert.Equal(t, *tc.input.Status, updatedRole.Status, "狀態應該被更新")
}
if tc.input.UID != nil {
assert.Equal(t, *tc.input.UID, updatedRole.UID, "UID 應該被更新")
}
if tc.input.ClientID != nil {
assert.Equal(t, *tc.input.ClientID, updatedRole.ClientID, "ClientID 應該被更新")
}
}
})
}
}
func TestRoleRepository_Delete(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 預先建立一個角色
existingRole := &entity.Role{
Name: "Test Role",
UID: "test_uid",
ClientID: "test_client_id",
Status: 1,
}
err = repo.Create(context.Background(), existingRole)
assert.NoError(t, err)
testCases := []struct {
name string
inputID string
expectErr bool
}{
{
name: "成功刪除角色",
inputID: existingRole.ID.Hex(),
expectErr: false,
},
{
name: "刪除不存在的角色不應報錯",
inputID: primitive.NewObjectID().Hex(),
expectErr: false,
},
{
name: "無效的 ObjectID 應返回錯誤",
inputID: "invalid_object_id",
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Delete(context.Background(), tc.inputID)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
// 驗證角色是否已刪除
if tc.inputID == existingRole.ID.Hex() {
_, err := repo.GetByID(context.Background(), existingRole.ID.Hex())
assert.Error(t, err, "應該找不到該角色")
}
}
})
}
}
func TestRoleRepository_All(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
clientID1 := "client_1"
clientID2 := "client_2"
// 預先建立角色資料
roles := []*entity.Role{
{
ID: primitive.NewObjectID(),
Name: "Admin",
UID: "admin_uid",
ClientID: clientID1,
Status: 1,
},
{
ID: primitive.NewObjectID(),
Name: "User",
UID: "user_uid",
ClientID: clientID1,
Status: 1,
},
{
ID: primitive.NewObjectID(),
Name: "Manager",
UID: "manager_uid",
ClientID: clientID2,
Status: 1,
},
}
// 插入測試資料
for _, role := range roles {
err := repo.Create(context.Background(), role)
assert.NoError(t, err)
}
testCases := []struct {
name string
clientID *string
expectLen int
expectErr bool
}{
{
name: "查詢所有角色",
clientID: nil,
expectLen: len(roles),
expectErr: false,
},
{
name: "根據 clientID 查詢角色",
clientID: &clientID1,
expectLen: 2,
expectErr: false,
},
{
name: "clientID 無匹配時應返回空",
clientID: new(string),
expectLen: 0,
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.All(context.Background(), tc.clientID)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.Len(t, result, tc.expectLen, "返回的角色數量應符合預期")
}
})
}
}
func TestRoleRepository_GetByUID(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 預先建立測試角色
existingRole := &entity.Role{
ID: primitive.NewObjectID(),
Name: "Admin",
UID: "admin_uid",
ClientID: "client_1",
Status: 1,
}
err = repo.Create(context.Background(), existingRole)
assert.NoError(t, err)
testCases := []struct {
name string
uid string
expectErr bool
expectNil bool
}{
{
name: "成功查詢角色",
uid: "admin_uid",
expectErr: false,
expectNil: false,
},
{
name: "查詢不存在的角色",
uid: "non_existent_uid",
expectErr: true,
expectNil: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.GetByUID(context.Background(), tc.uid)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
}
if tc.expectNil {
assert.Nil(t, result, "應該返回 nil")
} else {
assert.NotNil(t, result, "不應該返回 nil")
assert.Equal(t, existingRole.UID, result.UID, "UID 應相符")
assert.Equal(t, existingRole.Name, result.Name, "名稱應相符")
}
})
}
}
func TestRoleRepository_GetByID(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 預先建立測試角色
existingRole := &entity.Role{
ID: primitive.NewObjectID(),
Name: "Admin",
UID: "admin_uid",
ClientID: "client_1",
Status: 1,
}
err = repo.Create(context.Background(), existingRole)
assert.NoError(t, err)
testCases := []struct {
name string
id string
expectErr bool
expectNil bool
}{
{
name: "成功查詢角色",
id: existingRole.ID.Hex(),
expectErr: false,
expectNil: false,
},
{
name: "查詢不存在的角色",
id: primitive.NewObjectID().Hex(),
expectErr: true,
expectNil: true,
},
{
name: "提供無效的 ObjectID",
id: "invalid_id",
expectErr: true,
expectNil: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.GetByID(context.Background(), tc.id)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
}
if tc.expectNil {
assert.Nil(t, result, "應該返回 nil")
} else {
assert.NotNil(t, result, "不應該返回 nil")
assert.Equal(t, existingRole.ID, result.ID, "ID 應相符")
assert.Equal(t, existingRole.Name, result.Name, "名稱應相符")
}
})
}
}
func TestRoleRepository_List(t *testing.T) {
repo, tearDown, err := SetupTestRoleRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 預先建立測試角色
roles := []*entity.Role{
{
ID: primitive.NewObjectID(),
Name: "Admin",
UID: "admin_uid",
ClientID: "client_1",
Status: 1,
},
{
ID: primitive.NewObjectID(),
Name: "User",
UID: "user_uid",
ClientID: "client_1",
Status: 1,
},
{
ID: primitive.NewObjectID(),
Name: "Guest",
UID: "guest_uid",
ClientID: "client_2",
Status: 0,
},
}
// 插入測試資料
for _, role := range roles {
err := repo.Create(context.Background(), role)
assert.NoError(t, err)
}
testCases := []struct {
name string
query repository.ListQuery
expectLen int
expectErr bool
}{
{
name: "查詢所有角色",
query: repository.ListQuery{PageSize: 10, PageIndex: 1},
expectLen: 3,
expectErr: false,
},
{
name: "篩選名稱為 Admin",
query: repository.ListQuery{Name: ToPointer("Admin"), PageSize: 10, PageIndex: 1},
expectLen: 1,
expectErr: false,
},
{
name: "篩選特定 ClientID",
query: repository.ListQuery{ClientID: ToPointer("client_1"), PageSize: 10, PageIndex: 1},
expectLen: 2,
expectErr: false,
},
{
name: "篩選啟用 (Status=1) 的角色",
query: repository.ListQuery{Status: ToPointer(permission.Open), PageSize: 10, PageIndex: 1},
expectLen: 2,
expectErr: false,
},
{
name: "篩選特定 UID",
query: repository.ListQuery{UID: ToPointer("guest_uid"), PageSize: 10, PageIndex: 1},
expectLen: 1,
expectErr: false,
},
{
name: "測試分頁 PageSize=1, PageIndex=1",
query: repository.ListQuery{PageSize: 1, PageIndex: 1},
expectLen: 1,
expectErr: false,
},
{
name: "查詢無符合條件的角色",
query: repository.ListQuery{Name: ToPointer("NonExist"), PageSize: 10, PageIndex: 1},
expectLen: 0,
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, _, err := repo.List(context.Background(), tc.query)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.Len(t, result, tc.expectLen, "返回的角色數量應符合預期")
}
})
}
}