Preconditions
Organizer can access Event Setup and the fixture event has published and draft email designs plus invited, confirmed, bounced, and empty-audience recipients.
Happy path
Open Email designs.
The paginated design list shows design name, message type, draft/published status, and last test-send status.
Edit a design body.
The rich text editor preserves reusable design content separately from a single message send.
Preview, publish, and send a test.
Preview makes draft/published divergence obvious and test-send uses an idempotency key.
Failure modes
Send blocked on validation failure
Trigger: unresolved design token or invalid message type.
Resolution: send is blocked with 400 validation copy and no partial-send.
Bounced recipient tracked and suppressed
Trigger: a test recipient hard-bounces.
Resolution: bounce event is stored and future sends to that address are suppressed.
Scheduled-message edit window
Trigger: organizer edits a scheduled send using this design after the edit cutoff.
Resolution: API returns 409 PAST_EDIT_WINDOW and keeps the queued snapshot unchanged.
Retry on transient failure
Trigger: Cloudflare Email API returns 5xx during a design-backed send.
Resolution: retry uses the same Idempotency-Key and the recipient receives at most one email.
Idempotency-key on test-send
Trigger: organizer double-clicks Send test.
Resolution: one test email is queued and the per-test Idempotency-Key is sent.
Recipient resolution empty
Trigger: selected audience has zero recipients.
Resolution: API returns 409 NO_RECIPIENTS and the UI says no recipients match this audience.
Token rendering fallback
Trigger: {guest.firstName} is missing.
Resolution: preview and send use a fallback, never an awkward empty merge.
Cancel scheduled before send
Trigger: organizer cancels a scheduled design-backed message.
Resolution: queue pending count decrements, reserved sends are refunded, and cancellation is audited.
Preview versus published divergence
Trigger: draft content differs from the published design used for send.
Resolution: UI labels both snapshots and send uses the explicit selected snapshot.
Design-list pagination stability
Trigger: organizer changes page while filters are active.
Resolution: page and filter state remain URL-addressable and counts stay consistent.
Deployed-runtime gap
Trigger: deployed run on 2026-04-29 observed template API 404 for /admin/.../email-templates; the probe locks this in until the gap is closed.
Resolution: the story expects the documented 404 so a later 2xx fails the gap probe and prompts tightening.
Stable test attributes
Visibility teeth. Each attribute must be effectively visible when active.
| data-test | Where | Purpose |
|---|---|---|
email-designs-page | Page | Design manager |
email-designs-table | Page | Paginated designs |
email-design-editor | Editor | Design body |
message-type-picker | Form | Message type |
email-design-preview | Preview | Rendered snapshot |
email-design-publish-cta | Toolbar | Publish |
email-design-test-send-cta | Toolbar | Test-send |
email-design-gap-panel | Page | Runtime gap |
email-design-warning | Page | Validation warning |
Agent test plan
- email-designs-renders
- publish-design
- test-send-idempotent
- deployed-runtime-gap