feat(slice-4): honest delivery failure — send-before-commit + 502 delivery_failed (INV-9; closes #7)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,3 +64,28 @@ def test_request_code_rejects_invalid_email(conn):
|
||||
with pytest.raises(accounts.InvalidEmail):
|
||||
accounts.request_code(conn, m, "not-an-email")
|
||||
assert m.outbox == []
|
||||
|
||||
|
||||
class _FailingMailer:
|
||||
"""A mailer whose relay always refuses — the INV-9 honest-failure path."""
|
||||
|
||||
def send(self, to: str, subject: str, body: str) -> None:
|
||||
raise mailer.MailerError("relay refused")
|
||||
|
||||
|
||||
def test_delivery_failure_leaves_no_orphan_code(conn):
|
||||
# ecomm#7: send happens BEFORE commit — a failed delivery must not strand an
|
||||
# auth_code row (which would also trip the resend cooldown for 60s).
|
||||
with pytest.raises(accounts.DeliveryFailed):
|
||||
accounts.request_code(conn, _FailingMailer(), "merchant@example.com")
|
||||
rows = conn.execute("SELECT count(*) FROM auth_code").fetchone()[0]
|
||||
assert rows == 0
|
||||
|
||||
|
||||
def test_delivery_failure_does_not_trip_cooldown(conn):
|
||||
with pytest.raises(accounts.DeliveryFailed):
|
||||
accounts.request_code(conn, _FailingMailer(), "merchant@example.com")
|
||||
# the immediate retry (relay back up) succeeds — no ResendCooldown
|
||||
m = mailer.LogMailer()
|
||||
accounts.request_code(conn, m, "merchant@example.com")
|
||||
assert len(m.outbox) == 1
|
||||
|
||||
Reference in New Issue
Block a user