feat: new emails design
This commit is contained in:
1 parent
4e41d60142
commit
30a4df47b1
15 files changed
+498
-68
No files matched your search
@@ -0,0 +1,114 @@
|
||||
Feature: The two transactional email templates are replaced by the design's ready-to-use files
|
||||
|
||||
As the maintainer of RenewCMS
|
||||
I want the verification and password-reset emails to use the exact Go html/template files from
|
||||
docs/design/source/emails/, renamed to match the design's naming, instead of the old ad hoc
|
||||
mailValidation.html and passwordReset.html files
|
||||
So that account-verification and password-reset emails match the visual spec (bulletproof button,
|
||||
preheader, dark-mode overrides), and the template name used at the call site reflects the file it
|
||||
now loads
|
||||
|
||||
Background:
|
||||
Given internal/infrastructure/mailer/templates/mailValidation.html is removed and replaced by
|
||||
internal/infrastructure/mailer/templates/verification.html, copied verbatim from
|
||||
docs/design/source/emails/verification.html, still driven by a Go struct with a Host field and
|
||||
a VerificationCode field (the existing MailValidationData shape in CreateUser.go is unchanged)
|
||||
And internal/infrastructure/mailer/templates/passwordReset.html is removed and replaced by
|
||||
internal/infrastructure/mailer/templates/password-reset.html, copied verbatim from
|
||||
docs/design/source/emails/password-reset.html, still driven by a Go struct with a Host field, a
|
||||
VerificationCode field and an Email field (the existing MailPasswordResetData shape in
|
||||
RequestPasswordReset.go is unchanged)
|
||||
And MailRepository.Send (internal/infrastructure/mailer/mailRepository.go) is unchanged code: it
|
||||
already loads "templates/" + templateName + ".html" via template.ParseFS, so it now resolves
|
||||
the templateName "verification" to the new verification.html file and "password-reset" to the
|
||||
new password-reset.html file, purely because of the rename, with no change to Send's own logic
|
||||
And CreateUserUseCase.CreateUser (internal/infrastructure/useCases/CreateUser.go) now calls
|
||||
mail.Repository.Send with template "verification" instead of the old "mailValidation"; nothing
|
||||
else about that call changes: the receiver address, and the Host/VerificationCode data, are as
|
||||
before
|
||||
And RequestPasswordResetUseCase.RequestPasswordReset
|
||||
(internal/infrastructure/useCases/RequestPasswordReset.go) now calls mail.Repository.Send with
|
||||
template "password-reset" instead of the old "passwordReset"; nothing else about that call
|
||||
changes: the receiver address, and the Host/VerificationCode/Email data, are as before
|
||||
And the verification email's link is still built as
|
||||
"{{.Host}}/register/validate?c={{.VerificationCode}}" and the password-reset email's link is
|
||||
still built as
|
||||
"{{.Host}}/register/reset/validate?c={{.VerificationCode}}&email={{.Email}}", matching both the
|
||||
old templates and the use cases that populate them, so no handler, use case or route changes
|
||||
as a result of this slice
|
||||
And MailRepository (internal/infrastructure/mailer/mailRepository.go) gains an unexported render
|
||||
step, e.g. render(templateName string, data any) (subject string, body string, err error),
|
||||
that Send calls before dialing; render selects the subject by templateName ("Verify your
|
||||
RenewCMS account" for "verification", "Reset your RenewCMS password" for "password-reset",
|
||||
matching docs/design/emails.md's suggested subjects exactly) and parses/executes the
|
||||
corresponding templates/<templateName>.html file, returning its rendered body; Send then uses
|
||||
that subject and body to build and dial the message exactly as before, and any ParseFS or
|
||||
Execute error from render is returned by Send unchanged, with the same log.Println call sites
|
||||
as today
|
||||
And an unrecognized templateName still reaches template.ParseFS, which fails to find
|
||||
"templates/<templateName>.html" and returns its usual error; render does not special-case
|
||||
unknown names beyond the two known subjects, so an unknown templateName's subject falls back to
|
||||
the same literal "RenewCMS | Action required" used before this slice, and Send still returns
|
||||
the ParseFS error without attempting to dial
|
||||
And the two feature files that already assert a template-name string literal,
|
||||
registration_gate_and_verification_email.feature and request_password_reset.feature, are
|
||||
updated in this same slice so every occurrence of "mailValidation" reads "verification" and
|
||||
every occurrence of "passwordReset" reads "password-reset"; their behaviour is otherwise
|
||||
unchanged
|
||||
|
||||
Scenario: Registering a user sends the verification email under its new template name
|
||||
Given the user repository is empty
|
||||
When the client sends POST /v1/auth/register with username "alice", password "hunter2example12",
|
||||
email "alice@example.com"
|
||||
Then the response status is 200
|
||||
And exactly one email was sent to "alice@example.com" using template "verification"
|
||||
And that email's data has Host and VerificationCode populated exactly as before this slice
|
||||
|
||||
Scenario: Requesting a password reset sends the reset email under its new template name
|
||||
Given the user repository contains a user "alice" with email "alice@example.com"
|
||||
When the client sends POST /v1/auth/password-reset with body {"email": "alice@example.com"}
|
||||
Then the response status is 200
|
||||
And exactly one email was sent to "alice@example.com" using template "password-reset"
|
||||
And that email's data has Host, VerificationCode and Email populated exactly as before this slice
|
||||
|
||||
Scenario: render() produces the verification email's subject, link and copy
|
||||
Given a real *mailer.MailRepository
|
||||
When its render step is called with templateName "verification" and data whose Host is
|
||||
"https://cms.example.com" and whose VerificationCode is "abc123"
|
||||
Then the returned subject is "Verify your RenewCMS account"
|
||||
And the returned body contains the link "https://cms.example.com/register/validate?c=abc123"
|
||||
And the returned body contains the button text "Verify my account"
|
||||
And the returned body contains the text "This link expires in 2 hours."
|
||||
|
||||
Scenario: render() produces the password-reset email's subject, link and copy
|
||||
Given a real *mailer.MailRepository
|
||||
When its render step is called with templateName "password-reset" and data whose Host is
|
||||
"https://cms.example.com", whose VerificationCode is "abc123" and whose Email is
|
||||
"alice@example.com"
|
||||
Then the returned subject is "Reset your RenewCMS password"
|
||||
And the returned body contains the link
|
||||
"https://cms.example.com/register/reset/validate?c=abc123&email=alice%40example.com"
|
||||
And the returned body contains the button text "Choose a new password"
|
||||
And the returned body contains the text "This link expires in 1 hour and works once."
|
||||
|
||||
Scenario: render() falls back to the old default subject for an unrecognized template name
|
||||
Given a real *mailer.MailRepository
|
||||
When its render step is called with templateName "does-not-exist" and any data
|
||||
Then the returned subject is "RenewCMS | Action required"
|
||||
And an error is returned because templates/does-not-exist.html cannot be found
|
||||
And the returned body is empty
|
||||
|
||||
Scenario: A template execution failure is returned without sending
|
||||
Given a real *mailer.MailRepository
|
||||
And data that causes Execute to fail for a known templateName (e.g. a type without the fields
|
||||
the template references)
|
||||
When its render step is called with that templateName and that data
|
||||
Then render returns an error and MailRepository.Send never reaches DialAndSend
|
||||
|
||||
Scenario Outline: The old template files no longer exist under their previous names
|
||||
Then the file internal/infrastructure/mailer/templates/<old file> does not exist on disk
|
||||
|
||||
Examples:
|
||||
| old file |
|
||||
| mailValidation.html |
|
||||
| passwordReset.html |
|
||||
Reference in new issue
Block a user