Files
cardverse-be/internal/modules/user/service_test.go

265 lines
6.8 KiB
Go
Raw Normal View History

2026-07-30 09:51:25 +07:00
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)
}
}