Files

281 lines
7.4 KiB
Go
Raw Permalink Normal View History

2026-07-30 09:51:25 +07:00
package auth
import (
"errors"
"testing"
"time"
"cardverse/config"
"cardverse/internal/modules/user"
"cardverse/internal/pkg/utils"
)
func setupTestConfig() {
config.Cfg = &config.Config{
JWTSecret: "test-secret-key",
JWTExpiresHours: 1,
JWTRefreshSecret: "test-refresh-secret-key",
JWTRefreshExpiresHours: 168,
}
}
func TestService_Register_Success(t *testing.T) {
setupTestConfig()
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return nil, errors.New("record not found")
},
createFunc: func(u *user.User) error {
u.ID = 1
return nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
req := RegisterRequest{
Name: "User Test",
Email: "register@mail.com",
Password: "password123",
ConfirmPassword: "password123",
}
u, token, err := svc.Register(req)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if token == "" {
t.Error("verification token should not be empty")
}
if u.Status != user.StatusUnverified {
t.Errorf("expected status 'unverified', got: %s", u.Status)
}
}
func TestService_Register_PasswordMismatch(t *testing.T) {
setupTestConfig()
userRepo := &mockUserRepository{}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
req := RegisterRequest{
Name: "User Test",
Email: "mismatch@mail.com",
Password: "password123",
ConfirmPassword: "differentpassword",
}
_, _, err := svc.Register(req)
if !errors.Is(err, ErrPasswordMismatch) {
t.Fatalf("expected ErrPasswordMismatch, got: %v", err)
}
}
func TestService_Register_EmailAlreadyExists(t *testing.T) {
setupTestConfig()
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return &user.User{ID: 1, Email: email}, nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
req := RegisterRequest{
Name: "User Test",
Email: "existing@mail.com",
Password: "password123",
ConfirmPassword: "password123",
}
_, _, err := svc.Register(req)
if !errors.Is(err, ErrEmailAlreadyExists) {
t.Fatalf("expected ErrEmailAlreadyExists, got: %v", err)
}
}
func TestService_Login_Success(t *testing.T) {
setupTestConfig()
hashedPassword, _ := utils.HashPassword("rahasia123")
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return &user.User{ID: 1, Name: "Budi", Email: email, Password: hashedPassword, Role: user.RoleUser, Status: user.StatusActive}, nil
},
}
authRepo := &mockAuthRepository{
createRefreshTokenFunc: func(token *RefreshToken) error {
return nil
},
}
svc := NewService(userRepo, authRepo)
result, err := svc.Login(LoginRequest{Email: "budi@mail.com", Password: "rahasia123"})
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if result.AccessToken == "" {
t.Error("access_token should not be empty")
}
if result.RefreshToken == "" {
t.Error("refresh_token should not be empty")
}
if result.User.Email != "budi@mail.com" {
t.Errorf("expected email budi@mail.com, got %s", result.User.Email)
}
}
func TestService_Login_SuspendedAccount(t *testing.T) {
setupTestConfig()
hashedPassword, _ := utils.HashPassword("rahasia123")
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return &user.User{ID: 1, Name: "Budi", Email: email, Password: hashedPassword, Status: user.StatusSuspended}, nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
_, err := svc.Login(LoginRequest{Email: "budi@mail.com", Password: "rahasia123"})
if !errors.Is(err, ErrAccountSuspended) {
t.Fatalf("expected ErrAccountSuspended, got: %v", err)
}
}
func TestService_Login_InvalidPassword(t *testing.T) {
setupTestConfig()
hashedPassword, _ := utils.HashPassword("rahasia123")
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return &user.User{ID: 1, Email: email, Password: hashedPassword}, nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
_, err := svc.Login(LoginRequest{Email: "budi@mail.com", Password: "wrong_password"})
if !errors.Is(err, ErrInvalidCredentials) {
t.Fatalf("expected ErrInvalidCredentials, got: %v", err)
}
}
func TestService_RefreshToken_Success(t *testing.T) {
setupTestConfig()
validRefreshToken, _ := utils.GenerateRefreshToken(42)
userRepo := &mockUserRepository{
findByIDFunc: func(id uint) (*user.User, error) {
return &user.User{ID: 42, Email: "test@mail.com", Role: user.RoleUser, Status: user.StatusActive}, nil
},
}
authRepo := &mockAuthRepository{
findByTokenFunc: func(token string) (*RefreshToken, error) {
return &RefreshToken{
UserID: 42,
Token: token,
ExpiresAt: time.Now().Add(1 * time.Hour),
}, nil
},
}
svc := NewService(userRepo, authRepo)
res, err := svc.RefreshToken(RefreshTokenRequest{RefreshToken: validRefreshToken})
if err != nil {
t.Fatalf("RefreshToken expected no error, got: %v", err)
}
if res.AccessToken == "" || res.RefreshToken == "" {
t.Error("new access_token and refresh_token should not be empty")
}
}
func TestService_Logout_Success(t *testing.T) {
setupTestConfig()
deleted := false
authRepo := &mockAuthRepository{
deleteByTokenFunc: func(token string) error {
deleted = true
return nil
},
}
svc := NewService(&mockUserRepository{}, authRepo)
err := svc.Logout("token-to-delete")
if err != nil {
t.Fatalf("Logout expected no error, got: %v", err)
}
if !deleted {
t.Error("deleteByTokenFunc should have been called")
}
}
func TestService_VerifyEmail_Success(t *testing.T) {
setupTestConfig()
userRepo := &mockUserRepository{
findByVerificationTokenFunc: func(token string) (*user.User, error) {
return &user.User{ID: 1, Status: user.StatusUnverified, IsEmailVerified: false, VerificationToken: token}, nil
},
updateFunc: func(u *user.User) error {
return nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
err := svc.VerifyEmail("valid-token")
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
}
func TestService_ForgotPassword_AndResetPassword_Success(t *testing.T) {
setupTestConfig()
var storedToken string
userRepo := &mockUserRepository{
findByEmailFunc: func(email string) (*user.User, error) {
return &user.User{ID: 1, Email: email}, nil
},
findByResetTokenFunc: func(token string) (*user.User, error) {
expiry := time.Now().Add(1 * time.Hour)
return &user.User{ID: 1, ResetPasswordToken: token, ResetPasswordExpiresAt: &expiry}, nil
},
updateFunc: func(u *user.User) error {
storedToken = u.ResetPasswordToken
return nil
},
}
authRepo := &mockAuthRepository{}
svc := NewService(userRepo, authRepo)
resetToken, err := svc.ForgotPassword("user@mail.com")
if err != nil {
t.Fatalf("ForgotPassword expected no error, got: %v", err)
}
if resetToken == "" {
t.Fatal("resetToken should not be empty")
}
if storedToken != resetToken {
t.Errorf("expected storedToken to be %s, got %s", resetToken, storedToken)
}
err = svc.ResetPassword(ResetPasswordRequest{
Token: resetToken,
NewPassword: "newpassword123",
ConfirmNewPassword: "newpassword123",
})
if err != nil {
t.Fatalf("ResetPassword expected no error, got: %v", err)
}
}