- Add new test files for auth, service, and handler modules - Improve test organization and coverage - Refactor code for better maintainability - Add captcha, settings, stats, and theme handler tests - Add auth module tests (CAS, OAuth, password, SSO, state) - Add service layer tests for auth, export, permissions, roles - All Go tests pass (exit code 0) - All frontend tests pass (325 tests in 59 files)
433 lines
12 KiB
Go
433 lines
12 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/user-management-system/internal/auth"
|
|
"github.com/user-management-system/internal/cache"
|
|
"github.com/user-management-system/internal/domain"
|
|
"github.com/user-management-system/internal/service"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Auth Contact Binding Tests
|
|
// =============================================================================
|
|
|
|
func setupContactBindingTestEnv(t *testing.T) *authTestEnv {
|
|
t.Helper()
|
|
env := setupAuthTestEnv(t)
|
|
if env == nil {
|
|
return nil
|
|
}
|
|
|
|
// Setup email code service
|
|
l1Cache := cache.NewL1Cache()
|
|
l2Cache := cache.NewRedisCache(false)
|
|
cacheManager := cache.NewCacheManager(l1Cache, l2Cache)
|
|
emailProvider := &service.MockEmailProvider{}
|
|
emailCodeSvc := service.NewEmailCodeService(emailProvider, cacheManager, service.DefaultEmailCodeConfig())
|
|
env.authSvc.SetEmailCodeService(emailCodeSvc)
|
|
|
|
// Setup SMS code service
|
|
smsProvider := &service.MockSMSProvider{}
|
|
smsCodeSvc := service.NewSMSCodeService(smsProvider, cacheManager, service.DefaultSMSCodeConfig())
|
|
env.authSvc.SetSMSCodeService(smsCodeSvc)
|
|
|
|
return env
|
|
}
|
|
|
|
func TestAuthService_SendEmailBindCode(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &domain.User{
|
|
Username: "binduser",
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Send email bind code with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.SendEmailBindCode(ctx, 1, "test@test.com")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Send email bind code for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.SendEmailBindCode(ctx, 9999, "test@test.com")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Send email bind code with empty email", func(t *testing.T) {
|
|
err := env.authSvc.SendEmailBindCode(ctx, user.ID, "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty email")
|
|
}
|
|
})
|
|
|
|
t.Run("Send email bind code success", func(t *testing.T) {
|
|
err := env.authSvc.SendEmailBindCode(ctx, user.ID, "newemail@test.com")
|
|
if err != nil {
|
|
t.Fatalf("SendEmailBindCode failed: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Send email bind code for already bound email", func(t *testing.T) {
|
|
email := "alreadybound@test.com"
|
|
userWithEmail := &domain.User{
|
|
Username: "emailbounduser",
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
Email: &email,
|
|
}
|
|
env.userSvc.Create(ctx, userWithEmail)
|
|
|
|
err := env.authSvc.SendEmailBindCode(ctx, userWithEmail.ID, email)
|
|
if err == nil {
|
|
t.Error("Expected error for already bound email")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAuthService_BindEmail(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user with password
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
user := &domain.User{
|
|
Username: "bindemailuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Bind email with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.BindEmail(ctx, 1, "test@test.com", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind email for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.BindEmail(ctx, 9999, "test@test.com", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind email with empty email", func(t *testing.T) {
|
|
err := env.authSvc.BindEmail(ctx, user.ID, "", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty email")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind email with wrong password", func(t *testing.T) {
|
|
err := env.authSvc.BindEmail(ctx, user.ID, "bindemail@test.com", "123456", "wrongpassword", "")
|
|
if err == nil {
|
|
t.Error("Expected error for wrong password")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAuthService_UnbindEmail(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user with email and password
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
email := "unbind@test.com"
|
|
user := &domain.User{
|
|
Username: "unbindemailuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
Email: &email,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Unbind email with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.UnbindEmail(ctx, 1, "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind email for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.UnbindEmail(ctx, 9999, "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind email with wrong password", func(t *testing.T) {
|
|
err := env.authSvc.UnbindEmail(ctx, user.ID, "wrongpassword", "")
|
|
if err == nil {
|
|
t.Error("Expected error for wrong password")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind email for user without email", func(t *testing.T) {
|
|
userNoEmail := &domain.User{
|
|
Username: "noemailuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, userNoEmail)
|
|
|
|
err := env.authSvc.UnbindEmail(ctx, userNoEmail.ID, "Password123!", "")
|
|
if err == nil {
|
|
t.Error("Expected error for user without email")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAuthService_SendPhoneBindCode(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &domain.User{
|
|
Username: "phonebinduser",
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Send phone bind code with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
_, err := nilSvc.SendPhoneBindCode(ctx, 1, "13800138000")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Send phone bind code for non-existent user", func(t *testing.T) {
|
|
_, err := env.authSvc.SendPhoneBindCode(ctx, 9999, "13800138000")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Send phone bind code with empty phone", func(t *testing.T) {
|
|
_, err := env.authSvc.SendPhoneBindCode(ctx, user.ID, "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty phone")
|
|
}
|
|
})
|
|
|
|
t.Run("Send phone bind code success", func(t *testing.T) {
|
|
_, err := env.authSvc.SendPhoneBindCode(ctx, user.ID, "13800138001")
|
|
if err != nil {
|
|
t.Fatalf("SendPhoneBindCode failed: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAuthService_BindPhone(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user with password
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
user := &domain.User{
|
|
Username: "bindphoneuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Bind phone with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.BindPhone(ctx, 1, "13800138000", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind phone for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.BindPhone(ctx, 9999, "13800138000", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind phone with empty phone", func(t *testing.T) {
|
|
err := env.authSvc.BindPhone(ctx, user.ID, "", "code", "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty phone")
|
|
}
|
|
})
|
|
|
|
t.Run("Bind phone with wrong password", func(t *testing.T) {
|
|
err := env.authSvc.BindPhone(ctx, user.ID, "13800138002", "123456", "wrongpassword", "")
|
|
if err == nil {
|
|
t.Error("Expected error for wrong password")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAuthService_UnbindPhone(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create test user with phone and password
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
phone := "13900139000"
|
|
user := &domain.User{
|
|
Username: "unbindphoneuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
Phone: &phone,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
t.Run("Unbind phone with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.UnbindPhone(ctx, 1, "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind phone for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.UnbindPhone(ctx, 9999, "", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind phone with wrong password", func(t *testing.T) {
|
|
err := env.authSvc.UnbindPhone(ctx, user.ID, "wrongpassword", "")
|
|
if err == nil {
|
|
t.Error("Expected error for wrong password")
|
|
}
|
|
})
|
|
|
|
t.Run("Unbind phone for user without phone", func(t *testing.T) {
|
|
userNoPhone := &domain.User{
|
|
Username: "nophoneuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, userNoPhone)
|
|
|
|
err := env.authSvc.UnbindPhone(ctx, userNoPhone.ID, "Password123!", "")
|
|
if err == nil {
|
|
t.Error("Expected error for user without phone")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// BindEmail Extended Tests
|
|
// =============================================================================
|
|
|
|
func TestAuthService_BindEmail_Extended(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
|
|
t.Run("BindEmail with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.BindEmail(ctx, 1, "test@example.com", "code", "password", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("BindEmail for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.BindEmail(ctx, 9999, "test@example.com", "code", "password", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("BindEmail with empty email", func(t *testing.T) {
|
|
user := &domain.User{
|
|
Username: "bindemailuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
err := env.authSvc.BindEmail(ctx, user.ID, "", "code", "Password123!", "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty email")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// BindPhone Extended Tests
|
|
// =============================================================================
|
|
|
|
func TestAuthService_BindPhone_Extended(t *testing.T) {
|
|
env := setupContactBindingTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
hashedPassword, _ := auth.HashPassword("Password123!")
|
|
|
|
t.Run("BindPhone with nil service", func(t *testing.T) {
|
|
var nilSvc *service.AuthService
|
|
err := nilSvc.BindPhone(ctx, 1, "13800138000", "code", "password", "")
|
|
if err == nil {
|
|
t.Error("Expected error for nil service")
|
|
}
|
|
})
|
|
|
|
t.Run("BindPhone for non-existent user", func(t *testing.T) {
|
|
err := env.authSvc.BindPhone(ctx, 9999, "13800138000", "code", "password", "")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent user")
|
|
}
|
|
})
|
|
|
|
t.Run("BindPhone with empty phone", func(t *testing.T) {
|
|
user := &domain.User{
|
|
Username: "bindphoneuser",
|
|
Password: hashedPassword,
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
env.userSvc.Create(ctx, user)
|
|
|
|
err := env.authSvc.BindPhone(ctx, user.ID, "", "code", "Password123!", "")
|
|
if err == nil {
|
|
t.Error("Expected error for empty phone")
|
|
}
|
|
})
|
|
}
|