265 lines
6.8 KiB
Go
265 lines
6.8 KiB
Go
package user
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"cardverse/internal/pkg/utils"
|
|
)
|
|
|
|
func TestService_Create_Success(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByEmailFunc: func(email string) (*User, error) {
|
|
return nil, errors.New("record not found")
|
|
},
|
|
createFunc: func(u *User) error {
|
|
u.ID = 1
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
req := CreateUserRequest{Name: "Budi", Email: "budi@mail.com", Password: "rahasia123"}
|
|
newUser, err := svc.Create(nil, req)
|
|
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if newUser.Email != req.Email {
|
|
t.Errorf("expected email %s, got %s", req.Email, newUser.Email)
|
|
}
|
|
if newUser.Password == req.Password {
|
|
t.Error("stored password should be hashed, not plain text")
|
|
}
|
|
if !utils.CheckPassword(newUser.Password, req.Password) {
|
|
t.Error("hashed password does not match original password")
|
|
}
|
|
}
|
|
|
|
func TestService_Create_AdminRole_ForbiddenForRegularAdmin(t *testing.T) {
|
|
adminID := uint(5)
|
|
repo := &mockRepository{
|
|
findByEmailFunc: func(email string) (*User, error) {
|
|
return nil, errors.New("record not found")
|
|
},
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Role: RoleAdmin}, nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
req := CreateUserRequest{Name: "New Admin", Email: "admin2@mail.com", Password: "rahasia123", Role: RoleAdmin}
|
|
_, err := svc.Create(&adminID, req)
|
|
|
|
if !errors.Is(err, ErrForbiddenRoleCreation) {
|
|
t.Fatalf("expected ErrForbiddenRoleCreation for regular admin creating another admin, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestService_Create_AdminRole_AllowedForSuperAdmin(t *testing.T) {
|
|
superAdminID := uint(1)
|
|
repo := &mockRepository{
|
|
findByEmailFunc: func(email string) (*User, error) {
|
|
return nil, errors.New("record not found")
|
|
},
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Role: RoleSuperAdmin}, nil
|
|
},
|
|
createFunc: func(u *User) error {
|
|
u.ID = 10
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
req := CreateUserRequest{Name: "New Admin", Email: "admin2@mail.com", Password: "rahasia123", Role: RoleAdmin}
|
|
newAdmin, err := svc.Create(&superAdminID, req)
|
|
|
|
if err != nil {
|
|
t.Fatalf("expected no error for superadmin creating an admin, got: %v", err)
|
|
}
|
|
if newAdmin.Role != RoleAdmin {
|
|
t.Errorf("expected role %s, got %s", RoleAdmin, newAdmin.Role)
|
|
}
|
|
}
|
|
|
|
func TestService_Create_EmailAlreadyTaken(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByEmailFunc: func(email string) (*User, error) {
|
|
return &User{ID: 99, Email: email}, nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
_, err := svc.Create(nil, CreateUserRequest{Name: "Budi", Email: "budi@mail.com", Password: "rahasia123"})
|
|
|
|
if !errors.Is(err, ErrEmailTaken) {
|
|
t.Fatalf("expected ErrEmailTaken, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestService_GetByID_Success(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Name: "Budi"}, nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
u, err := svc.GetByID(1)
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if u.ID != 1 {
|
|
t.Errorf("expected ID 1, got: %d", u.ID)
|
|
}
|
|
}
|
|
|
|
func TestService_GetByID_NotFound(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return nil, errors.New("record not found")
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
_, err := svc.GetByID(999)
|
|
if !errors.Is(err, ErrUserNotFound) {
|
|
t.Fatalf("expected ErrUserNotFound, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestService_Update_Success(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Name: "Old Name"}, nil
|
|
},
|
|
updateFunc: func(u *User) error {
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
updated, err := svc.Update(1, 1, UpdateUserRequest{Name: "New Name"})
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if updated.Name != "New Name" {
|
|
t.Errorf("expected Name 'New Name', got: '%s'", updated.Name)
|
|
}
|
|
}
|
|
|
|
func TestService_UpdateAvatar_Success(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Name: "User Test"}, nil
|
|
},
|
|
updateFunc: func(u *User) error {
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
updated, err := svc.UpdateAvatar(1, "/images/avatars/avatar_1_123.png")
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if updated.AvatarURL == nil || *updated.AvatarURL != "/images/avatars/avatar_1_123.png" {
|
|
t.Errorf("expected AvatarURL '/images/avatars/avatar_1_123.png', got: '%v'", updated.AvatarURL)
|
|
}
|
|
}
|
|
|
|
func TestService_Update_NotFound(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return nil, errors.New("record not found")
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
_, err := svc.Update(1, 1, UpdateUserRequest{Name: "Anything"})
|
|
if !errors.Is(err, ErrUserNotFound) {
|
|
t.Fatalf("expected ErrUserNotFound, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestService_SuspendAndUnsuspend_Success(t *testing.T) {
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id, Status: StatusActive}, nil
|
|
},
|
|
updateFunc: func(u *User) error {
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
suspended, err := svc.SuspendUser(1, 2)
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if suspended.Status != StatusSuspended {
|
|
t.Errorf("expected status 'suspended', got: '%s'", suspended.Status)
|
|
}
|
|
|
|
unsuspended, err := svc.UnsuspendUser(1, 2)
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if unsuspended.Status != StatusActive {
|
|
t.Errorf("expected status 'active', got: '%s'", unsuspended.Status)
|
|
}
|
|
}
|
|
|
|
func TestService_Delete_Success(t *testing.T) {
|
|
deleteCalled := false
|
|
repo := &mockRepository{
|
|
findByIDFunc: func(id uint) (*User, error) {
|
|
return &User{ID: id}, nil
|
|
},
|
|
deleteFunc: func(id uint) error {
|
|
deleteCalled = true
|
|
return nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
if err := svc.Delete(1); err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if !deleteCalled {
|
|
t.Error("repository.Delete should have been called")
|
|
}
|
|
}
|
|
|
|
func TestService_GetAllPaginated_DefaultNormalization(t *testing.T) {
|
|
var capturedPage, capturedLimit int
|
|
var capturedSearch string
|
|
|
|
repo := &mockRepository{
|
|
findAllPaginatedFunc: func(page, limit int, query ListUserQuery) ([]User, int64, error) {
|
|
capturedPage, capturedLimit, capturedSearch = page, limit, query.Search
|
|
return []User{{ID: 1}}, 1, nil
|
|
},
|
|
}
|
|
svc := NewService(repo)
|
|
|
|
_, total, err := svc.GetAllPaginated(ListUserQuery{Page: 0, Limit: 0, Search: "budi"})
|
|
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
if total != 1 {
|
|
t.Errorf("expected total 1, got: %d", total)
|
|
}
|
|
if capturedPage != 1 {
|
|
t.Errorf("expected page normalized to 1, got: %d", capturedPage)
|
|
}
|
|
if capturedLimit != 20 {
|
|
t.Errorf("expected limit normalized to 20, got: %d", capturedLimit)
|
|
}
|
|
if capturedSearch != "budi" {
|
|
t.Errorf("expected search 'budi', got: '%s'", capturedSearch)
|
|
}
|
|
}
|