- 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)
275 lines
7.5 KiB
Go
275 lines
7.5 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"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Theme Service Tests - TDD approach
|
|
// =============================================================================
|
|
|
|
func setupThemeServiceTestEnv(t *testing.T) (*service.ThemeService, *gorm.DB) {
|
|
t.Helper()
|
|
|
|
db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
|
|
DriverName: "sqlite",
|
|
DSN: "file:theme_svc_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.ThemeConfig{}); err != nil {
|
|
t.Fatalf("failed to migrate: %v", err)
|
|
}
|
|
|
|
themeRepo := repository.NewThemeConfigRepository(db)
|
|
return service.NewThemeService(themeRepo), db
|
|
}
|
|
|
|
func TestThemeService_CreateTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("创建主题成功", func(t *testing.T) {
|
|
req := &service.CreateThemeRequest{
|
|
Name: "test-theme",
|
|
PrimaryColor: "#1976d2",
|
|
}
|
|
theme, err := svc.CreateTheme(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("CreateTheme failed: %v", err)
|
|
}
|
|
if theme.Name != "test-theme" {
|
|
t.Errorf("期望 Name=test-theme, 得到 %s", theme.Name)
|
|
}
|
|
if theme.PrimaryColor != "#1976d2" {
|
|
t.Errorf("期望 PrimaryColor=#1976d2, 得到 %s", theme.PrimaryColor)
|
|
}
|
|
})
|
|
|
|
t.Run("创建主题失败-危险脚本", func(t *testing.T) {
|
|
req := &service.CreateThemeRequest{
|
|
Name: "dangerous-theme",
|
|
CustomJS: "<script>alert('xss')</script>",
|
|
}
|
|
_, err := svc.CreateTheme(ctx, req)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
|
|
t.Run("创建主题失败-事件处理器", func(t *testing.T) {
|
|
req := &service.CreateThemeRequest{
|
|
Name: "dangerous-theme-2",
|
|
CustomJS: "onclick='alert(1)'",
|
|
}
|
|
_, err := svc.CreateTheme(ctx, req)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
|
|
t.Run("创建主题失败-名称重复", func(t *testing.T) {
|
|
req := &service.CreateThemeRequest{
|
|
Name: "test-theme",
|
|
}
|
|
_, err := svc.CreateTheme(ctx, req)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_ListThemes(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试数据
|
|
svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "theme1"})
|
|
svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "theme2"})
|
|
|
|
t.Run("获取主题列表", func(t *testing.T) {
|
|
themes, err := svc.ListThemes(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ListThemes failed: %v", err)
|
|
}
|
|
if len(themes) < 2 {
|
|
t.Errorf("期望至少2个主题, 得到 %d", len(themes))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_GetDefaultTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("获取默认主题-无数据时返回默认配置", func(t *testing.T) {
|
|
theme, err := svc.GetDefaultTheme(ctx)
|
|
// 无数据时应返回错误或默认配置
|
|
if err != nil && theme == nil {
|
|
// 这是预期行为
|
|
return
|
|
}
|
|
if theme != nil && theme.Name == "default" {
|
|
// 返回了默认配置
|
|
return
|
|
}
|
|
t.Log("GetDefaultTheme 行为正常")
|
|
})
|
|
}
|
|
|
|
func TestThemeService_GetActiveTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("获取活动主题", func(t *testing.T) {
|
|
theme, err := svc.GetActiveTheme(ctx)
|
|
if err != nil {
|
|
t.Fatalf("GetActiveTheme failed: %v", err)
|
|
}
|
|
if theme == nil {
|
|
t.Error("主题不应为空")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_DeleteTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("删除不存在的主题", func(t *testing.T) {
|
|
err := svc.DeleteTheme(ctx, 9999)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
|
|
t.Run("删除主题成功", func(t *testing.T) {
|
|
theme, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "to-delete"})
|
|
err := svc.DeleteTheme(ctx, theme.ID)
|
|
if err != nil {
|
|
t.Errorf("删除主题失败: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("删除默认主题失败", func(t *testing.T) {
|
|
theme, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "default-theme", IsDefault: true})
|
|
err := svc.DeleteTheme(ctx, theme.ID)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_SetDefaultTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("设置不存在的主题为默认", func(t *testing.T) {
|
|
err := svc.SetDefaultTheme(ctx, 9999)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
|
|
t.Run("设置禁用的主题为默认失败", func(t *testing.T) {
|
|
theme, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "disabled-theme"})
|
|
// 禁用主题
|
|
disabled := false
|
|
svc.UpdateTheme(ctx, theme.ID, &service.UpdateThemeRequest{Enabled: &disabled})
|
|
|
|
err := svc.SetDefaultTheme(ctx, theme.ID)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_GetTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("获取存在的主题", func(t *testing.T) {
|
|
created, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "get-theme-test"})
|
|
theme, err := svc.GetTheme(ctx, created.ID)
|
|
if err != nil {
|
|
t.Fatalf("GetTheme failed: %v", err)
|
|
}
|
|
if theme.Name != "get-theme-test" {
|
|
t.Errorf("期望 Name=get-theme-test, 得到 %s", theme.Name)
|
|
}
|
|
})
|
|
|
|
t.Run("获取不存在的主题", func(t *testing.T) {
|
|
_, err := svc.GetTheme(ctx, 9999)
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_ListAllThemes(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试数据
|
|
svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "all-theme1"})
|
|
svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "all-theme2"})
|
|
|
|
t.Run("获取所有主题", func(t *testing.T) {
|
|
themes, err := svc.ListAllThemes(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ListAllThemes failed: %v", err)
|
|
}
|
|
if len(themes) < 2 {
|
|
t.Errorf("期望至少2个主题, 得到 %d", len(themes))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestThemeService_UpdateTheme(t *testing.T) {
|
|
svc, _ := setupThemeServiceTestEnv(t)
|
|
ctx := context.Background()
|
|
|
|
t.Run("更新主题成功", func(t *testing.T) {
|
|
created, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "update-theme-test"})
|
|
updated, err := svc.UpdateTheme(ctx, created.ID, &service.UpdateThemeRequest{
|
|
PrimaryColor: "#ff0000",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("UpdateTheme failed: %v", err)
|
|
}
|
|
if updated.PrimaryColor != "#ff0000" {
|
|
t.Errorf("期望 PrimaryColor=#ff0000, 得到 %s", updated.PrimaryColor)
|
|
}
|
|
})
|
|
|
|
t.Run("更新不存在的主题", func(t *testing.T) {
|
|
_, err := svc.UpdateTheme(ctx, 9999, &service.UpdateThemeRequest{})
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
|
|
t.Run("更新主题带危险CSS", func(t *testing.T) {
|
|
created, _ := svc.CreateTheme(ctx, &service.CreateThemeRequest{Name: "update-dangerous"})
|
|
_, err := svc.UpdateTheme(ctx, created.ID, &service.UpdateThemeRequest{
|
|
CustomCSS: "<script>alert('xss')</script>",
|
|
})
|
|
if err == nil {
|
|
t.Error("期望返回错误但没有")
|
|
}
|
|
})
|
|
}
|