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") } }) }