init push
This commit is contained in:
501
internal/service/role_service_test.go
Normal file
501
internal/service/role_service_test.go
Normal file
@@ -0,0 +1,501 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"wucher/internal/domain/auth"
|
||||
)
|
||||
|
||||
type roleServiceRepoMock struct {
|
||||
createCalled bool
|
||||
updateCalled bool
|
||||
deleteCalled bool
|
||||
getByIDCalled bool
|
||||
getByNameCalled bool
|
||||
listCalled bool
|
||||
getPermByIDCalled bool
|
||||
getPermByKeyCalled bool
|
||||
updatePermCalled bool
|
||||
assignPermCalled bool
|
||||
removePermCalled bool
|
||||
listPermCalled bool
|
||||
|
||||
lastCreate *auth.Role
|
||||
lastUpdate *auth.Role
|
||||
lastDelete []byte
|
||||
lastListFilter string
|
||||
lastListSort string
|
||||
lastListLimit int
|
||||
lastListOffset int
|
||||
lastGetPermID []byte
|
||||
lastGetPermKey string
|
||||
lastAssignRoleID []byte
|
||||
lastAssignPermissionID []byte
|
||||
lastRemoveRoleID []byte
|
||||
lastRemovePermissionID []byte
|
||||
lastPermFilter string
|
||||
lastPermSort string
|
||||
lastPermLimit int
|
||||
lastPermOffset int
|
||||
|
||||
roleByID *auth.Role
|
||||
roleByName *auth.Role
|
||||
listRoles []auth.Role
|
||||
listTotal int64
|
||||
permissionByID *auth.Permission
|
||||
permissionByKey *auth.Permission
|
||||
assignedPermission *auth.RolePermission
|
||||
listPermissions []auth.Permission
|
||||
listPermissionsTotal int64
|
||||
|
||||
createErr error
|
||||
updateErr error
|
||||
deleteErr error
|
||||
getByIDErr error
|
||||
getByNameErr error
|
||||
listErr error
|
||||
getPermByIDErr error
|
||||
getPermByKeyErr error
|
||||
updatePermErr error
|
||||
assignPermErr error
|
||||
removePermErr error
|
||||
listPermErr error
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) CreateRole(_ context.Context, role *auth.Role) error {
|
||||
m.createCalled = true
|
||||
m.lastCreate = role
|
||||
return m.createErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) UpdateRole(_ context.Context, role *auth.Role) error {
|
||||
m.updateCalled = true
|
||||
m.lastUpdate = role
|
||||
return m.updateErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) DeleteRole(_ context.Context, id []byte) error {
|
||||
m.deleteCalled = true
|
||||
m.lastDelete = id
|
||||
return m.deleteErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) GetRoleByID(_ context.Context, _ []byte) (*auth.Role, error) {
|
||||
m.getByIDCalled = true
|
||||
return m.roleByID, m.getByIDErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) GetRoleByName(_ context.Context, _ string) (*auth.Role, error) {
|
||||
m.getByNameCalled = true
|
||||
return m.roleByName, m.getByNameErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) ListRoles(_ context.Context, filterName string, sort string, limit, offset int) ([]auth.Role, int64, error) {
|
||||
m.listCalled = true
|
||||
m.lastListFilter = filterName
|
||||
m.lastListSort = sort
|
||||
m.lastListLimit = limit
|
||||
m.lastListOffset = offset
|
||||
return m.listRoles, m.listTotal, m.listErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) GetPermissionByID(_ context.Context, id []byte) (*auth.Permission, error) {
|
||||
m.getPermByIDCalled = true
|
||||
m.lastGetPermID = id
|
||||
return m.permissionByID, m.getPermByIDErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) GetPermissionByKey(_ context.Context, key string) (*auth.Permission, error) {
|
||||
m.getPermByKeyCalled = true
|
||||
m.lastGetPermKey = key
|
||||
return m.permissionByKey, m.getPermByKeyErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) UpdatePermission(_ context.Context, permission *auth.Permission) error {
|
||||
m.updatePermCalled = true
|
||||
m.permissionByID = permission
|
||||
return m.updatePermErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) ListPermissions(_ context.Context, filter, sort string, limit, offset int) ([]auth.Permission, int64, error) {
|
||||
m.listPermCalled = true
|
||||
m.lastPermFilter = filter
|
||||
m.lastPermSort = sort
|
||||
m.lastPermLimit = limit
|
||||
m.lastPermOffset = offset
|
||||
return m.listPermissions, m.listPermissionsTotal, m.listPermErr
|
||||
}
|
||||
func (m *roleServiceRepoMock) ListPermissionsByRoleID(_ context.Context, _ []byte) ([]auth.Permission, error) {
|
||||
return []auth.Permission{}, nil
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) HasRolePermission(_ context.Context, _ []byte, _ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) AssignPermission(_ context.Context, roleID, permissionID []byte) (*auth.RolePermission, error) {
|
||||
m.assignPermCalled = true
|
||||
m.lastAssignRoleID = roleID
|
||||
m.lastAssignPermissionID = permissionID
|
||||
if m.assignedPermission == nil {
|
||||
m.assignedPermission = &auth.RolePermission{RoleID: roleID, PermissionID: permissionID}
|
||||
}
|
||||
return m.assignedPermission, m.assignPermErr
|
||||
}
|
||||
|
||||
func (m *roleServiceRepoMock) RemovePermission(_ context.Context, roleID []byte, permissionID []byte) error {
|
||||
m.removePermCalled = true
|
||||
m.lastRemoveRoleID = roleID
|
||||
m.lastRemovePermissionID = permissionID
|
||||
return m.removePermErr
|
||||
}
|
||||
|
||||
func TestRoleService_Create_Validation(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if err := svc.Create(context.Background(), &auth.Role{Name: " "}); err == nil {
|
||||
t.Fatalf("expected validation error")
|
||||
}
|
||||
if repo.createCalled {
|
||||
t.Fatalf("expected repo.CreateRole not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_Create_RepoError(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{createErr: errors.New("db error")}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
err := svc.Create(context.Background(), &auth.Role{Name: "admin"})
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if !repo.createCalled {
|
||||
t.Fatalf("expected repo.CreateRole called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_Update_Validation(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if err := svc.Update(context.Background(), &auth.Role{Name: ""}); err == nil {
|
||||
t.Fatalf("expected validation error")
|
||||
}
|
||||
if repo.updateCalled {
|
||||
t.Fatalf("expected repo.UpdateRole not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_Update_Success(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
err := svc.Update(context.Background(), &auth.Role{Name: "admin"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !repo.updateCalled {
|
||||
t.Fatalf("expected repo.UpdateRole called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_Delete_Success(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
id := []byte("id")
|
||||
err := svc.Delete(context.Background(), id)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !repo.deleteCalled {
|
||||
t.Fatalf("expected repo.DeleteRole called")
|
||||
}
|
||||
if string(repo.lastDelete) != string(id) {
|
||||
t.Fatalf("expected delete id passed to repo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_GetByID_Success(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{roleByID: &auth.Role{Name: "admin"}}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
role, err := svc.GetByID(context.Background(), []byte("id"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if role == nil || role.Name != "admin" {
|
||||
t.Fatalf("unexpected role")
|
||||
}
|
||||
if !repo.getByIDCalled {
|
||||
t.Fatalf("expected repo.GetRoleByID called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_GetByName_Success(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{roleByName: &auth.Role{Name: "admin"}}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
role, err := svc.GetByName(context.Background(), "admin")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if role == nil || role.Name != "admin" {
|
||||
t.Fatalf("unexpected role")
|
||||
}
|
||||
if !repo.getByNameCalled {
|
||||
t.Fatalf("expected repo.GetRoleByName called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_GetPermissionByID(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
perm := &auth.Permission{Name: "Users Read", Key: "users.read"}
|
||||
repo := &roleServiceRepoMock{permissionByID: perm}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
id := []byte("perm-id")
|
||||
got, err := svc.GetPermissionByID(context.Background(), id)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got == nil || got.Key != "users.read" {
|
||||
t.Fatalf("unexpected permission: %+v", got)
|
||||
}
|
||||
if !repo.getPermByIDCalled {
|
||||
t.Fatalf("expected repo.GetPermissionByID called")
|
||||
}
|
||||
if string(repo.lastGetPermID) != string(id) {
|
||||
t.Fatalf("expected id forwarded to repo")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repo error", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{getPermByIDErr: errors.New("db error")}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if _, err := svc.GetPermissionByID(context.Background(), []byte("perm-id")); err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleService_GetPermissionByKey(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{
|
||||
permissionByKey: &auth.Permission{Name: "Delete User", Key: "user.delete"},
|
||||
}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
got, err := svc.GetPermissionByKey(context.Background(), "user.delete")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got == nil || got.Key != "user.delete" {
|
||||
t.Fatalf("unexpected permission: %+v", got)
|
||||
}
|
||||
if !repo.getPermByKeyCalled {
|
||||
t.Fatalf("expected repo.GetPermissionByKey called")
|
||||
}
|
||||
if repo.lastGetPermKey != "user.delete" {
|
||||
t.Fatalf("expected key forwarded to repo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleService_UpdatePermission(t *testing.T) {
|
||||
t.Run("validation", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if err := svc.UpdatePermission(context.Background(), &auth.Permission{Name: " ", Key: "user.delete"}); err == nil {
|
||||
t.Fatalf("expected validation error for empty name")
|
||||
}
|
||||
if err := svc.UpdatePermission(context.Background(), &auth.Permission{Name: "Delete User", Key: " "}); err == nil {
|
||||
t.Fatalf("expected validation error for empty key")
|
||||
}
|
||||
if repo.updatePermCalled {
|
||||
t.Fatalf("expected repo.UpdatePermission not called")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
perm := &auth.Permission{Name: "Delete User", Key: "user.delete", RequiresPIN: true}
|
||||
if err := svc.UpdatePermission(context.Background(), perm); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !repo.updatePermCalled {
|
||||
t.Fatalf("expected repo.UpdatePermission called")
|
||||
}
|
||||
if repo.permissionByID == nil || !repo.permissionByID.RequiresPIN {
|
||||
t.Fatalf("expected permission forwarded to repo")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleService_AssignPermission(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
roleID := []byte("role-id")
|
||||
permID := []byte("perm-id")
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
rp, err := svc.AssignPermission(context.Background(), roleID, permID)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if rp == nil {
|
||||
t.Fatalf("expected role permission")
|
||||
}
|
||||
if !repo.assignPermCalled {
|
||||
t.Fatalf("expected repo.AssignPermission called")
|
||||
}
|
||||
if string(repo.lastAssignRoleID) != string(roleID) || string(repo.lastAssignPermissionID) != string(permID) {
|
||||
t.Fatalf("expected roleID/permissionID forwarded to repo")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repo error", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{assignPermErr: errors.New("assign error")}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if _, err := svc.AssignPermission(context.Background(), []byte("role-id"), []byte("perm-id")); err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleService_RemovePermission(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
roleID := []byte("role-id")
|
||||
permID := []byte("perm-id")
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
err := svc.RemovePermission(context.Background(), roleID, permID)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !repo.removePermCalled {
|
||||
t.Fatalf("expected repo.RemovePermission called")
|
||||
}
|
||||
if string(repo.lastRemoveRoleID) != string(roleID) || string(repo.lastRemovePermissionID) != string(permID) {
|
||||
t.Fatalf("expected roleID/permissionID forwarded to repo")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repo error", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{removePermErr: errors.New("remove error")}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if err := svc.RemovePermission(context.Background(), []byte("role-id"), []byte("perm-id")); err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleService_ListPermissions(t *testing.T) {
|
||||
t.Run("normalize sort and forward args", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{
|
||||
listPermissions: []auth.Permission{{Name: "Users Read", Key: "users.read"}},
|
||||
listPermissionsTotal: 1,
|
||||
}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
perms, total, err := svc.ListPermissions(context.Background(), "users", "-key", 10, 20)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(perms) != 1 || perms[0].Key != "users.read" || total != 1 {
|
||||
t.Fatalf("unexpected list result: perms=%+v total=%d", perms, total)
|
||||
}
|
||||
if !repo.listPermCalled {
|
||||
t.Fatalf("expected repo.ListPermissions called")
|
||||
}
|
||||
if repo.lastPermFilter != "users" {
|
||||
t.Fatalf("expected filter forwarded")
|
||||
}
|
||||
if repo.lastPermSort != "`key` DESC" {
|
||||
t.Fatalf("expected normalized permission sort, got %q", repo.lastPermSort)
|
||||
}
|
||||
if repo.lastPermLimit != 10 || repo.lastPermOffset != 20 {
|
||||
t.Fatalf("expected limit/offset forwarded")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repo error", func(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{listPermErr: errors.New("list error")}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
if _, _, err := svc.ListPermissions(context.Background(), "", "bad", 10, 0); err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if repo.lastPermSort != "" {
|
||||
t.Fatalf("unexpected sort for invalid input, got %q", repo.lastPermSort)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleService_List_NormalizeSort(t *testing.T) {
|
||||
repo := &roleServiceRepoMock{}
|
||||
svc := NewRoleService(repo)
|
||||
|
||||
_, _, err := svc.List(context.Background(), "adm", "-created_at", 10, 20)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !repo.listCalled {
|
||||
t.Fatalf("expected repo.ListRoles called")
|
||||
}
|
||||
if repo.lastListFilter != "adm" {
|
||||
t.Fatalf("expected filter passed to repo")
|
||||
}
|
||||
if repo.lastListSort != "created_at DESC" {
|
||||
t.Fatalf("expected normalized sort, got %q", repo.lastListSort)
|
||||
}
|
||||
if repo.lastListLimit != 10 || repo.lastListOffset != 20 {
|
||||
t.Fatalf("expected limit/offset passed to repo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeSort(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"name": "name ASC",
|
||||
"-name": "name DESC",
|
||||
"created_at": "created_at ASC",
|
||||
"-created_at": "created_at DESC",
|
||||
"updated_at": "updated_at ASC",
|
||||
"-updated_at": "updated_at DESC",
|
||||
"": "",
|
||||
"bad": "",
|
||||
}
|
||||
for in, want := range cases {
|
||||
if got := normalizeSort(in); got != want {
|
||||
t.Fatalf("normalizeSort(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizePermissionSort(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"name": "name ASC",
|
||||
"-name": "name DESC",
|
||||
"key": "`key` ASC",
|
||||
"-key": "`key` DESC",
|
||||
"created_at": "created_at ASC",
|
||||
"-created_at": "created_at DESC",
|
||||
"updated_at": "updated_at ASC",
|
||||
"-updated_at": "updated_at DESC",
|
||||
"": "",
|
||||
"bad": "",
|
||||
}
|
||||
for in, want := range cases {
|
||||
if got := normalizePermissionSort(in); got != want {
|
||||
t.Fatalf("normalizePermissionSort(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user