package test import ( "RenewCMS/internal/infrastructure/config" "RenewCMS/internal/infrastructure/mailer" "RenewCMS/internal/infrastructure/useCases" "os" "strings" "testing" ) func TestTransactionalEmailTemplates(t *testing.T) { t.Run("render() produces the verification email's subject, link and copy", func(t *testing.T) { repo := mailer.NewMailRepository(config.SmtpSettings{}) subject, body, err := repo.Render("verification", useCases.MailValidationData{ Host: "https://cms.example.com", VerificationCode: "abc123", }) if err != nil { t.Fatalf("expected no error, got %v", err) } if subject != "Verify your RenewCMS account" { t.Errorf("expected subject %q, got %q", "Verify your RenewCMS account", subject) } if !strings.Contains(body, "https://cms.example.com/register/validate?c=abc123") { t.Errorf("expected body to contain the verification link, got %q", body) } if !strings.Contains(body, "Verify my account") { t.Errorf("expected body to contain the button text, got %q", body) } if !strings.Contains(body, "This link expires in 2 hours.") { t.Errorf("expected body to contain the expiry copy, got %q", body) } }) t.Run("render() produces the password-reset email's subject, link and copy", func(t *testing.T) { repo := mailer.NewMailRepository(config.SmtpSettings{}) subject, body, err := repo.Render("password-reset", useCases.MailPasswordResetData{ Host: "https://cms.example.com", VerificationCode: "abc123", Email: "alice@example.com", }) if err != nil { t.Fatalf("expected no error, got %v", err) } if subject != "Reset your RenewCMS password" { t.Errorf("expected subject %q, got %q", "Reset your RenewCMS password", subject) } if !strings.Contains(body, "https://cms.example.com/register/reset/validate?c=abc123&email=alice%40example.com") { t.Errorf("expected body to contain the password-reset link, got %q", body) } if !strings.Contains(body, "Choose a new password") { t.Errorf("expected body to contain the button text, got %q", body) } if !strings.Contains(body, "This link expires in 1 hour and works once.") { t.Errorf("expected body to contain the expiry copy, got %q", body) } }) t.Run("render() falls back to the old default subject for an unrecognized template name", func(t *testing.T) { repo := mailer.NewMailRepository(config.SmtpSettings{}) subject, body, err := repo.Render("does-not-exist", nil) if subject != "RenewCMS | Action required" { t.Errorf("expected fallback subject, got %q", subject) } if err == nil { t.Fatal("expected an error because templates/does-not-exist.html cannot be found") } if body != "" { t.Errorf("expected empty body, got %q", body) } }) t.Run("A template execution failure is returned without sending", func(t *testing.T) { repo := mailer.NewMailRepository(config.SmtpSettings{}) type incompatibleData struct { Unrelated int } _, body, err := repo.Render("verification", incompatibleData{Unrelated: 1}) if err == nil { t.Fatal("expected an error from a failed template execution") } if body != "" { t.Errorf("expected empty body, got %q", body) } }) t.Run("Send() returns a render error without dialing SMTP", func(t *testing.T) { repo := mailer.NewMailRepository(config.SmtpSettings{}) _, _, renderErr := repo.Render("does-not-exist", nil) err := repo.Send("someone@example.com", "does-not-exist", nil) if err == nil { t.Fatal("expected an error from a failed render, got nil") } if err.Error() != renderErr.Error() { t.Errorf("expected Send to return the render error %q, got %q", renderErr, err) } }) t.Run("The old template files no longer exist under their previous names", func(t *testing.T) { for _, oldFile := range []string{"mailValidation.html", "passwordReset.html"} { path := "../internal/infrastructure/mailer/templates/" + oldFile if _, err := os.Stat(path); !os.IsNotExist(err) { t.Errorf("expected %s to not exist, got err=%v", path, err) } } }) }