284 lines
15 KiB
Python
284 lines
15 KiB
Python
from typing import Callable, List, Optional, Tuple, Union
|
|
from unittest import mock
|
|
|
|
from django.test import TestCase
|
|
|
|
from ...models import Administre
|
|
from ...models import AvisPosteChoices as AvisPoste
|
|
from ...models import CustomUser, Decision, DecisionChoices, Poste, SousVivier
|
|
from ...models import StatutPamChoices as StatutPam
|
|
from ...utils.decisions import (DECISIONS, KEY_CHOICES, KEY_CREATE,
|
|
KEY_PROFILES, KEY_UPDATE, ExtraDecisions,
|
|
get_all_decisions, get_available_decisions)
|
|
from ...utils.permissions import (KEY_READ, KEY_WRITE, Profiles,
|
|
get_profiles_by_adm)
|
|
|
|
|
|
class DecisionsTest(TestCase):
|
|
|
|
def setUp(self):
|
|
""" vérifie qu'il n'existe aucun administré ou poste avant le test """
|
|
|
|
self.assertEqual(Administre.objects.exists(), False, "pas d'administré avant un test")
|
|
self.assertEqual(Poste.objects.exists(), False, "pas de poste avant un test")
|
|
|
|
def tearDown(self):
|
|
""" supprime tous les administrés, les postes, les décisions en fin de test """
|
|
|
|
Decision.objects.all().delete()
|
|
Poste.objects.all().delete()
|
|
Administre.objects.all().delete()
|
|
|
|
def __load_administres(self) -> List[Administre]:
|
|
""" charge les administrés de la base à partir des IDs """
|
|
|
|
self.assertTrue(self.adm_ids, "il est nécessaire de renseigner des IDs d'administrés pour le chargement")
|
|
return list(Administre.objects.filter(pk__in=self.adm_ids or ()))
|
|
|
|
def __setup_decisions(self, decision: Optional[Union[DecisionChoices, ExtraDecisions]]) -> None:
|
|
""" supprime et recrée (si nécessaire) les postes et les décisions des administrés """
|
|
|
|
Decision.objects.all().delete()
|
|
Poste.objects.all().delete()
|
|
if decision and decision != ExtraDecisions.EMPTY:
|
|
for adm_id in self.adm_ids:
|
|
poste = Poste.objects.create(pk=str(adm_id), p_avis=AvisPoste.P1)
|
|
Decision.objects.create(administre_id=adm_id, poste=poste, de_decision=decision)
|
|
|
|
def __do_for_profiles(self, action: Callable[[Profiles], None], profiles: Tuple[Profiles], decisions: Tuple[Union[DecisionChoices, ExtraDecisions]] = ()) -> None:
|
|
"""
|
|
exécute une action (un test) avec un sous-test :
|
|
- soit pour chaque profil (utilise un mock)
|
|
- soit pour chaque profil et chaque statut de décision (utilise un mock)
|
|
implicite : self.adm_ids
|
|
"""
|
|
|
|
def run_subTest(profile: Profiles, decision: Optional[Union[DecisionChoices, ExtraDecisions]] = None) -> None:
|
|
with self.subTest(profile=profile.name, **({'decision': decision.name} if decision else {})):
|
|
@mock.patch(
|
|
f'{get_available_decisions.__module__}.{get_profiles_by_adm.__name__}',
|
|
return_value={adm_id: {KEY_READ: (), KEY_WRITE: (profile,)} for adm_id in self.adm_ids}
|
|
)
|
|
def do_with_profile(mock):
|
|
action(profile, decision)
|
|
do_with_profile()
|
|
|
|
for p in profiles:
|
|
if decisions:
|
|
for decision in decisions:
|
|
self.__setup_decisions(decision)
|
|
run_subTest(p, decision)
|
|
else:
|
|
run_subTest(p)
|
|
|
|
def __assert_common(self, decisions_by_adm):
|
|
"""
|
|
assertions communes à propos des décisions renvoyées pour les administrés
|
|
implicite : self.adm_ids
|
|
"""
|
|
|
|
self.assertIsInstance(decisions_by_adm, dict, "le résultat n'est jamais None")
|
|
for adm_id in self.adm_ids:
|
|
self.assertTrue(adm_id in decisions_by_adm, "tous les administrés doivent être présents dans le résultat")
|
|
|
|
decisions = decisions_by_adm.get(adm_id)
|
|
self.assertIsInstance(decisions, dict, "le format des décisions est un dictionnaire")
|
|
for key in (KEY_CREATE, KEY_UPDATE):
|
|
self.assertTrue(key in decisions, f"les décisions doivent contenir la clé {key}")
|
|
self.assertIsInstance(decisions.get(key), tuple, f"la valeur de {key} des décisions n'a pas le type attendu")
|
|
|
|
def test_tree_attribute(self):
|
|
""" vérifie que le comportement reste correct avec l'ajout de nouveaux attributs """
|
|
|
|
attr_trees = 'trees'
|
|
for choice in DecisionChoices:
|
|
self.assertIsInstance(choice.label, str, f"{choice} : le libellé n'a pas le bon type")
|
|
self.assertIsInstance(choice.value, str, f"{choice} : la valeur n'a pas le bon type")
|
|
self.assertEqual(choice.value, choice, f"{choice} : n'est pas égal à sa valeur")
|
|
self.assertIsInstance(getattr(choice, attr_trees), tuple, f"{choice} : l'attribut {attr_trees} n'a pas le bon type")
|
|
|
|
def test_champ_decisions(self):
|
|
""" vérifie la structure de DECISIONS """
|
|
|
|
to_test = DECISIONS
|
|
|
|
self.assertIsInstance(to_test, dict, "la structure n'a pas le type attendu")
|
|
self.assertTrue(to_test, "la structure ne doit pas être vide")
|
|
|
|
for key, value in to_test.items():
|
|
self.assertTrue(key is None or isinstance(key, DecisionChoices), f"la décision {key} n'a pas le type attendu")
|
|
self.assertIsInstance(value, dict, f"la valeur pour la décision {key} n'a pas le type attendu")
|
|
|
|
profiles = value.get(KEY_PROFILES)
|
|
self.assertTrue(profiles is None or isinstance(profiles, tuple), f"la valeur de {KEY_PROFILES} de la valeur pour la décision {key} n'a pas le type attendu")
|
|
for p in profiles:
|
|
self.assertIsInstance(p, Profiles, f"un élément de la clé {KEY_PROFILES} de la valeur pour la décision {key} n'a pas le type attendu")
|
|
|
|
choices = value.get(KEY_CHOICES)
|
|
self.assertTrue(choices is None or isinstance(choices, tuple), f"la valeur de {KEY_CHOICES} de la valeur pour la décision {key} n'a pas le type attendu")
|
|
for c in choices:
|
|
self.assertIsInstance(c, (DecisionChoices, ExtraDecisions), f"un élément de la clé {KEY_CHOICES} de la valeur pour la décision {key} n'a pas le type attendu")
|
|
|
|
def test_get_all_decisions(self):
|
|
""" vérifie les valeurs de get_all_decisions """
|
|
|
|
to_test = get_all_decisions()
|
|
|
|
self.assertIsInstance(to_test, tuple, "le résultat n'a pas le type attendu")
|
|
self.assertTrue(to_test, "le résultat ne doit pas être vide")
|
|
|
|
for value in to_test:
|
|
self.assertIsInstance(value, DecisionChoices, f"la valeur {value} n'a pas le type attendu")
|
|
|
|
def test_pam_wihout_choice(self):
|
|
""" pour ces statuts PAM il n'y a aucun choix """
|
|
|
|
user = CustomUser()
|
|
self.adm_ids = tuple(a.a_id_sap for a in (
|
|
Administre.objects.create(pk=i + 1, a_statut_pam=status) for i, status in enumerate(StatutPam) if not status.dec_enabled
|
|
))
|
|
|
|
def action(_p, _d):
|
|
decisions_by_adm = get_available_decisions(self.__load_administres(), user=user)
|
|
|
|
self.__assert_common(decisions_by_adm)
|
|
for adm_id in self.adm_ids:
|
|
decisions = decisions_by_adm.get(adm_id)
|
|
self.assertFalse(decisions.get(KEY_CREATE))
|
|
self.assertFalse(decisions.get(KEY_UPDATE))
|
|
|
|
self.__do_for_profiles(action, profiles=tuple(Profiles))
|
|
|
|
def test_pam_with_choices(self):
|
|
""" pour ces statuts PAM c'est l'arbre de décision qui est utilisé """
|
|
|
|
user = CustomUser()
|
|
self.adm_ids = tuple(a.a_id_sap for a in (
|
|
Administre.objects.create(pk=i + 1, a_statut_pam=status) for i, status in enumerate(StatutPam) if status.dec_enabled
|
|
))
|
|
D = DecisionChoices
|
|
EX = ExtraDecisions
|
|
|
|
def action(p, d):
|
|
decisions_by_adm = get_available_decisions(self.__load_administres(), user=user)
|
|
|
|
self.__assert_common(decisions_by_adm)
|
|
for adm_id in self.adm_ids:
|
|
decisions = decisions_by_adm.get(adm_id)
|
|
|
|
# create
|
|
decisions_create = decisions.get(KEY_CREATE)
|
|
if p == Profiles.FILIERE:
|
|
self.assertCountEqual(decisions_create, (D.PROPOSITION_FE, D.HME_PROPOSITION_VIVIER))
|
|
else:
|
|
self.assertFalse(decisions_create)
|
|
|
|
# update
|
|
decisions_update = decisions.get(KEY_UPDATE)
|
|
if not d and p == Profiles.FILIERE:
|
|
self.assertCountEqual(decisions_update, (D.PROPOSITION_FE, D.HME_PROPOSITION_VIVIER))
|
|
|
|
elif d == D.PROPOSITION_FE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.DIALOGUE_EN_COURS, D.FOREMP_EN_COURS))
|
|
|
|
elif d == D.DIALOGUE_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.DIALOGUE_TERMINE, D.DIALOGUE_INFRUCTUEUX))
|
|
|
|
elif d == D.DIALOGUE_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.FOREMP_EN_COURS,))
|
|
|
|
elif d == D.DIALOGUE_INFRUCTUEUX and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.FOREMP_EN_COURS, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.FOREMP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.FOREMP_TERMINE,))
|
|
|
|
elif d == D.FOREMP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
|
self.assertCountEqual(decisions_update, (D.PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.PREPOSITIONNE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.POSITIONNE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.POSITIONNE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.OMIP_EN_COURS, D.OMI_EN_COURS, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.OMIP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.OMIP_TERMINE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.OMIP_TERMINE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.ATTENTE_AVIONAGE, D.OMI_EN_COURS, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.ATTENTE_AVIONAGE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.OMI_EN_COURS,))
|
|
|
|
elif d == D.OMI_EN_COURS and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.OMI_ACTIVE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.OMI_ACTIVE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.OMI_ANNULE,))
|
|
|
|
elif d == D.OMI_ANNULE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.REMIS_A_DISPOSITION,))
|
|
|
|
elif d == D.REMIS_A_DISPOSITION and p == Profiles.FILIERE:
|
|
self.assertCountEqual(decisions_update, (EX.EMPTY,))
|
|
|
|
elif d == D.HME_PROPOSITION_VIVIER and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_INITIE,))
|
|
|
|
elif d == D.HME_ETUDE_DESISTEMENT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_DESISTEMENT,))
|
|
|
|
elif d == D.HME_DESISTEMENT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.REMIS_A_DISPOSITION,))
|
|
|
|
elif d == D.HME_DIALOGUE_INITIE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_EN_COURS,))
|
|
|
|
elif d == D.HME_DIALOGUE_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_TERMINE, D.HME_DIALOGUE_INFRUCTUEUX))
|
|
|
|
elif d == D.HME_DIALOGUE_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_PREPOSITIONNE,))
|
|
|
|
elif d == D.HME_DIALOGUE_INFRUCTUEUX and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_ETUDE_DESISTEMENT, D.HME_PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.HME_FOREMP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_FOREMP_TERMINE, D.HME_OMI_EN_COURS))
|
|
|
|
elif d == D.HME_FOREMP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_OMIP_EN_COURS, D.HME_OMI_EN_COURS))
|
|
|
|
elif d == D.HME_PREPOSITIONNE and p == Profiles.HME:
|
|
self.assertCountEqual(decisions_update, (D.HME_VALIDATION_EXPERT, D.HME_REFUS_EXPERT))
|
|
|
|
elif d == D.HME_POSITIONNE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_OMIP_EN_COURS, D.HME_OMI_EN_COURS, D.HME_FOREMP_EN_COURS))
|
|
|
|
elif d == D.HME_VALIDATION_EXPERT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_POSITIONNE,))
|
|
|
|
elif d == D.HME_REFUS_EXPERT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
|
|
|
elif d == D.HME_OMIP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_OMIP_TERMINE,))
|
|
|
|
elif d == D.HME_OMIP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_ATTENTE_AVIONAGE, D.HME_OMI_EN_COURS))
|
|
|
|
elif d == D.HME_ATTENTE_AVIONAGE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_OMI_EN_COURS,))
|
|
|
|
elif d == D.HME_OMI_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, (D.HME_OMI_ACTIVE,))
|
|
|
|
elif d == D.HME_OMI_ACTIVE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
|
self.assertCountEqual(decisions_update, ())
|
|
|
|
else:
|
|
self.assertFalse(decisions_update)
|
|
|
|
self.__do_for_profiles(action, profiles=tuple(Profiles), decisions=(EX.EMPTY, *get_all_decisions()))
|