"""Tests for email rendering + dev fallback. SMTP submission itself isn't exercised here — covered by manual end-to-end test against real SMTP.""" from __future__ import annotations import asyncio import pytest from app.services import email_service def test_render_otp_email_returns_three_parts(): subject, text, html = email_service.render_otp_email("123456", 15) assert isinstance(subject, str) and isinstance(text, str) and isinstance(html, str) def test_render_otp_email_includes_code_and_ttl(): subject, text, html = email_service.render_otp_email("123456", 15) assert "Cassandra" in subject assert "123456" in subject # subject embeds the code for inbox visibility assert "123456" in text assert "123456" in html assert "15 minutes" in text assert "15 minutes" in html def test_render_otp_email_plain_text_part_has_no_html(): """The plain-text alternative must remain plain — no markup leaking in from the HTML template.""" _, text, _ = email_service.render_otp_email("000000", 15) assert "<" not in text and ">" not in text def test_render_otp_email_html_is_well_formed_doctype(): _, _, html = email_service.render_otp_email("000000", 15) assert html.lstrip().startswith("") assert "" in html def test_render_otp_email_html_has_preheader_and_responsive_styles(): _, _, html = email_service.render_otp_email("000000", 15) # Inbox preview snippet — must be present and contain the code. assert "Your Cassandra sign-in code" in html # Responsive + dark-mode media queries indicate cross-client robustness. assert "prefers-color-scheme" in html assert "@media (max-width" in html # No external assets — emails should render with network off. assert "http://" not in html assert "https://" not in html def test_send_email_falls_back_to_stdout_when_smtp_unset(monkeypatch): """When SMTP_SERVER is empty, send_email should log and return rather than attempting to connect.""" from app.config import Settings monkeypatch.setattr( "app.services.email_service.get_settings", lambda: Settings(SMTP_SERVER=""), ) asyncio.run(email_service.send_email("u@example.com", "test", "body")) def test_send_email_accepts_html_alternative(monkeypatch): """multipart/alternative is opt-in via the html_body kwarg; verify the call signature still works without it (plain-only path).""" from app.config import Settings monkeypatch.setattr( "app.services.email_service.get_settings", lambda: Settings(SMTP_SERVER=""), ) # plain-only asyncio.run(email_service.send_email("u@example.com", "t", "plain")) # with HTML asyncio.run(email_service.send_email("u@example.com", "t", "plain", html_body="

hi

"))