first commit
This commit is contained in:
264
internal/modules/user/service_test.go
Normal file
264
internal/modules/user/service_test.go
Normal file
@@ -0,0 +1,264 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user