package usecase import ( "backend/pkg/notification/domain/entity" "backend/pkg/notification/domain/template" "backend/pkg/notification/domain/usecase" "context" "testing" "github.com/stretchr/testify/assert" ) func TestTemplateUseCase_RenderEmailTemplate(t *testing.T) { uc := MustTemplateUseCase(TemplateUseCaseParam{ TemplateRepo: nil, }) ctx := context.Background() tests := []struct { name string tmpl template.EmailTemplate params entity.TemplateParams expectedSubj string expectedBody string shouldContain []string shouldNotError bool }{ { name: "渲染基本參數", tmpl: template.EmailTemplate{ Title: "Hello {{.Username}}", Body: "

Your code is: {{.VerifyCode}}

", }, params: entity.TemplateParams{ Username: "張三", VerifyCode: "123456", }, expectedSubj: "Hello 張三", shouldContain: []string{"123456"}, shouldNotError: true, }, { name: "渲染額外參數", tmpl: template.EmailTemplate{ Title: "Welcome", Body: "

Hello {{.Username}}, your link: {{.Link}}

", }, params: entity.TemplateParams{ Username: "John", Extra: map[string]string{ "Link": "https://example.com", }, }, shouldContain: []string{"John", "https://example.com"}, shouldNotError: true, }, { name: "特殊字符不轉義(簡單字符串替換)", tmpl: template.EmailTemplate{ Title: "Test", Body: "

Name: {{.Username}}

", }, params: entity.TemplateParams{ Username: "", }, shouldContain: []string{""}, // 使用簡單字符串替換,不轉義 shouldNotError: true, }, { name: "空模板", tmpl: template.EmailTemplate{ Title: "", Body: "", }, params: entity.TemplateParams{ Username: "Test", }, expectedSubj: "", expectedBody: "", shouldNotError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := uc.RenderEmailTemplate(ctx, tt.tmpl, tt.params) if tt.shouldNotError { assert.NoError(t, err) if tt.expectedSubj != "" { assert.Equal(t, tt.expectedSubj, result.Subject) } if tt.expectedBody != "" { assert.Equal(t, tt.expectedBody, result.Body) } for _, contain := range tt.shouldContain { assert.Contains(t, result.Body, contain) } } else { assert.Error(t, err) } }) } } func TestTemplateUseCase_RenderSMSTemplate(t *testing.T) { uc := MustTemplateUseCase(TemplateUseCaseParam{ TemplateRepo: nil, }) ctx := context.Background() tests := []struct { name string tmpl usecase.SMSTemplateResp params entity.TemplateParams expectedBody string shouldContain []string shouldNotError bool }{ { name: "渲染 SMS 驗證碼", tmpl: usecase.SMSTemplateResp{ Body: "您的驗證碼是:{{.VerifyCode}},請在5分鐘內使用。", }, params: entity.TemplateParams{ VerifyCode: "654321", }, shouldContain: []string{"654321", "5分鐘"}, shouldNotError: true, }, { name: "SMS 純文本替換", tmpl: usecase.SMSTemplateResp{ Body: "Hi {{.Username}}, your code: {{.VerifyCode}}", }, params: entity.TemplateParams{ Username: "", VerifyCode: "111111", }, shouldContain: []string{"", "111111"}, // 使用簡單字符串替換 shouldNotError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := uc.RenderSMSTemplate(ctx, tt.tmpl, tt.params) if tt.shouldNotError { assert.NoError(t, err) if tt.expectedBody != "" { assert.Equal(t, tt.expectedBody, result.Body) } for _, contain := range tt.shouldContain { assert.Contains(t, result.Body, contain) } } else { assert.Error(t, err) } }) } } func TestTemplateUseCase_GetEmailTemplateByStatic(t *testing.T) { uc := MustTemplateUseCase(TemplateUseCaseParam{ TemplateRepo: nil, }) ctx := context.Background() tests := []struct { name string language template.Language templateID template.Type wantErr bool }{ { name: "獲取忘記密碼模板 (zh-tw)", language: template.LanguageZhTW, templateID: template.ForgetPasswordVerify, wantErr: false, }, { name: "獲取綁定郵箱模板 (zh-tw)", language: template.LanguageZhTW, templateID: template.BindingEmail, wantErr: false, }, { name: "不存在的語言", language: template.Language("xx-xx"), templateID: template.ForgetPasswordVerify, wantErr: true, }, { name: "不存在的模板類型", language: template.LanguageZhTW, templateID: template.Type("non_existent"), wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := uc.GetEmailTemplateByStatic(ctx, tt.language, tt.templateID) if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) assert.NotEmpty(t, result.Title) assert.NotEmpty(t, result.Body) } }) } } func TestTemplateUseCase_GetDefaultSMSTemplate(t *testing.T) { uc := &TemplateUseCase{} tests := []struct { name string templateID template.Type shouldContain []string }{ { name: "忘記密碼模板", templateID: template.ForgetPasswordVerify, shouldContain: []string{"密碼重設", "驗證碼"}, }, { name: "綁定郵箱模板", templateID: template.BindingEmail, shouldContain: []string{"綁定", "驗證碼"}, }, { name: "默認模板", templateID: template.Type("unknown"), shouldContain: []string{"驗證碼"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := uc.getDefaultSMSTemplate(tt.templateID) assert.NotEmpty(t, result.Body) for _, contain := range tt.shouldContain { assert.Contains(t, result.Body, contain) } }) } }