@@ -265,6 +265,7 @@ def test_create_history_marks_sent_to_failed_when_send_raises(api_client, sms_te
265265 body = response .json ()
266266 assert body ["sent_to_status_summary" ]["failed" ] == 1
267267 assert body ["sent_to_list" ][0 ]["status" ] == NotificationStatus .FAILED
268+ assert "external api down" in body ["sent_to_list" ][0 ]["failure_reason" ]
268269
269270
270271@pytest .mark .django_db (transaction = True )
@@ -426,6 +427,66 @@ def test_retry_noop_when_no_failed_sent_to(api_client, email_history):
426427 mock_client .send_message .assert_not_called ()
427428
428429
430+ # ---- History Render SentTo As HTML -----------------------------------------
431+
432+
433+ @pytest .mark .django_db
434+ def test_render_sent_to_as_html_returns_html_with_rendered_context (api_client , email_history ):
435+ sent_to = email_history .sent_to_list .get ()
436+ response = api_client .get (
437+ reverse (
438+ "v1:admin-notification-email-history-render-sent-to-as-html" ,
439+ kwargs = {"pk" : email_history .id , "sent_to_id" : sent_to .id },
440+ )
441+ )
442+ assert response .status_code == http .HTTPStatus .OK
443+ assert response ["Content-Type" ].startswith ("text/html" )
444+ body = response .content .decode ()
445+ assert body .lstrip ().startswith ("<html" )
446+ # email_history fixture의 context (name="길동")가 template_data를 거쳐 HTML에 반영되어야 함.
447+ assert "Hi 길동" in body
448+ assert "Hello 길동" in body
449+
450+
451+ @pytest .mark .django_db
452+ def test_render_sent_to_as_html_uses_history_template_data_snapshot (api_client , email_history , email_template ):
453+ # History.template_data는 발송 시점의 snapshot이므로, 이후 Template.data를 바꿔도
454+ # 기존 sent_to의 렌더 결과는 영향을 받지 않아야 한다.
455+ sent_to = email_history .sent_to_list .get ()
456+ url = reverse (
457+ "v1:admin-notification-email-history-render-sent-to-as-html" ,
458+ kwargs = {"pk" : email_history .id , "sent_to_id" : sent_to .id },
459+ )
460+
461+ before = api_client .get (url ).content .decode ()
462+
463+ email_template .data = '{"title":"DIFFERENT {{ name }}","from_":"X","send_to":"Y","body":"CHANGED {{ name }}"}'
464+ email_template .save ()
465+
466+ after = api_client .get (url ).content .decode ()
467+ assert before == after
468+ assert "Hi 길동" in after
469+ assert "Hello 길동" in after
470+ assert "DIFFERENT" not in after
471+ assert "CHANGED" not in after
472+
473+
474+ @pytest .mark .django_db
475+ def test_render_sent_to_as_html_404_when_sent_to_belongs_to_other_history (api_client , email_history , email_template ):
476+ other = EmailNotificationHistory .objects .create_for_recipients (
477+ template = email_template ,
478+ recipients = [{"recipient" : "other@example.com" , "context" : {"name" : "다른" , "recipient" : "y" }}],
479+ )
480+ other_sent_to = other .sent_to_list .get ()
481+ response = api_client .get (
482+ reverse (
483+ "v1:admin-notification-email-history-render-sent-to-as-html" ,
484+ kwargs = {"pk" : email_history .id , "sent_to_id" : other_sent_to .id },
485+ )
486+ )
487+ assert response .status_code == http .HTTPStatus .NOT_FOUND
488+
489+
429490# ---- 채널 간 격리 -----------------------------------------------------------
430491
431492
0 commit comments