- 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
9.3 KiB
Go
345 lines
9.3 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/user-management-system/internal/domain"
|
|
"github.com/user-management-system/internal/repository"
|
|
"github.com/user-management-system/internal/service"
|
|
gormsqlite "gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Export Service Tests
|
|
// =============================================================================
|
|
|
|
func setupExportTestEnv(t *testing.T) (*service.ExportService, *gorm.DB) {
|
|
t.Helper()
|
|
|
|
db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
|
|
DriverName: "sqlite",
|
|
DSN: "file:export_test?mode=memory&cache=shared",
|
|
}), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("failed to connect database: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(&domain.User{}); err != nil {
|
|
t.Fatalf("failed to migrate: %v", err)
|
|
}
|
|
|
|
userRepo := repository.NewUserRepository(db)
|
|
svc := service.NewExportService(userRepo, nil)
|
|
|
|
return svc, db
|
|
}
|
|
|
|
func TestExportService_ExportUsers(t *testing.T) {
|
|
svc, db := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// Create test users
|
|
for i := 0; i < 3; i++ {
|
|
user := &domain.User{
|
|
Username: "export_user_" + string(rune('a'+i)),
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
db.Create(user)
|
|
}
|
|
|
|
t.Run("Export users as CSV", func(t *testing.T) {
|
|
req := &service.ExportUsersRequest{
|
|
Format: "csv",
|
|
}
|
|
data, filename, contentType, err := svc.ExportUsers(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsers failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected export data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
if contentType == "" {
|
|
t.Error("Expected content type")
|
|
}
|
|
})
|
|
|
|
t.Run("Export users as XLSX", func(t *testing.T) {
|
|
req := &service.ExportUsersRequest{
|
|
Format: "xlsx",
|
|
}
|
|
data, _, _, err := svc.ExportUsers(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsers failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected export data")
|
|
}
|
|
})
|
|
|
|
t.Run("Export users with invalid format", func(t *testing.T) {
|
|
req := &service.ExportUsersRequest{
|
|
Format: "invalid",
|
|
}
|
|
_, _, _, err := svc.ExportUsers(ctx, req)
|
|
if err == nil {
|
|
t.Error("Expected error for invalid format")
|
|
}
|
|
})
|
|
|
|
t.Run("Export users with nil request", func(t *testing.T) {
|
|
data, _, _, err := svc.ExportUsers(ctx, nil)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsers with nil request failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected export data")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExportService_ExportUsersCSV(t *testing.T) {
|
|
svc, db := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &domain.User{
|
|
Username: "csv_user",
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
db.Create(user)
|
|
|
|
t.Run("Export users CSV", func(t *testing.T) {
|
|
data, filename, err := svc.ExportUsersCSV(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsersCSV failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected CSV data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExportService_ExportUsersXLSX(t *testing.T) {
|
|
svc, db := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &domain.User{
|
|
Username: "xlsx_user",
|
|
Password: "$2a$10$hash",
|
|
Status: domain.UserStatusActive,
|
|
}
|
|
db.Create(user)
|
|
|
|
t.Run("Export users XLSX", func(t *testing.T) {
|
|
data, filename, err := svc.ExportUsersXLSX(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsersXLSX failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected XLSX data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExportService_GetImportTemplate(t *testing.T) {
|
|
svc, _ := setupExportTestEnv(t)
|
|
|
|
t.Run("Get import template default", func(t *testing.T) {
|
|
data, filename := svc.GetImportTemplate()
|
|
if len(data) == 0 {
|
|
t.Error("Expected template data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
})
|
|
|
|
t.Run("Get import template CSV", func(t *testing.T) {
|
|
data, filename, contentType, err := svc.GetImportTemplateByFormat("csv")
|
|
if err != nil {
|
|
t.Fatalf("GetImportTemplateByFormat failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected template data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
if contentType == "" {
|
|
t.Error("Expected content type")
|
|
}
|
|
})
|
|
|
|
t.Run("Get import template XLSX", func(t *testing.T) {
|
|
data, _, _, err := svc.GetImportTemplateByFormat("xlsx")
|
|
if err != nil {
|
|
t.Fatalf("GetImportTemplateByFormat failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected template data")
|
|
}
|
|
})
|
|
|
|
t.Run("Get import template invalid format", func(t *testing.T) {
|
|
_, _, _, err := svc.GetImportTemplateByFormat("invalid")
|
|
if err == nil {
|
|
t.Error("Expected error for invalid format")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Export Users CSV Extended Tests
|
|
// =============================================================================
|
|
|
|
func TestExportService_ExportUsersCSV_Extended(t *testing.T) {
|
|
svc, db := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// Create multiple test users with various fields
|
|
email := "export@test.com"
|
|
phone := "13800138000"
|
|
users := []*domain.User{
|
|
{Username: "csv_user1", Password: "$2a$10$hash", Status: domain.UserStatusActive, Email: &email, Phone: &phone, Nickname: "User One"},
|
|
{Username: "csv_user2", Password: "$2a$10$hash", Status: domain.UserStatusInactive},
|
|
{Username: "csv_user3", Password: "$2a$10$hash", Status: domain.UserStatusLocked},
|
|
}
|
|
for _, u := range users {
|
|
db.Create(u)
|
|
}
|
|
|
|
t.Run("Export users CSV with data", func(t *testing.T) {
|
|
data, filename, err := svc.ExportUsersCSV(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ExportUsersCSV failed: %v", err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Error("Expected CSV data")
|
|
}
|
|
if filename == "" {
|
|
t.Error("Expected filename")
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Import Users Tests
|
|
// =============================================================================
|
|
|
|
func TestExportService_ImportUsersCSV(t *testing.T) {
|
|
svc, _ := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("Import CSV with empty data", func(t *testing.T) {
|
|
successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(""))
|
|
_ = failCount
|
|
_ = errs
|
|
// Empty data should result in 0 successful imports
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success, got %d", successCount)
|
|
}
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// Import Users Extended Tests
|
|
// =============================================================================
|
|
|
|
func TestExportService_ImportUsers(t *testing.T) {
|
|
svc, db := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("Import users with invalid format", func(t *testing.T) {
|
|
successCount, _, _ := svc.ImportUsers(ctx, []byte("test"), "invalid_format")
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success for invalid format, got %d", successCount)
|
|
}
|
|
})
|
|
|
|
t.Run("Import valid CSV data", func(t *testing.T) {
|
|
csvData := "用户名,密码,邮箱,手机号,昵称\nnewuser1,Password123!,new1@test.com,13800138001,User One\nnewuser2,Password123!,new2@test.com,13800138002,User Two"
|
|
successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
|
|
if successCount != 2 {
|
|
t.Errorf("Expected 2 successful imports, got %d, errors: %v", successCount, errs)
|
|
}
|
|
_ = failCount
|
|
})
|
|
|
|
t.Run("Import CSV with missing username", func(t *testing.T) {
|
|
csvData := "用户名,密码\n,Password123!"
|
|
successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success, got %d", successCount)
|
|
}
|
|
if failCount == 0 {
|
|
t.Error("Expected at least one failure")
|
|
}
|
|
if len(errs) == 0 {
|
|
t.Error("Expected error message")
|
|
}
|
|
})
|
|
|
|
t.Run("Import CSV with missing password", func(t *testing.T) {
|
|
csvData := "用户名,密码\nnopwduser,"
|
|
successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success, got %d", successCount)
|
|
}
|
|
if failCount == 0 {
|
|
t.Error("Expected at least one failure")
|
|
}
|
|
_ = errs
|
|
})
|
|
|
|
t.Run("Import CSV with duplicate username", func(t *testing.T) {
|
|
// Create existing user
|
|
db.Create(&domain.User{Username: "duplicateuser", Password: "$2a$10$hash", Status: domain.UserStatusActive})
|
|
|
|
csvData := "用户名,密码\nduplicateuser,Password123!"
|
|
successCount, failCount, _ := svc.ImportUsersCSV(ctx, []byte(csvData))
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success for duplicate, got %d", successCount)
|
|
}
|
|
if failCount == 0 {
|
|
t.Error("Expected failure for duplicate username")
|
|
}
|
|
})
|
|
|
|
t.Run("Import CSV with only headers", func(t *testing.T) {
|
|
csvData := "用户名,密码,邮箱"
|
|
successCount, _, _ := svc.ImportUsersCSV(ctx, []byte(csvData))
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success for header-only CSV, got %d", successCount)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExportService_ImportUsersXLSX(t *testing.T) {
|
|
svc, _ := setupExportTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("Import XLSX with invalid data", func(t *testing.T) {
|
|
successCount, _, _ := svc.ImportUsersXLSX(ctx, []byte("not a valid xlsx"))
|
|
if successCount != 0 {
|
|
t.Errorf("Expected 0 success for invalid XLSX, got %d", successCount)
|
|
}
|
|
})
|
|
}
|