backend/pkg/permission/repository/permission_test.go

508 lines
12 KiB
Go

package repository
import (
"backend/pkg/permission/domain"
"backend/pkg/permission/domain/entity"
"backend/pkg/permission/domain/permission"
domainRepo "backend/pkg/permission/domain/repository"
"context"
"fmt"
"github.com/alicebob/miniredis/v2"
"github.com/zeromicro/go-zero/core/stores/redis"
"testing"
"time"
mgo "backend/pkg/library/mongo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zeromicro/go-zero/core/stores/cache"
"go.mongodb.org/mongo-driver/v2/bson"
)
func setupPermissionRepo(db string) (domainRepo.PermissionRepository, func(), error) {
h, p, tearDown, err := startMongoContainer()
if err != nil {
return nil, nil, err
}
s, _ := miniredis.Run()
conf := &mgo.Conf{
Schema: mongoSchema,
Host: fmt.Sprintf("%s:%s", h, p),
Database: db,
MaxStaleness: 300,
MaxPoolSize: 100,
MinPoolSize: 100,
MaxConnIdleTime: 300,
Compressors: []string{},
EnableStandardReadWriteSplitMode: false,
ConnectTimeoutMs: 3000,
}
cacheConf := cache.CacheConf{
cache.NodeConf{
RedisConf: redis.RedisConf{
Host: s.Addr(),
Type: redis.NodeType,
},
Weight: 100,
},
}
cacheOpts := []cache.Option{
cache.WithExpiry(1000 * time.Microsecond),
cache.WithNotFoundExpiry(1000 * time.Microsecond),
}
param := PermissionRepositoryParam{
Conf: conf,
CacheConf: cacheConf,
CacheOpts: cacheOpts,
}
repo := NewPermissionRepository(param)
_, _ = repo.Index20251009001UP(context.Background())
return repo, tearDown, nil
}
func TestPermissionRepository_FindOne(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testPerm := &entity.Permission{
ID: bson.NewObjectID(),
Name: "test.permission",
State: domain.RecordActive,
Type: permission.TypeBackend,
}
testPerm.CreateTime = time.Now().Unix()
testPerm.UpdateTime = testPerm.CreateTime
// 插入測試數據
_, err = repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, testPerm)
require.NoError(t, err)
tests := []struct {
name string
id string
wantErr error
check func(*testing.T, *entity.Permission)
}{
{
name: "找到存在的權限",
id: testPerm.ID.Hex(),
wantErr: nil,
check: func(t *testing.T, perm *entity.Permission) {
assert.Equal(t, testPerm.Name, perm.Name)
assert.Equal(t, testPerm.State, perm.State)
},
},
{
name: "無效的 ObjectID",
id: "invalid-id",
wantErr: ErrInvalidObjectID,
check: nil,
},
{
name: "不存在的權限",
id: bson.NewObjectID().Hex(),
wantErr: ErrNotFound,
check: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
perm, err := repo.FindOne(ctx, tt.id)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
assert.Nil(t, perm)
} else {
assert.NoError(t, err)
assert.NotNil(t, perm)
if tt.check != nil {
tt.check(t, perm)
}
}
})
}
}
func TestPermissionRepository_FindByName(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testPerms := []*entity.Permission{
{
ID: bson.NewObjectID(),
Name: "user.list",
State: domain.RecordActive,
Type: permission.TypeBackend,
},
{
ID: bson.NewObjectID(),
Name: "user.create",
State: domain.RecordActive,
Type: permission.TypeBackend,
},
}
for _, perm := range testPerms {
perm.CreateTime = time.Now().Unix()
perm.UpdateTime = perm.CreateTime
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
require.NoError(t, err)
}
tests := []struct {
name string
permName string
wantErr error
wantName string
}{
{
name: "找到存在的權限",
permName: "user.list",
wantErr: nil,
wantName: "user.list",
},
{
name: "找到另一個權限",
permName: "user.create",
wantErr: nil,
wantName: "user.create",
},
{
name: "不存在的權限",
permName: "user.delete",
wantErr: ErrNotFound,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
perm, err := repo.FindByName(ctx, tt.permName)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
assert.Nil(t, perm)
} else {
assert.NoError(t, err)
assert.NotNil(t, perm)
assert.Equal(t, tt.wantName, perm.Name)
}
})
}
}
func TestPermissionRepository_GetByNames(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testPerms := []*entity.Permission{
{ID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
{ID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
{ID: bson.NewObjectID(), Name: "user.update", State: domain.RecordActive},
}
for _, perm := range testPerms {
perm.CreateTime = time.Now().Unix()
perm.UpdateTime = perm.CreateTime
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
require.NoError(t, err)
}
tests := []struct {
name string
names []string
wantCount int
wantErr error
}{
{
name: "找到多個權限",
names: []string{"user.list", "user.create"},
wantCount: 2,
wantErr: nil,
},
{
name: "找到單一權限",
names: []string{"user.update"},
wantCount: 1,
wantErr: nil,
},
{
name: "找到所有權限",
names: []string{"user.list", "user.create", "user.update"},
wantCount: 3,
wantErr: nil,
},
{
name: "部分存在的權限",
names: []string{"user.list", "user.delete"},
wantCount: 1,
wantErr: nil,
},
{
name: "不存在的權限",
names: []string{"admin.super"},
wantCount: 0,
wantErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
perms, err := repo.GetByNames(ctx, tt.names)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
} else {
assert.NoError(t, err)
assert.Len(t, perms, tt.wantCount)
}
})
}
}
func TestPermissionRepository_FindByHTTP(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testPerms := []*entity.Permission{
{
ID: bson.NewObjectID(),
Name: "user.list",
HTTPPath: "/api/users",
HTTPMethod: "GET",
State: domain.RecordActive,
},
{
ID: bson.NewObjectID(),
Name: "user.create",
HTTPPath: "/api/users",
HTTPMethod: "POST",
State: domain.RecordActive,
},
}
for _, perm := range testPerms {
perm.CreateTime = time.Now().Unix()
perm.UpdateTime = perm.CreateTime
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
require.NoError(t, err)
}
tests := []struct {
name string
path string
method string
wantName string
wantErr error
}{
{
name: "找到 GET 權限",
path: "/api/users",
method: "GET",
wantName: "user.list",
wantErr: nil,
},
{
name: "找到 POST 權限",
path: "/api/users",
method: "POST",
wantName: "user.create",
wantErr: nil,
},
{
name: "不存在的路徑",
path: "/api/admin",
method: "GET",
wantErr: ErrNotFound,
},
{
name: "不存在的方法",
path: "/api/users",
method: "DELETE",
wantErr: ErrNotFound,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
perm, err := repo.FindByHTTP(ctx, tt.path, tt.method)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
assert.Nil(t, perm)
} else {
assert.NoError(t, err)
assert.NotNil(t, perm)
assert.Equal(t, tt.wantName, perm.Name)
assert.Equal(t, tt.path, perm.HTTPPath)
assert.Equal(t, tt.method, perm.HTTPMethod)
}
})
}
}
func TestPermissionRepository_List(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
parent := &entity.Permission{
ID: bson.NewObjectID(),
ParentID: bson.ObjectID{},
Name: "user",
State: domain.RecordActive,
Type: permission.TypeBackend,
}
parent.CreateTime = time.Now().Unix()
parent.UpdateTime = parent.CreateTime
child := &entity.Permission{
ID: bson.NewObjectID(),
ParentID: parent.ID,
Name: "user.list",
State: domain.RecordActive,
Type: permission.TypeBackend,
}
child.CreateTime = time.Now().Unix()
child.UpdateTime = child.CreateTime
inactiveChild := &entity.Permission{
ID: bson.NewObjectID(),
ParentID: parent.ID,
Name: "user.delete",
State: domain.RecordInactive,
Type: permission.TypeBackend,
}
inactiveChild.CreateTime = time.Now().Unix()
inactiveChild.UpdateTime = inactiveChild.CreateTime
for _, perm := range []*entity.Permission{parent, child, inactiveChild} {
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
require.NoError(t, err)
}
tests := []struct {
name string
filter domainRepo.PermissionFilter
wantCount int
wantNames []string
}{
{
name: "列出所有權限",
filter: domainRepo.PermissionFilter{},
wantCount: 3,
},
{
name: "只列出啟用的權限",
filter: domainRepo.PermissionFilter{
Status: func() *permission.RecordState {
s := domain.RecordActive
return &s
}(),
},
wantCount: 2,
wantNames: []string{"user", "user.list"},
},
{
name: "只列出停用的權限",
filter: domainRepo.PermissionFilter{
Status: func() *permission.RecordState {
s := domain.RecordInactive
return &s
}(),
},
wantCount: 1,
wantNames: []string{"user.delete"},
},
{
name: "按類型過濾",
filter: domainRepo.PermissionFilter{
Type: func() *permission.Type {
t := permission.TypeBackend
return &t
}(),
},
wantCount: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
perms, err := repo.List(ctx, tt.filter)
assert.NoError(t, err)
assert.Len(t, perms, tt.wantCount)
if len(tt.wantNames) > 0 {
names := make([]string, len(perms))
for i, p := range perms {
names[i] = p.Name
}
for _, wantName := range tt.wantNames {
assert.Contains(t, names, wantName)
}
}
})
}
}
func TestPermissionRepository_ListActive(t *testing.T) {
repo, tearDown, err := setupPermissionRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
activePerms := []*entity.Permission{
{ID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
{ID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
}
inactivePerms := []*entity.Permission{
{ID: bson.NewObjectID(), Name: "user.delete", State: domain.RecordInactive},
{ID: bson.NewObjectID(), Name: "user.admin", State: domain.RecordDeleted},
}
allPerms := append(activePerms, inactivePerms...)
for _, perm := range allPerms {
perm.CreateTime = time.Now().Unix()
perm.UpdateTime = perm.CreateTime
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
require.NoError(t, err)
}
t.Run("只返回啟用的權限", func(t *testing.T) {
perms, err := repo.ListActive(ctx)
assert.NoError(t, err)
assert.Len(t, perms, 2)
for _, perm := range perms {
assert.Equal(t, domain.RecordActive, perm.State)
}
})
}