email: render_digest_email — multipart digest template

Adds render_digest_email(kind, date_str, content_html, unsubscribe_url,
settings_url) -> tuple[str, str, str] to email_service.py, following the
same contract as render_otp_email. Includes _DIGEST_HTML_TEMPLATE with
light/dark palette from branding and _strip_html_to_text for the plain-text
fallback. Unit tests in tests/test_email_render.py cover daily, weekly, and
invalid-kind cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Giorgio Gilestro 2026-05-25 23:02:05 +02:00
parent 1391f15c28
commit a4e585fbfb
2 changed files with 150 additions and 0 deletions

View file

@ -0,0 +1,44 @@
"""Unit tests for render_digest_email."""
from __future__ import annotations
from app.services.email_service import render_digest_email
def test_daily_subject_and_bodies():
subj, text, html = render_digest_email(
kind="daily",
date_str="2026-05-25",
content_html="<p>Markets did stuff today.</p>",
unsubscribe_url="https://read.markets/email/unsubscribe?token=abc",
settings_url="https://read.markets/settings",
)
assert "Daily" in subj
assert "2026-05-25" in subj
assert "Markets did stuff today" in html
assert "abc" in html # unsubscribe link landed
assert "/settings" in html
# Plain-text fallback strips HTML.
assert "<p>" not in text
assert "Markets did stuff today" in text
def test_weekly_subject_says_recap():
subj, _, _ = render_digest_email(
kind="weekly",
date_str="2026-05-25",
content_html="<p>x</p>",
unsubscribe_url="https://x/u",
settings_url="https://x/s",
)
assert "Weekly" in subj
assert "recap" in subj.lower()
def test_invalid_kind_raises():
import pytest
with pytest.raises(ValueError):
render_digest_email(
kind="bogus", date_str="2026-05-25",
content_html="<p>x</p>",
unsubscribe_url="u", settings_url="s",
)