groupe-meditation/backend/tests/test_business_rules.py

50 lines
1.9 KiB
Python

import unittest
import sys
from pathlib import Path
from types import SimpleNamespace
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from app.core.decision_types import type_decision_depuis_proposition
from app.core.financial_position import PositionTresorerie
from app.core.sanitization import safe_query_params
class DecisionTypeTests(unittest.TestCase):
def test_resolution_prefix(self):
prop = SimpleNamespace(numero_resolution="RES-2026-001", candidature_id=None)
self.assertEqual(type_decision_depuis_proposition(prop), "resolution")
def test_nomination_from_candidature(self):
prop = SimpleNamespace(numero_resolution=None, candidature_id="candidate-id")
self.assertEqual(type_decision_depuis_proposition(prop), "nomination")
def test_contribution_prefix(self):
prop = SimpleNamespace(numero_resolution="DON-2026-001", candidature_id=None)
self.assertEqual(type_decision_depuis_proposition(prop), "contribution")
def test_plain_proposition_without_decision_marker(self):
prop = SimpleNamespace(numero_resolution=None, candidature_id=None)
self.assertEqual(type_decision_depuis_proposition(prop), "proposition")
class PositionTresorerieTests(unittest.TestCase):
def test_available_bank_excludes_reserves_and_commitments(self):
position = PositionTresorerie(
solde_banque=100.0,
encaisse=25.0,
total_reserves=40.0,
engagements_non_debites=15.0,
)
self.assertEqual(position.disponible_bancaire, 45.0)
self.assertEqual(position.disponible_total, 70.0)
class AuditTests(unittest.TestCase):
def test_sensitive_query_params_are_masked(self):
request = SimpleNamespace(query_params={"pin": "1234", "membre_id": "abc"})
self.assertEqual(safe_query_params(request.query_params), {"pin": "***", "membre_id": "abc"})
if __name__ == "__main__":
unittest.main()