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: "", } _, 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: "", }) if err == nil { t.Error("期望返回错误但没有") } }) }