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