115 lines
3.9 KiB
Go
115 lines
3.9 KiB
Go
package test
|
|
|
|
import (
|
|
"RenewCMS/internal/infrastructure/config"
|
|
"RenewCMS/internal/infrastructure/mailer"
|
|
"RenewCMS/internal/infrastructure/useCases"
|
|
"bytes"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestInvitationsQaMailer(t *testing.T) {
|
|
repo := mailer.NewMailRepository(config.SmtpSettings{})
|
|
|
|
t.Run("The invitation renders with the inviter, the address and the accept link", func(t *testing.T) {
|
|
data := useCases.MailInviteData{Host: invitePublicURL, VerificationCode: "abc-123", Email: "lea@example.com", InvitedBy: "Ines Duarte"}
|
|
|
|
subject, body, err := repo.Render("invitation", data)
|
|
|
|
if err != nil {
|
|
t.Fatalf("unexpected error %v", err)
|
|
}
|
|
if subject != "Ines Duarte invited you to RenewCMS" {
|
|
t.Errorf("unexpected subject %q", subject)
|
|
}
|
|
for _, want := range []string{invitePublicURL + "/invite/accept?c=abc-123", "lea@example.com", "Ines Duarte"} {
|
|
if !strings.Contains(body, want) {
|
|
t.Errorf("body misses %q", want)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("The inviter name is HTML-escaped in the body", func(t *testing.T) {
|
|
data := useCases.MailInviteData{Host: invitePublicURL, VerificationCode: "abc-123", Email: "lea@example.com", InvitedBy: "<b>x</b>"}
|
|
|
|
_, body, err := repo.Render("invitation", data)
|
|
|
|
if err != nil {
|
|
t.Fatalf("unexpected error %v", err)
|
|
}
|
|
if strings.Contains(body, "<b>x</b>") || !strings.Contains(body, "<b>x</b>") {
|
|
t.Errorf("inviter name was not escaped")
|
|
}
|
|
})
|
|
|
|
t.Run("Other subjects are unchanged", func(t *testing.T) {
|
|
reset, _, err := repo.Render("password-reset", useCases.MailPasswordResetData{Host: invitePublicURL, VerificationCode: "x", Email: "a@b.example"})
|
|
if err != nil || reset != "Reset your RenewCMS password" {
|
|
t.Errorf("unexpected reset subject %q, %v", reset, err)
|
|
}
|
|
verification, _, err := repo.Render("verification", useCases.MailValidationData{Host: invitePublicURL, VerificationCode: "x"})
|
|
if err != nil || verification != "Verify your RenewCMS account" {
|
|
t.Errorf("unexpected verification subject %q, %v", verification, err)
|
|
}
|
|
})
|
|
|
|
t.Run("The shipped template is byte-identical to the design export", func(t *testing.T) {
|
|
shipped, err := os.ReadFile("../internal/infrastructure/mailer/templates/invitation.html")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
design, err := os.ReadFile("../docs/design/source/emails/invitation.html")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(shipped, design) {
|
|
t.Errorf("template differs from docs/design/source/emails/invitation.html")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestInvitationsQaList(t *testing.T) {
|
|
t.Run("Invite status follows its age", func(t *testing.T) {
|
|
f := newInviteFixture(t, 100)
|
|
now := time.Now()
|
|
f.invites.seed(inviteAt("old@renew.example", now.Add(-72*time.Hour-time.Minute), now.Add(-time.Minute)))
|
|
f.invites.seed(inviteAt("fresh@renew.example", now.Add(-48*time.Hour), now.Add(24*time.Hour)))
|
|
acceptedAt := now
|
|
accepted := inviteAt("done@renew.example", now.Add(-time.Hour), now.Add(71*time.Hour))
|
|
accepted.AcceptedAt = &acceptedAt
|
|
f.invites.seed(accepted)
|
|
|
|
rec := f.list(t)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", rec.Code)
|
|
}
|
|
statuses := map[string]string{}
|
|
for _, item := range decodeList(t, rec.Body.Bytes()) {
|
|
if decodedString(t, item, "kind") == "invite" {
|
|
statuses[decodedString(t, item, "email")] = decodedString(t, item, "status")
|
|
}
|
|
}
|
|
if len(statuses) != 2 || statuses["old@renew.example"] != "expired" || statuses["fresh@renew.example"] != "pending" {
|
|
t.Errorf("unexpected statuses %v", statuses)
|
|
}
|
|
})
|
|
|
|
t.Run("The list never carries secrets", func(t *testing.T) {
|
|
f := newInviteFixture(t, 100)
|
|
f.invites.seed(pendingInvite("sam@renew.example"))
|
|
|
|
body := f.list(t).Body.String()
|
|
|
|
for _, forbidden := range []string{"\"code\"", "hashed_code", "verification_code", "password"} {
|
|
if strings.Contains(body, forbidden) {
|
|
t.Errorf("list leaks %q", forbidden)
|
|
}
|
|
}
|
|
})
|
|
}
|