Files
benevoles/backend/tests/test_api_assignments.py
T
AdamThomasandClaude Opus 5.5 d722a81a87
ci-cd / build-backend (push) Successful in 31s
ci-cd / build-frontend (push) Successful in 19s
ci-cd / deploy (push) Successful in 12s
Retrait des disponibilités et des limites de temps dans la journée
Disponibilités déclarées supprimées (table `availability`, migration 0022,
API, éditeur de la fiche bénévole, badge de couverture du panneau
d'affectation, colonnes des statistiques) ainsi que les règles
OUTSIDE_AVAILABILITY, DAILY_HOURS_EXCEEDED et INSUFFICIENT_REST, les malus
de disponibilité et de repos du solveur et le filtre « Surchargés » de la
vue bénévoles. Seul le chevauchement reste contrôlé. La case « je suis
disponible » du formulaire public est conservée.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:29:58 +02:00

146 lines
4.9 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.
import datetime as dt
from tests.factories import (
dt_at,
make_position,
make_shift,
make_volunteer,
)
def _url(edition, suffix=""):
return f"/editions/{edition.id}/assignments{suffix}"
def _setup(session, edition):
position = make_position(session, edition)
shift = make_shift(
session, edition, position, start=dt_at(10, 14), end=dt_at(10, 18)
)
volunteer = make_volunteer(session, edition, email="v@ex.fr")
return volunteer, shift
def test_create_assignment_clean(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
resp = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
)
assert resp.status_code == 201
body = resp.json()
assert body["warnings"] == []
assert body["assignment"]["source"] == "MANUAL"
assert body["assignment"]["locked"] is False
def test_long_day_without_rest_raises_no_warning(client, edition, session, day_parts):
# Plus de limite d'heures par jour ni de repos minimal : 14h–18h puis
# 18h–04h (14 h d'affilée) passe sans avertissement.
volunteer, shift = _setup(session, edition)
position = make_position(session, edition, name="Bar")
following = make_shift(
session, edition, position, start=dt_at(10, 18), end=dt_at(11, 4)
)
for s in (shift, following):
resp = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(s.id)},
)
assert resp.status_code == 201
assert resp.json()["warnings"] == []
def test_create_assignment_blocked_by_overlap(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
assert client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
).status_code == 201
position = make_position(session, edition, name="Parking")
overlapping = make_shift(
session, edition, position, start=dt_at(10, 16), end=dt_at(10, 20)
)
resp = client.post(
_url(edition),
json={
"volunteer_id": str(volunteer.id),
"shift_id": str(overlapping.id),
},
)
assert resp.status_code == 422
detail = resp.json()["detail"]
assert detail["code"] == "error.validation_failed"
assert any(v["code"] == "SHIFT_OVERLAP" for v in detail["violations"])
# Rien n'a été enregistré pour ce créneau.
listed = client.get(
_url(edition), params={"shift_id": str(overlapping.id)}
).json()
assert listed == []
def test_create_duplicate_assignment_conflicts(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
body = {"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)}
assert client.post(_url(edition), json=body).status_code == 201
resp = client.post(_url(edition), json=body)
assert resp.status_code == 409
assert resp.json()["detail"]["code"] == "assignment.duplicate"
def test_assignment_wrong_edition_is_422(client, edition, session, day_parts):
from app.models import Edition
other = Edition(
year=2027, start_date=dt.date(2027, 7, 1), end_date=dt.date(2027, 7, 4)
)
session.add(other)
session.commit()
session.refresh(other)
stranger = make_volunteer(session, other, email="s@ex.fr")
_, shift = _setup(session, edition)
resp = client.post(
_url(edition),
json={"volunteer_id": str(stranger.id), "shift_id": str(shift.id)},
)
assert resp.status_code == 422
assert resp.json()["detail"]["code"] == "assignment.wrong_edition"
def test_validate_endpoint_does_not_persist(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
resp = client.post(
_url(edition, "/validate"),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
)
assert resp.status_code == 200
body = resp.json()
assert body["blocking"] is False
assert body["violations"] == []
assert client.get(_url(edition)).json() == []
def test_patch_locked_keeps_assignment(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
aid = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
).json()["assignment"]["id"]
resp = client.patch(_url(edition, f"/{aid}"), json={"locked": True})
assert resp.status_code == 200
assert resp.json()["assignment"]["locked"] is True
assert resp.json()["warnings"] == []
def test_delete_assignment(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
aid = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
).json()["assignment"]["id"]
assert client.delete(_url(edition, f"/{aid}")).status_code == 204
assert client.get(_url(edition, f"/{aid}")).status_code == 404