- 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)
345 lines
8.6 KiB
Go
345 lines
8.6 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/user-management-system/internal/domain"
|
|
"github.com/user-management-system/internal/service"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Auth Setter Tests - Phase 1
|
|
// =============================================================================
|
|
|
|
func TestAuthService_Setters(t *testing.T) {
|
|
env := setupAuthTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
|
|
t.Run("SetWebhookService", func(t *testing.T) {
|
|
env.authSvc.SetWebhookService(nil)
|
|
})
|
|
|
|
t.Run("SetLoginLogRepository", func(t *testing.T) {
|
|
env.authSvc.SetLoginLogRepository(nil)
|
|
})
|
|
|
|
t.Run("SetAnomalyDetector", func(t *testing.T) {
|
|
env.authSvc.SetAnomalyDetector(nil)
|
|
})
|
|
|
|
t.Run("SetDeviceService", func(t *testing.T) {
|
|
env.authSvc.SetDeviceService(nil)
|
|
})
|
|
|
|
t.Run("SetSMSCodeService", func(t *testing.T) {
|
|
env.authSvc.SetSMSCodeService(nil)
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Auth Nil Service Tests
|
|
// =============================================================================
|
|
|
|
func TestAuthService_NilServiceMethods(t *testing.T) {
|
|
ctx := context.Background()
|
|
var nilSvc *service.AuthService
|
|
|
|
t.Run("RefreshToken", func(t *testing.T) {
|
|
_, err := nilSvc.RefreshToken(ctx, "token")
|
|
if err == nil {
|
|
t.Error("Expected error")
|
|
}
|
|
})
|
|
|
|
t.Run("GetUserInfo", func(t *testing.T) {
|
|
_, err := nilSvc.GetUserInfo(ctx, 1)
|
|
if err == nil {
|
|
t.Error("Expected error")
|
|
}
|
|
})
|
|
|
|
t.Run("Logout", func(t *testing.T) {
|
|
err := nilSvc.Logout(ctx, "user", nil)
|
|
// Logout on nil service should not error
|
|
_ = err
|
|
})
|
|
|
|
t.Run("IsTokenBlacklisted", func(t *testing.T) {
|
|
if nilSvc.IsTokenBlacklisted(ctx, "jti") {
|
|
t.Error("Expected false")
|
|
}
|
|
})
|
|
|
|
t.Run("OAuthLogin", func(t *testing.T) {
|
|
_, err := nilSvc.OAuthLogin(ctx, "provider", "state")
|
|
if err == nil {
|
|
t.Error("Expected error")
|
|
}
|
|
})
|
|
|
|
t.Run("OAuthCallback", func(t *testing.T) {
|
|
_, err := nilSvc.OAuthCallback(ctx, "provider", "code")
|
|
if err == nil {
|
|
t.Error("Expected error")
|
|
}
|
|
})
|
|
|
|
t.Run("GetEnabledOAuthProviders", func(t *testing.T) {
|
|
providers := nilSvc.GetEnabledOAuthProviders()
|
|
// nil service returns empty slice, not nil
|
|
if len(providers) != 0 {
|
|
t.Error("Expected empty slice")
|
|
}
|
|
})
|
|
|
|
t.Run("LoginByCode", func(t *testing.T) {
|
|
_, err := nilSvc.LoginByCode(ctx, "phone", "code", "ip")
|
|
if err == nil {
|
|
t.Error("Expected error")
|
|
}
|
|
})
|
|
|
|
t.Run("WarmupCache", func(t *testing.T) {
|
|
err := nilSvc.WarmupCache(ctx, 10)
|
|
// Should not error on nil service
|
|
_ = err
|
|
})
|
|
|
|
t.Run("RefreshTokenTTLSeconds", func(t *testing.T) {
|
|
if nilSvc.RefreshTokenTTLSeconds() != 0 {
|
|
t.Error("Expected 0")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// User Status Tests
|
|
// =============================================================================
|
|
|
|
func TestAuthService_UserStatusLogin(t *testing.T) {
|
|
env := setupAuthTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
t.Run("Login with inactive status", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "inactive_login",
|
|
Password: "Test123!",
|
|
}
|
|
resp, _ := env.authSvc.Register(ctx, req)
|
|
env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusInactive)
|
|
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "inactive_login",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err == nil {
|
|
t.Error("Expected error for inactive user")
|
|
}
|
|
})
|
|
|
|
t.Run("Login with locked status", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "locked_login",
|
|
Password: "Test123!",
|
|
}
|
|
resp, _ := env.authSvc.Register(ctx, req)
|
|
env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusLocked)
|
|
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "locked_login",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err == nil {
|
|
t.Error("Expected error for locked user")
|
|
}
|
|
})
|
|
|
|
t.Run("Login with disabled status", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "disabled_login",
|
|
Password: "Test123!",
|
|
}
|
|
resp, _ := env.authSvc.Register(ctx, req)
|
|
env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusDisabled)
|
|
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "disabled_login",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err == nil {
|
|
t.Error("Expected error for disabled user")
|
|
}
|
|
})
|
|
|
|
t.Run("Login with active status", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "active_login",
|
|
Password: "Test123!",
|
|
}
|
|
resp, _ := env.authSvc.Register(ctx, req)
|
|
env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusActive)
|
|
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "active_login",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err != nil {
|
|
t.Errorf("Active user should login: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Register Edge Cases
|
|
// =============================================================================
|
|
|
|
func TestAuthService_RegisterEdgeCases(t *testing.T) {
|
|
env := setupAuthTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
t.Run("Register with email", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "emailuser",
|
|
Password: "Test123!",
|
|
Email: "email@test.com",
|
|
}
|
|
resp, err := env.authSvc.Register(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("Register failed: %v", err)
|
|
}
|
|
if resp.Email != "email@test.com" {
|
|
t.Errorf("Expected email, got %s", resp.Email)
|
|
}
|
|
})
|
|
|
|
t.Run("Register with phone", func(t *testing.T) {
|
|
req := &service.RegisterRequest{
|
|
Username: "phoneuser",
|
|
Password: "Test123!",
|
|
Phone: "13800138000",
|
|
}
|
|
_, err := env.authSvc.Register(ctx, req)
|
|
// Phone registration requires SMS config, expect error
|
|
if err == nil {
|
|
t.Log("Phone registration succeeded")
|
|
} else {
|
|
t.Logf("Phone registration failed (expected without SMS config): %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Register with duplicate email", func(t *testing.T) {
|
|
req1 := &service.RegisterRequest{
|
|
Username: "dupemail1",
|
|
Password: "Test123!",
|
|
Email: "dup@test.com",
|
|
}
|
|
env.authSvc.Register(ctx, req1)
|
|
|
|
req2 := &service.RegisterRequest{
|
|
Username: "dupemail2",
|
|
Password: "Test123!",
|
|
Email: "dup@test.com",
|
|
}
|
|
_, err := env.authSvc.Register(ctx, req2)
|
|
if err == nil {
|
|
t.Error("Expected error for duplicate email")
|
|
}
|
|
})
|
|
|
|
t.Run("Register with duplicate phone", func(t *testing.T) {
|
|
req1 := &service.RegisterRequest{
|
|
Username: "dupphone1",
|
|
Password: "Test123!",
|
|
Phone: "13900139000",
|
|
}
|
|
env.authSvc.Register(ctx, req1)
|
|
|
|
req2 := &service.RegisterRequest{
|
|
Username: "dupphone2",
|
|
Password: "Test123!",
|
|
Phone: "13900139000",
|
|
}
|
|
_, err := env.authSvc.Register(ctx, req2)
|
|
if err == nil {
|
|
t.Error("Expected error for duplicate phone")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Login Edge Cases
|
|
// =============================================================================
|
|
|
|
func TestAuthService_LoginEdgeCases(t *testing.T) {
|
|
env := setupAuthTestEnv(t)
|
|
if env == nil {
|
|
return
|
|
}
|
|
ctx := context.Background()
|
|
|
|
// Create user with known credentials
|
|
req := &service.RegisterRequest{
|
|
Username: "loginedge",
|
|
Password: "Test123!",
|
|
Email: "loginedge@test.com",
|
|
}
|
|
env.authSvc.Register(ctx, req)
|
|
|
|
t.Run("Login with username", func(t *testing.T) {
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "loginedge",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err != nil {
|
|
t.Errorf("Login failed: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Login with email as account", func(t *testing.T) {
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Account: "loginedge@test.com",
|
|
Password: "Test123!",
|
|
}, "127.0.0.1")
|
|
if err != nil {
|
|
t.Errorf("Login with email failed: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Login with remember", func(t *testing.T) {
|
|
resp, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "loginedge",
|
|
Password: "Test123!",
|
|
Remember: true,
|
|
}, "127.0.0.1")
|
|
if err != nil {
|
|
t.Fatalf("Login failed: %v", err)
|
|
}
|
|
if resp.RefreshToken == "" {
|
|
t.Error("Expected refresh token with remember")
|
|
}
|
|
})
|
|
|
|
t.Run("Login with device info", func(t *testing.T) {
|
|
_, err := env.authSvc.Login(ctx, &service.LoginRequest{
|
|
Username: "loginedge",
|
|
Password: "Test123!",
|
|
DeviceID: "device123",
|
|
DeviceName: "Test Device",
|
|
DeviceBrowser: "Chrome",
|
|
DeviceOS: "Windows",
|
|
}, "127.0.0.1")
|
|
if err != nil {
|
|
t.Errorf("Login with device info failed: %v", err)
|
|
}
|
|
})
|
|
}
|