package lib import ( "os" "path/filepath" "strings" "testing" ) func TestSendTemplate(t *testing.T) { // Create a mailer with templates loaded m := &Mailer{enabled: true} // Find the email templates directory templateDir := "../portal/emails" if _, err := os.Stat(templateDir); os.IsNotExist(err) { templateDir = "portal/emails" if _, err := os.Stat(templateDir); os.IsNotExist(err) { t.Skipf("email templates directory not found, skipping test") } } absPath, err := filepath.Abs(templateDir) if err != nil { t.Fatalf("failed to get absolute path: %v", err) } if err := m.LoadTemplates(absPath); err != nil { t.Fatalf("failed to load templates: %v", err) } tests := []struct { name string tmplName string data any expected []string }{ { name: "invite", tmplName: "invite.html", data: InviteData{ InviterName: "Sarah Mitchell", InviterOrg: "Goldman Sachs", ProjectName: "Project Phoenix", InviteURL: "https://app.muskepo.com/invite/abc123", RecipientName: "John Smith", ExpiresIn: "7 days", }, expected: []string{"Sarah Mitchell", "Goldman Sachs", "Project Phoenix", "Accept Invitation", "DEALSPACE"}, }, { name: "tasks_assigned", tmplName: "tasks_assigned.html", data: TasksAssignedData{ RecipientName: "John Smith", ProjectName: "Project Phoenix", Count: 3, Tasks: []TaskItem{ {Title: "FIN-001: Audited financials", DueDate: "March 15", Priority: "high"}, }, TasksURL: "https://app.muskepo.com/app/tasks", }, expected: []string{"John Smith", "Project Phoenix", "3 new tasks", "View My Tasks"}, }, { name: "answer_submitted", tmplName: "answer_submitted.html", data: AnswerSubmittedData{ AnswererName: "John Smith", RequestTitle: "FIN-001: Audited financials", WorkstreamName: "Finance", ReviewURL: "https://app.muskepo.com/app/review/ans_xyz123", }, expected: []string{"John Smith", "FIN-001: Audited financials", "Finance", "Review Answer"}, }, { name: "answer_approved", tmplName: "answer_approved.html", data: AnswerApprovedData{ RequestTitle: "FIN-001: Audited financials", Published: true, }, expected: []string{"Your answer was approved", "FIN-001: Audited financials", "Published to Data Room"}, }, { name: "answer_rejected", tmplName: "answer_rejected.html", data: AnswerRejectedData{ RequestTitle: "FIN-001: Audited financials", Reason: "Need final audited version", RequestURL: "https://app.muskepo.com/app/tasks/req_001", }, expected: []string{"Your answer needs revision", "FIN-001: Audited financials", "View Feedback"}, }, { name: "request_forwarded", tmplName: "request_forwarded.html", data: RequestForwardedData{ SenderName: "John Smith", RequestTitle: "FIN-003: AR aging report", RequestURL: "https://app.muskepo.com/app/tasks/req_003", DueDate: "March 18, 2026", HasDueDate: true, }, expected: []string{"John Smith", "FIN-003: AR aging report", "View Request", "March 18, 2026"}, }, { name: "welcome", tmplName: "welcome.html", data: WelcomeData{ RecipientName: "John Smith", TasksURL: "https://app.muskepo.com/app/tasks", }, expected: []string{"Welcome to Dealspace", "John Smith", "Your inbox is your home", "Ask Aria", "Go to My Tasks"}, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result, err := m.RenderTemplate(tc.tmplName, tc.data) if err != nil { t.Fatalf("RenderTemplate(%s) failed: %v", tc.tmplName, err) } if len(result) == 0 { t.Errorf("RenderTemplate(%s) returned empty result", tc.tmplName) } for _, expected := range tc.expected { if !strings.Contains(result, expected) { t.Errorf("RenderTemplate(%s) missing expected string: %q", tc.tmplName, expected) } } if !strings.Contains(result, "") { t.Errorf("RenderTemplate(%s) missing DOCTYPE", tc.tmplName) } }) } } func TestMailerDisabled(t *testing.T) { m := &Mailer{enabled: false} err := m.Send("test@example.com", "Test Subject", "test") if err != nil { t.Errorf("Send on disabled mailer should return nil, got: %v", err) } err = m.SendTemplate("test@example.com", "Test Subject", "invite.html", nil) if err != nil { t.Errorf("SendTemplate on disabled mailer should return nil, got: %v", err) } } func TestMailerEnabled(t *testing.T) { enabled := &Mailer{enabled: true} disabled := &Mailer{enabled: false} if !enabled.Enabled() { t.Error("enabled mailer should return true for Enabled()") } if disabled.Enabled() { t.Error("disabled mailer should return false for Enabled()") } } func TestBase64Encode(t *testing.T) { tests := []struct { input string expected string }{ {"", ""}, {"f", "Zg=="}, {"fo", "Zm8="}, {"foo", "Zm9v"}, {"foobar", "Zm9vYmFy"}, } for _, tc := range tests { result := base64Encode(tc.input) if result != tc.expected { t.Errorf("base64Encode(%q) = %q, want %q", tc.input, result, tc.expected) } } } func TestEmailFuncs(t *testing.T) { funcs := emailFuncs() gt := funcs["gt"].(func(int, int) bool) if !gt(5, 3) { t.Error("gt(5, 3) should be true") } sub := funcs["sub"].(func(int, int) int) if sub(10, 3) != 7 { t.Error("sub(10, 3) should be 7") } truncate := funcs["truncate"].(func(string, int) string) if truncate("hello world", 5) != "hello..." { t.Error("truncate('hello world', 5) should be 'hello...'") } }