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

475 lines
11 KiB
Go
Raw Normal View History

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 SetupTestPermissionRepository(db string) (repository.PermissionRepository, 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 := PermissionRepositoryParam{
Conf: conf,
}
repo := NewPermissionRepository(param)
_, _ = repo.Index20250214UP(context.Background())
return repo, tearDown, nil
}
// 測試 Insert
func TestPermissionRepository_Insert(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
testCases := []struct {
name string
input entity.Permission
expectErr bool
}{
{
name: "成功插入",
input: entity.Permission{
Name: "test-permission",
HTTPMethod: "GET",
HTTPPath: "/test",
Status: 1,
Type: permission.BackendUser,
},
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Insert(context.Background(), tc.input)
if tc.expectErr {
assert.NotNil(t, err, "應該要返回錯誤")
} else {
assert.Nil(t, err, "不應該返回錯誤")
}
})
}
}
func TestPermissionRepository_Update(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 先插入一條測試數據
existingPermission := entity.Permission{
Name: "original-permission",
HTTPMethod: "GET",
HTTPPath: "/original",
Status: 1,
Type: permission.BackendUser,
}
err = repo.Insert(context.Background(), existingPermission)
assert.Nil(t, err, "插入初始數據失敗")
// 取得剛插入的 ID
found, err := repo.FindOne(context.Background(), repository.PermissionQuery{
HTTPMethod: existingPermission.HTTPMethod,
HTTPPath: existingPermission.HTTPPath,
})
assert.Nil(t, err, "應該能找到插入的權限")
id := found.ID.Hex()
testCases := []struct {
name string
id string
updateReq repository.UpdatePermission
expectErr bool
}{
{
name: "成功更新名稱",
id: id,
updateReq: repository.UpdatePermission{
Name: ToPointer("updated-name"),
},
expectErr: false,
},
{
name: "成功更新 HTTP 方法",
id: id,
updateReq: repository.UpdatePermission{
HTTPMethod: ToPointer("PUT"),
},
expectErr: false,
},
{
name: "成功更新 HTTP 路徑",
id: id,
updateReq: repository.UpdatePermission{
HTTPPath: ToPointer("/updated-path"),
},
expectErr: false,
},
{
name: "成功更新狀態",
id: id,
updateReq: repository.UpdatePermission{
Status: ToPointer(permission.Open),
},
expectErr: false,
},
{
name: "成功更新多個欄位",
id: id,
updateReq: repository.UpdatePermission{
Name: ToPointer("multi-updated"),
HTTPMethod: ToPointer("PATCH"),
HTTPPath: ToPointer("/multi-update"),
Status: ToPointer(permission.Close),
},
expectErr: false,
},
{
name: "更新失敗 - 錯誤的 ObjectID",
id: "invalid",
updateReq: repository.UpdatePermission{
Name: ToPointer("invalid-update"),
},
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Update(context.Background(), tc.id, tc.updateReq)
if tc.expectErr {
assert.NotNil(t, err, "應該要返回錯誤")
} else {
assert.Nil(t, err, "不應該返回錯誤")
// 確保更新後的資料正確
updated, err := repo.GetAll(context.Background(), nil)
assert.Nil(t, err, "應該能找到更新後的權限")
if tc.updateReq.Name != nil {
assert.Equal(t, *tc.updateReq.Name, updated[0].Name, "名稱應該被更新")
}
if tc.updateReq.HTTPMethod != nil {
assert.Equal(t, *tc.updateReq.HTTPMethod, updated[0].HTTPMethod, "HTTP 方法應該被更新")
}
if tc.updateReq.HTTPPath != nil {
assert.Equal(t, *tc.updateReq.HTTPPath, updated[0].HTTPPath, "HTTP 路徑應該被更新")
}
if tc.updateReq.Status != nil {
assert.Equal(t, *tc.updateReq.Status, updated[0].Status, "狀態應該被更新")
}
}
})
}
}
// 測試 Delete 方法
func TestPermissionRepository_Delete(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 插入測試數據
permission := entity.Permission{
ID: primitive.NewObjectID(),
Name: "delete-test",
HTTPMethod: "DELETE",
HTTPPath: "/test-delete",
Status: 1,
}
err = repo.Insert(context.Background(), permission)
assert.NoError(t, err, "插入測試數據時不應發生錯誤")
testCases := []struct {
name string
id string
expectErr bool
}{
{
name: "成功刪除存在的權限",
id: permission.ID.Hex(),
expectErr: false,
},
{
name: "刪除不存在的權限",
id: primitive.NewObjectID().Hex(),
expectErr: false, // MongoDB 刪除不存在的 ID 仍然不會報錯
},
{
name: "刪除無效的 ObjectID",
id: "invalid-object-id",
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := repo.Delete(context.Background(), tc.id)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
}
})
}
}
// 測試 GetAll 方法
func TestPermissionRepository_GetAll(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 插入測試數據
testPermissions := []entity.Permission{
{
ID: primitive.NewObjectID(),
Name: "read",
HTTPMethod: "GET",
HTTPPath: "/read",
Status: permission.Open,
},
{
ID: primitive.NewObjectID(),
Name: "write",
HTTPMethod: "POST",
HTTPPath: "/write",
Status: permission.Close,
},
}
for _, p := range testPermissions {
err := repo.Insert(context.Background(), p)
assert.NoError(t, err, "插入測試數據時不應該發生錯誤")
}
testCases := []struct {
name string
status *permission.Status
expectLen int
expectErr bool
}{
{
name: "查詢所有權限",
status: nil,
expectLen: 2,
expectErr: false,
},
{
name: "查詢開啟的權限",
status: ToPointer(permission.Open),
expectLen: 1,
expectErr: false,
},
{
name: "查詢關閉的權限",
status: ToPointer(permission.Close),
expectLen: 1,
expectErr: false,
},
{
name: "查詢不存在的權限狀態",
status: ToPointer(permission.Status(-1)),
expectLen: 0,
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.GetAll(context.Background(), tc.status)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.Len(t, result, tc.expectLen, "查詢結果數量不符合預期")
}
})
}
}
// 測試 GetAllIntoIDMap 方法
func TestPermissionRepository_GetAllIntoIDMap(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 插入測試數據
testPermissions := []entity.Permission{
{
ID: primitive.NewObjectID(),
Name: "read",
HTTPMethod: "GET",
HTTPPath: "/read",
Status: permission.Open,
},
{
ID: primitive.NewObjectID(),
Name: "write",
HTTPMethod: "POST",
HTTPPath: "/write",
Status: permission.Close,
},
}
for _, p := range testPermissions {
err := repo.Insert(context.Background(), p)
assert.NoError(t, err, "插入測試數據時不應該發生錯誤")
}
testCases := []struct {
name string
status *permission.Status
expectLen int
expectErr bool
}{
{
name: "查詢所有權限並轉為 Map",
status: nil,
expectLen: 2,
expectErr: false,
},
{
name: "查詢開啟的權限並轉為 Map",
status: ToPointer(permission.Open),
expectLen: 1,
expectErr: false,
},
{
name: "查詢關閉的權限並轉為 Map",
status: ToPointer(permission.Close),
expectLen: 1,
expectErr: false,
},
{
name: "查詢不存在的權限狀態並轉為 Map",
status: ToPointer(permission.Status(-1)),
expectLen: 0,
expectErr: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.GetAllIntoIDMap(context.Background(), tc.status)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.Len(t, result, tc.expectLen, "查詢結果數量不符合預期")
// 確保 Map 的 key 是權限名稱
for key, permission := range result {
assert.Equal(t, key, permission.Name, "Map 的 Key 應該與 Name 相符")
}
}
})
}
}
func TestPermissionRepository_FindByNames(t *testing.T) {
repo, tearDown, err := SetupTestPermissionRepository("testDB")
assert.NoError(t, err)
defer tearDown()
// 測試數據
testPermissions := []entity.Permission{
{
ID: primitive.NewObjectID(),
Name: "read-data",
HTTPMethod: "GET",
HTTPPath: "/data",
Status: 1,
},
{
ID: primitive.NewObjectID(),
Name: "write-data",
HTTPMethod: "POST",
HTTPPath: "/data",
Status: 1,
},
}
// 插入測試數據
for _, perm := range testPermissions {
err := repo.Insert(context.Background(), perm)
assert.NoError(t, err)
}
testCases := []struct {
name string
input []string
expectLen int
expectErr bool
}{
{
name: "成功查詢單個名稱",
input: []string{"read-data"},
expectLen: 1,
expectErr: false,
},
{
name: "成功查詢多個名稱",
input: []string{"read-data", "write-data"},
expectLen: 2,
expectErr: false,
},
{
name: "查詢名稱不存在時應返回空結果",
input: []string{"unknown-permission"},
expectLen: 0,
expectErr: false,
},
{
name: "當查詢發生錯誤時,應返回錯誤",
input: nil, // 無效查詢
expectLen: 0,
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := repo.FindByNames(context.Background(), tc.input)
if tc.expectErr {
assert.Error(t, err, "應該返回錯誤")
} else {
assert.NoError(t, err, "不應該返回錯誤")
assert.Len(t, result, tc.expectLen, "返回的數據長度應符合預期")
}
})
}
}
func ToPointer[T any](v T) *T {
return &v
}