Files
benevoles/backend/tests/test_seed.py
T
AdamThomasandClaude Sonnet 5 096b7cd26a
ci-cd / build-backend (push) Successful in 1m12s
ci-cd / build-frontend (push) Successful in 18s
ci-cd / deploy (push) Successful in 12s
Lien d'inscription protégé par jeton, reçus fiscaux mécénat, infobulles et revue de sécurité
- Lien d'inscription protégé par un jeton (FormTemplate.access_token,
  /inscription/<token>), avec régénération depuis l'écran de configuration.
- Reçus fiscaux mécénat (cerfa 11580*05) : un PDF par bénévole ayant payé en
  mécénat, donateur/montant (chiffres et toutes lettres en français,
  app/mecenat/number_words.py)/date complétés par-dessus le modèle officiel.
- Jeu de démonstration : bénévoles avec cotisation classique ou mécénat payée.
- Infobulles (HelpTip et détail de cellule de la grille des besoins)
  repositionnées en position: fixed via JS, bornées à l'écran.
- Revue de sécurité : logo des emails en pièce jointe inline au lieu d'une
  URL (fuyait le jeton d'inscription), sujet retiré du log de remise des
  emails (pouvait porter un nom de bénévole), photo du formulaire public
  revalidée par décodage réel avant stockage, export Excel protégé contre
  l'injection de formule, sondage du statut de paiement limité en
  fréquence, pyjwt mis à jour.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 07:47:17 +02:00

73 lines
2.8 KiB
Python

from sqlmodel import select
from app.models import Edition, FeePaymentStatus, Volunteer
from app.seed import DEMO_EDITION_NAME, build
def test_build_creates_a_realistic_dataset(session):
summary = build(session)
assert summary.volunteers == 120
assert summary.positions == 15
assert summary.shifts > 40
assert summary.assignments > 100
assert summary.understaffed_shifts >= 3 # « quelques trous d'effectif »
assert summary.blocking == 0 # aucune violation bloquante
# Au moins deux règles d'avertissement représentées, quelques alertes.
assert len(summary.warnings) >= 2
assert sum(summary.warnings.values()) >= 3
# Programmation et vœux des bénévoles : le mode démo doit les illustrer.
assert summary.artists > 0
assert summary.position_wishes > 0
assert summary.artist_wishes > 0
assert summary.companion_wishes > 0
# Paiement de la cotisation : au moins un exemple de chaque chemin.
assert summary.fee_paid_classique > 0
assert summary.fee_paid_mecenat > 0
edition = session.exec(
select(Edition).where(Edition.name == DEMO_EDITION_NAME)
).one()
volunteers = session.exec(
select(Volunteer).where(Volunteer.edition_id == edition.id)
).all()
assert len(volunteers) == 120
paid = [v for v in volunteers if v.fee_payment_status == FeePaymentStatus.PAID]
assert len(paid) == summary.fee_paid_classique + summary.fee_paid_mecenat
mecenat = [v for v in paid if v.mecenat_address is not None]
assert len(mecenat) == summary.fee_paid_mecenat
for volunteer in mecenat:
assert volunteer.mecenat_city and volunteer.mecenat_postal_code
assert volunteer.mecenat_country == "France"
assert volunteer.fee_payment_label == "Mécénat"
classique = [v for v in paid if v.mecenat_address is None]
for volunteer in classique:
assert volunteer.fee_payment_label == "Cotisation classique"
assert volunteer.fee_amount == 15.0
def test_build_is_deterministic_and_idempotent(session):
first = build(session)
second = build(session)
assert (second.volunteers, second.positions, second.shifts) == (
first.volunteers,
first.positions,
first.shifts,
)
assert second.assignments == first.assignments
assert second.understaffed_shifts == first.understaffed_shifts
assert dict(second.warnings) == dict(first.warnings)
assert second.artists == first.artists
assert second.position_wishes == first.position_wishes
assert second.artist_wishes == first.artist_wishes
assert second.companion_wishes == first.companion_wishes
assert second.fee_paid_classique == first.fee_paid_classique
assert second.fee_paid_mecenat == first.fee_paid_mecenat
editions = session.exec(
select(Edition).where(Edition.name == DEMO_EDITION_NAME)
).all()
assert len(editions) == 1