package email import ( "strings" "testing" ) func TestRender_FileChanged(t *testing.T) { subject, body, err := Render("file_changed", TemplateData{ ActorName: "Alice", DocumentPath: "docs/api.md", DocumentTitle: "API Reference", ViewURL: "https://example.com/docs/api.md", UnsubURL: "https://example.com/unsub/123", InstanceName: "Cairnquire", }) if err != nil { t.Fatalf("Render: %v", err) } if !strings.Contains(subject, "docs/api.md") { t.Errorf("subject should include path: %q", subject) } if !strings.Contains(subject, "Alice") { t.Errorf("subject should include actor: %q", subject) } if !strings.Contains(body, "Alice") { t.Errorf("body should mention actor: %q", body) } if !strings.Contains(body, "API Reference") { t.Errorf("body should mention title: %q", body) } if !strings.Contains(body, "https://example.com/docs/api.md") { t.Errorf("body should include view url: %q", body) } if !strings.Contains(body, "https://example.com/unsub/123") { t.Errorf("body should include unsub url: %q", body) } } func TestRender_Comment(t *testing.T) { subject, body, err := Render("comment", TemplateData{ ActorName: "Bob", DocumentTitle: "Getting Started", CommentBody: "This step is unclear.\nCan we add an example?", ViewURL: "https://example.com/docs/getting-started", }) if err != nil { t.Fatalf("Render: %v", err) } if !strings.Contains(subject, "Bob") { t.Errorf("subject should include actor: %q", subject) } if !strings.Contains(body, "> This step is unclear.") { t.Errorf("body should quote comment: %q", body) } if !strings.Contains(body, "> Can we add an example?") { t.Errorf("body should quote second line: %q", body) } if !strings.Contains(body, "Reply to this email") { t.Errorf("body should mention reply-to-respond: %q", body) } } func TestRender_Mention(t *testing.T) { subject, body, err := Render("mention", TemplateData{ ActorName: "Carol", DocumentTitle: "Spec", MentionText: "@dan please review", }) if err != nil { t.Fatalf("Render: %v", err) } if !strings.Contains(subject, "Mention") { t.Errorf("subject: %q", subject) } if !strings.Contains(body, "> @dan please review") { t.Errorf("body should quote mention: %q", body) } } func TestRender_Conflict(t *testing.T) { subject, body, err := Render("conflict", TemplateData{ DocumentPath: "notes/2024.md", ConflictDesc: "Local and remote both edited line 12", }) if err != nil { t.Fatalf("Render: %v", err) } if !strings.Contains(subject, "conflict") { t.Errorf("subject: %q", subject) } if !strings.Contains(body, "sync conflict") { t.Errorf("body should mention conflict: %q", body) } if !strings.Contains(body, "line 12") { t.Errorf("body should include conflict desc: %q", body) } } func TestRender_UnknownKind(t *testing.T) { _, _, err := Render("bogus", TemplateData{}) if err == nil { t.Fatal("expected error for unknown kind") } } func TestRender_PlainTextOnly(t *testing.T) { for _, kind := range []string{"file_changed", "comment", "mention", "conflict"} { _, body, err := Render(kind, TemplateData{ ActorName: "A", DocumentTitle: "T", CommentBody: "html", }) if err != nil { t.Fatalf("Render %s: %v", kind, err) } if strings.Contains(body, "") || strings.Contains(body, "") { t.Errorf("template %s produced HTML: %q", kind, body) } } }