test: add comprehensive test coverage and improve code quality
- 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)
2026-04-17 20:43:50 +08:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/user-management-system/internal/domain"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// Stats Service Internal Tests
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// mockStatsUserRepoInternal mocks user repository for stats tests
|
|
|
|
|
type mockStatsUserRepoInternal struct {
|
|
|
|
|
totalUsers int64
|
|
|
|
|
activeUsers int64
|
|
|
|
|
inactiveUsers int64
|
|
|
|
|
lockedUsers int64
|
|
|
|
|
disabledUsers int64
|
|
|
|
|
newUsersToday int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *mockStatsUserRepoInternal) List(ctx context.Context, offset, limit int) ([]*domain.User, int64, error) {
|
|
|
|
|
return nil, m.totalUsers, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *mockStatsUserRepoInternal) ListByStatus(ctx context.Context, status domain.UserStatus, offset, limit int) ([]*domain.User, int64, error) {
|
|
|
|
|
switch status {
|
|
|
|
|
case domain.UserStatusActive:
|
|
|
|
|
return nil, m.activeUsers, nil
|
|
|
|
|
case domain.UserStatusInactive:
|
|
|
|
|
return nil, m.inactiveUsers, nil
|
|
|
|
|
case domain.UserStatusLocked:
|
|
|
|
|
return nil, m.lockedUsers, nil
|
|
|
|
|
case domain.UserStatusDisabled:
|
|
|
|
|
return nil, m.disabledUsers, nil
|
|
|
|
|
}
|
|
|
|
|
return nil, 0, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *mockStatsUserRepoInternal) ListCreatedAfter(ctx context.Context, since time.Time, offset, limit int) ([]*domain.User, int64, error) {
|
|
|
|
|
return nil, m.newUsersToday, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mockStatsLoginLogRepoInternal mocks login log repository for stats tests
|
|
|
|
|
type mockStatsLoginLogRepoInternal struct {
|
|
|
|
|
successCount int64
|
|
|
|
|
failedCount int64
|
|
|
|
|
weekCount int64
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 15:33:12 +08:00
|
|
|
func (m *mockStatsLoginLogRepoInternal) CountByResultSince(ctx context.Context, success bool, since time.Time) (int64, error) {
|
test: add comprehensive test coverage and improve code quality
- 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)
2026-04-17 20:43:50 +08:00
|
|
|
if success {
|
2026-04-18 15:33:12 +08:00
|
|
|
return m.successCount, nil
|
test: add comprehensive test coverage and improve code quality
- 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)
2026-04-17 20:43:50 +08:00
|
|
|
}
|
2026-04-18 15:33:12 +08:00
|
|
|
return m.failedCount, nil
|
test: add comprehensive test coverage and improve code quality
- 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)
2026-04-17 20:43:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStatsService_GetDashboardStats_Internal(t *testing.T) {
|
|
|
|
|
userRepo := &mockStatsUserRepoInternal{
|
|
|
|
|
totalUsers: 100,
|
|
|
|
|
activeUsers: 80,
|
|
|
|
|
inactiveUsers: 10,
|
|
|
|
|
lockedUsers: 5,
|
|
|
|
|
disabledUsers: 5,
|
|
|
|
|
newUsersToday: 3,
|
|
|
|
|
}
|
|
|
|
|
loginLogRepo := &mockStatsLoginLogRepoInternal{
|
|
|
|
|
successCount: 50,
|
|
|
|
|
failedCount: 5,
|
|
|
|
|
weekCount: 200,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svc := NewStatsService(userRepo, loginLogRepo)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
stats, err := svc.GetDashboardStats(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GetDashboardStats failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if stats.Users.TotalUsers != 100 {
|
|
|
|
|
t.Errorf("Expected TotalUsers=100, got %d", stats.Users.TotalUsers)
|
|
|
|
|
}
|
|
|
|
|
if stats.Logins.LoginsTodaySuccess != 50 {
|
|
|
|
|
t.Errorf("Expected LoginsTodaySuccess=50, got %d", stats.Logins.LoginsTodaySuccess)
|
|
|
|
|
}
|
|
|
|
|
if stats.Logins.LoginsTodayFailed != 5 {
|
|
|
|
|
t.Errorf("Expected LoginsTodayFailed=5, got %d", stats.Logins.LoginsTodayFailed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStatsService_GetDashboardStats_NilLoginLogRepo(t *testing.T) {
|
|
|
|
|
userRepo := &mockStatsUserRepoInternal{
|
|
|
|
|
totalUsers: 50,
|
|
|
|
|
activeUsers: 40,
|
|
|
|
|
inactiveUsers: 5,
|
|
|
|
|
lockedUsers: 3,
|
|
|
|
|
disabledUsers: 2,
|
|
|
|
|
newUsersToday: 2,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svc := NewStatsService(userRepo, nil)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
stats, err := svc.GetDashboardStats(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GetDashboardStats failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if stats.Users.TotalUsers != 50 {
|
|
|
|
|
t.Errorf("Expected TotalUsers=50, got %d", stats.Users.TotalUsers)
|
|
|
|
|
}
|
|
|
|
|
// Login stats should be 0 when loginLogRepo is nil
|
|
|
|
|
if stats.Logins.LoginsTodaySuccess != 0 {
|
|
|
|
|
t.Errorf("Expected LoginsTodaySuccess=0, got %d", stats.Logins.LoginsTodaySuccess)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestDaysAgo(t *testing.T) {
|
|
|
|
|
result := daysAgo(0)
|
|
|
|
|
if result.After(time.Now()) {
|
|
|
|
|
t.Error("daysAgo(0) should not be in the future")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = daysAgo(7)
|
|
|
|
|
if result.After(time.Now()) {
|
|
|
|
|
t.Error("daysAgo(7) should not be in the future")
|
|
|
|
|
}
|
|
|
|
|
}
|