Files
benevoles/backend/tests/test_api_notifications.py
T
AdamThomasandClaude Opus 5.5 8d6781e6ce
ci-cd / build-backend (push) Successful in 48s
ci-cd / deploy (push) Successful in 13s
ci-cd / build-frontend (push) Successful in 7s
Récapitulatif de planning : créneaux en tableau avec le référent
{creneaux} devient un tableau par jour de festival (horaire, poste,
référent avec son téléphone), en HTML dans l'email et en lignes lisibles
dans la version texte — envoi réel et email de test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:52:06 +01:00

132 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from sqlmodel import select
from app.models import Assignment, MagicLinkToken, Role
from tests.factories import dt_at, make_position, make_shift, make_volunteer
from tests.mail import plain_text
def _url(edition):
return f"/editions/{edition.id}/notifications/planning"
def test_one_email_per_volunteer_with_an_address(client, edition, session, outbox):
position = make_position(session, edition, name="Bar")
s1 = make_shift(session, edition, position, start=dt_at(10, 9), end=dt_at(10, 13))
s2 = make_shift(session, edition, position, start=dt_at(11, 9), end=dt_at(11, 12))
ana = make_volunteer(session, edition, first_name="Ana", email="ana@e.fr")
make_volunteer(session, edition, first_name="Bob", email="bob@e.fr")
make_volunteer(session, edition, first_name="Cid", email=None)
session.add_all(
[
Assignment(edition_id=edition.id, volunteer_id=ana.id, shift_id=s1.id),
Assignment(edition_id=edition.id, volunteer_id=ana.id, shift_id=s2.id),
]
)
session.commit()
resp = client.post(
_url(edition),
json={
"subject": "Planning de {prenom}",
"body": "Tu as {nb_creneaux} créneau(x), {nb_heures} h.\n{creneaux}",
},
)
assert resp.status_code == 200
body = resp.json()
assert body["queued"] == 2
assert body["skipped_no_email"] == 1
assert len(outbox) == 2
by_to = {m["To"]: m for m in outbox}
assert by_to["ana@e.fr"]["Subject"] == "Planning de Ana"
ana_body = plain_text(by_to["ana@e.fr"])
assert "Tu as 2 créneau(x), 7.0 h." in ana_body
assert "Bar" in ana_body
assert "Tu as 0 créneau(x), 0.0 h." in plain_text(by_to["bob@e.fr"])
def test_default_template_is_used_when_body_omitted(client, edition, session, outbox):
make_volunteer(session, edition, first_name="Ana", email="ana@e.fr")
resp = client.post(_url(edition), json={})
assert resp.status_code == 200
assert plain_text(outbox[0]).startswith("Bonjour Ana,")
def test_magic_link_is_embedded_when_placeholder_present(
client, edition, session, make_account, outbox
):
ana = make_volunteer(session, edition, first_name="Ana", email="ana@e.fr")
make_account(Role.VOLUNTEER, volunteer_id=ana.id, email="ana@e.fr")
resp = client.post(
_url(edition), json={"body": "Connecte-toi : {lien_connexion}"}
)
assert resp.status_code == 200
assert "/connexion?token=" in plain_text(outbox[0])
assert len(session.exec(select(MagicLinkToken)).all()) == 1
def test_no_magic_link_token_without_placeholder(
client, edition, session, make_account, outbox
):
ana = make_volunteer(session, edition, first_name="Ana", email="ana@e.fr")
make_account(Role.VOLUNTEER, volunteer_id=ana.id, email="ana@e.fr")
client.post(_url(edition), json={"body": "Bonjour {prenom}"})
assert session.exec(select(MagicLinkToken)).all() == []
def test_can_target_a_subset(client, edition, session, outbox):
ana = make_volunteer(session, edition, email="ana@e.fr")
make_volunteer(session, edition, email="bob@e.fr")
resp = client.post(
_url(edition), json={"volunteer_ids": [str(ana.id)]}
)
assert resp.json()["queued"] == 1
assert outbox[0]["To"] == "ana@e.fr"
def test_planning_notification_is_coordinator_only(
edition, session, make_account, as_account, outbox
):
lead = make_account(Role.LEAD, email="lead@e.fr")
resp = as_account(lead).post(_url(edition), json={})
assert resp.status_code == 403
def test_shifts_placeholder_is_a_table_by_day_with_the_referent(
client, edition, session, outbox, make_account
):
rita = make_volunteer(session, edition, first_name="Rita", last_name="Ref", email="r@e.fr")
rita.phone = "06 11 22 33 44"
session.add(rita)
lead = make_account(Role.LEAD, volunteer_id=rita.id)
bar = make_position(session, edition, name="Bar central")
bar.lead_account_id = lead.id
session.add(bar)
parking = make_position(session, edition, name="Parking")
s1 = make_shift(session, edition, bar, start=dt_at(10, 18), end=dt_at(10, 22))
s2 = make_shift(session, edition, parking, start=dt_at(11, 9), end=dt_at(11, 12))
ana = make_volunteer(session, edition, first_name="Ana", email="ana@e.fr")
session.add_all(
[
Assignment(edition_id=edition.id, volunteer_id=ana.id, shift_id=s1.id),
Assignment(edition_id=edition.id, volunteer_id=ana.id, shift_id=s2.id),
]
)
session.commit()
client.post(
_url(edition), json={"volunteer_ids": [str(ana.id)], "body": "Ton planning :\n\n{creneaux}"}
)
(message,) = outbox
html = message.get_body(preferencelist=("html",)).get_content()
# Vrai tableau : en-têtes, une ligne de jour, horaire, poste, référent.
assert "<table" in html and "Référent" in html
assert "18:00–22:00" in html and "Bar central" in html
assert "Rita Ref · 06 11 22 33 44" in html
assert "à désigner" in html # Parking n'a pas de référent
assert "" not in html
text = plain_text(message)
assert "18:00–22:00 · Bar central · référent : Rita Ref · 06 11 22 33 44" in text
assert "09:00–12:00 · Parking · référent : à désigner" in text