From aea47d83657558156cddf4c9d7aa77a4ad65a05c Mon Sep 17 00:00:00 2001 From: Peter Woolery Date: Fri, 8 May 2026 21:40:00 -0700 Subject: [PATCH] fix: escape member.name in step_email; add all-voted reminder test --- backend/app/services/orchestrator/steps.py | 2 +- backend/tests/test_orchestrator.py | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/backend/app/services/orchestrator/steps.py b/backend/app/services/orchestrator/steps.py index b936c60..75728a9 100644 --- a/backend/app/services/orchestrator/steps.py +++ b/backend/app/services/orchestrator/steps.py @@ -145,7 +145,7 @@ def step_email(run: "WeeklyRun", db: "Session") -> None: email_html = ( f"

This week's meal suggestions

" f"{stale_banner}" - f"

Hi {member.name}, please vote on this week's meals by Fri 17:00 PT:

" + f"

Hi {html.escape(member.name)}, please vote on this week's meals by Fri 17:00 PT:

" f"" f"

Silence = approved. Any denial removes that meal.

" ) diff --git a/backend/tests/test_orchestrator.py b/backend/tests/test_orchestrator.py index 08fff3f..badc139 100644 --- a/backend/tests/test_orchestrator.py +++ b/backend/tests/test_orchestrator.py @@ -417,6 +417,36 @@ def test_step_reminder_skips_voter( assert weekly_run_emailed.reminded_at is not None +def test_step_reminder_no_sends_when_all_voted( + db, weekly_run_emailed, meal_plan, pending_item, member, monkeypatch +): + from app.models import MealPlanVote + # Member has voted on the only pending item + vote = MealPlanVote( + meal_plan_item_id=pending_item.id, + family_member_id=member.id, + vote=True, + ) + db.add(vote) + db.flush() + + sent = [] + + class FakeBackend: + def send(self, **kwargs): + sent.append(kwargs) + + monkeypatch.setattr( + "app.services.orchestrator.steps.get_email_backend", + lambda: FakeBackend(), + ) + from app.services.orchestrator.steps import step_reminder + step_reminder(weekly_run_emailed, db) + # All items voted on — no emails sent, but reminded_at still stamped + assert len(sent) == 0 + assert weekly_run_emailed.reminded_at is not None + + # --------------------------------------------------------------------------- # step_deadline tests # ---------------------------------------------------------------------------