init
This commit is contained in:
5
backend-django/backend/tests/__init__.py
Normal file
5
backend-django/backend/tests/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from .initial import *
|
||||
from .models import *
|
||||
from .utils import *
|
||||
from .views import *
|
||||
from .droits import *
|
||||
1
backend-django/backend/tests/droits/__init__.py
Normal file
1
backend-django/backend/tests/droits/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .socle import *
|
||||
590
backend-django/backend/tests/droits/socle.py
Normal file
590
backend-django/backend/tests/droits/socle.py
Normal file
@@ -0,0 +1,590 @@
|
||||
from django.urls import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient, APITestCase
|
||||
|
||||
from ...models import (Administre, CustomUser, Decision, DecisionChoices,
|
||||
Domaine, Filiere, FormationEmploi, Garnison, Poste,
|
||||
RefGest, RefOrg, RefSvFil, SousVivier)
|
||||
|
||||
|
||||
class TestSocleVerifDroits(APITestCase):
|
||||
""" Classe permettant de tester la vérification des droits de lecture et d'écriture d'un gestionnaire """
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
# Création des gestionnaires
|
||||
cls.gest1 = CustomUser.objects.create(username='gest1', password='password', id=1)
|
||||
cls.gest2 = CustomUser.objects.create(username='gest2', password='password', id=2)
|
||||
cls.gest3 = CustomUser.objects.create(username='gest3', password='password', id=3)
|
||||
cls.gest4 = CustomUser.objects.create(username='gest4', password='password', id=4)
|
||||
cls.gest5 = CustomUser.objects.create(username='gest5', password='password', id=5)
|
||||
cls.gest6 = CustomUser.objects.create(username='gest6', password='password', id=6)
|
||||
cls.gest7 = CustomUser.objects.create(username='gest7', password='password', id=7)
|
||||
cls.gest8 = CustomUser.objects.create(username='gest8', password='password', id=8)
|
||||
cls.gest9 = CustomUser.objects.create(username='gest9', password='password', id=9)
|
||||
cls.gest10 = CustomUser.objects.create(username='gest10', password='password', id=10)
|
||||
|
||||
|
||||
# Création des objets du référentiel organique
|
||||
cls.ref_org30 = RefOrg.objects.create(
|
||||
ref_org_code='org30',
|
||||
ref_org_code_niv_org3='org30',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_itd=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
) # Référentiel organique avec les droits de lecture et d'écriture (attribué aux gestionnaires 1)
|
||||
|
||||
cls.ref_org40a = RefOrg.objects.create(
|
||||
ref_org_code='org40a',
|
||||
ref_org_code_niv_org3='org30',
|
||||
ref_org_code_niv_org4='org40a',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_itd=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org40b = RefOrg.objects.create(
|
||||
ref_org_code='org40b',
|
||||
ref_org_code_niv_org3='org30',
|
||||
ref_org_code_niv_org4='org40b',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_itd=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org41 = RefOrg.objects.create(
|
||||
ref_org_code='org41',
|
||||
ref_org_code_niv_org4='org41',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True
|
||||
) # Référentiel organique sans les droits de lecture et d'écriture (attribué aux gestionnaires 3)
|
||||
|
||||
cls.ref_org42 = RefOrg.objects.create(
|
||||
ref_org_code='org42',
|
||||
ref_org_code_niv_org4='org42',
|
||||
ref_org_droit_lect=True
|
||||
) # Référentiel organique avec les droits de lecture mais ni pcp ni fil ni itd (attribué aux gestionnaires 4)
|
||||
|
||||
cls.ref_org43 = RefOrg.objects.create(
|
||||
ref_org_code='org43',
|
||||
ref_org_code_niv_org4='org43',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org44 = RefOrg.objects.create(
|
||||
ref_org_code='org44',
|
||||
ref_org_code_niv_org4='org44',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True
|
||||
) # Référentiel organique sans les droits d'écriture (attribué aux gestionnaires 6)
|
||||
|
||||
cls.ref_org45 = RefOrg.objects.create(
|
||||
ref_org_code='org45',
|
||||
ref_org_code_niv_org4='org45',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
) # Référentiel organique sans FE ni FIL (attribué aux gestionnaires 7)
|
||||
|
||||
cls.ref_org36 = RefOrg.objects.create(
|
||||
ref_org_code='org36',
|
||||
ref_org_code_niv_org3='org36',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
) # Référentiel organique ne possedant aucune instances dans les ref FE et FIL (attribué aux gestionnaires 8)
|
||||
|
||||
cls.ref_org37 = RefOrg.objects.create(
|
||||
ref_org_code='org37',
|
||||
ref_org_code_niv_org3='org37',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org47a = RefOrg.objects.create(
|
||||
ref_org_code='org47a',
|
||||
ref_org_code_niv_org3='org37',
|
||||
ref_org_code_niv_org4='org47a',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org47b = RefOrg.objects.create(
|
||||
ref_org_code='org47b',
|
||||
ref_org_code_niv_org3='org37',
|
||||
ref_org_code_niv_org4='org47b',
|
||||
ref_org_ref_fe=True,
|
||||
ref_org_ref_sv_fil=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
)
|
||||
|
||||
cls.ref_org48 = RefOrg.objects.create(
|
||||
ref_org_code='org48',
|
||||
ref_org_code_niv_org4='org48',
|
||||
ref_org_itd=True,
|
||||
ref_org_droit_lect=True,
|
||||
ref_org_droit_ecr=True
|
||||
) # Référentiel organique avec tous les droits mais seulement pour un gestionnaire ITD (attribué au gestionnaire 10)
|
||||
|
||||
|
||||
# Création des objets du référentiel gestionnaire
|
||||
cls.ref_gest1 = RefGest.objects.create(ref_gest_sap=cls.gest1.id, ref_gest_org=cls.ref_org30)
|
||||
cls.ref_gest2 = RefGest.objects.create(ref_gest_sap=cls.gest2.id) # Gestionnaire ne possedant pas de cod_niv_org
|
||||
cls.ref_gest3 = RefGest.objects.create(ref_gest_sap=cls.gest3.id, ref_gest_org=cls.ref_org41)
|
||||
cls.ref_gest4 = RefGest.objects.create(ref_gest_sap=cls.gest4.id, ref_gest_org=cls.ref_org42)
|
||||
cls.ref_gest5 = RefGest.objects.create(ref_gest_sap=cls.gest5.id, ref_gest_org=cls.ref_org43)
|
||||
cls.ref_gest6 = RefGest.objects.create(ref_gest_sap=cls.gest6.id, ref_gest_org=cls.ref_org44)
|
||||
cls.ref_gest7 = RefGest.objects.create(ref_gest_sap=cls.gest7.id, ref_gest_org=cls.ref_org45)
|
||||
cls.ref_gest8 = RefGest.objects.create(ref_gest_sap=cls.gest8.id, ref_gest_org=cls.ref_org36)
|
||||
cls.ref_gest9 = RefGest.objects.create(ref_gest_sap=cls.gest9.id, ref_gest_org=cls.ref_org37)
|
||||
cls.ref_gest10 = RefGest.objects.create(ref_gest_sap=cls.gest10.id, ref_gest_org=cls.ref_org48)
|
||||
|
||||
# Création du référentiel FE et des DOM/FIL
|
||||
cls.gar1 = Garnison.objects.create(gar_id='Gar1', gar_lieu='lieu1')
|
||||
cls.fe1 = FormationEmploi.objects.create(fe_code='Fe1', fe_code_niv_org4='org40a', fe_garnison_lieu=cls.gar1.gar_lieu)
|
||||
cls.fe2 = FormationEmploi.objects.create(fe_code='Fe2', fe_code_niv_org4='org43', fe_garnison_lieu=cls.gar1.gar_lieu)
|
||||
cls.fe3 = FormationEmploi.objects.create(fe_code='Fe3', fe_code_niv_org4='org47a', fe_garnison_lieu=cls.gar1.gar_lieu)
|
||||
|
||||
cls.dom1 = Domaine.objects.create(d_code='Dom1')
|
||||
cls.fil1 = Filiere.objects.create(f_code='Fil1')
|
||||
|
||||
|
||||
# Création des administrés, postes et décisions
|
||||
cls.adm1 = Administre.objects.create(a_id_sap=1, formation_emploi=cls.fe1, a_domaine=cls.dom1, a_filiere=cls.fil1, a_categorie='Cat1', a_nom='nom', a_prenom='prénom', a_sexe='M', a_eip='eip1') # Administré du fe1
|
||||
cls.adm2 = Administre.objects.create(a_id_sap=2, formation_emploi=cls.fe1, a_domaine=cls.dom1, a_filiere=cls.fil1, a_categorie='Cat1', a_nom='nom', a_prenom='prénom', a_sexe='M', a_eip='eip2') # Idem
|
||||
cls.adm3 = Administre.objects.create(a_id_sap=3, formation_emploi=cls.fe2, a_domaine=cls.dom1, a_filiere=cls.fil1, a_categorie='Cat1', a_nom='nom', a_prenom='prénom', a_sexe='M', a_eip='eip3') # Administré du fe2
|
||||
cls.adm4 = Administre.objects.create(a_id_sap=4, formation_emploi=cls.fe2, a_domaine=cls.dom1, a_filiere=cls.fil1, a_categorie='Cat1', a_nom='nom', a_prenom='prénom', a_sexe='M', a_eip='eip4') # Idem
|
||||
|
||||
cls.poste1 = Poste.objects.create(p_id='Poste1', formation_emploi=cls.fe1, p_domaine=cls.dom1, p_filiere=cls.fil1, p_categorie='Cat1', p_eip='eip1')
|
||||
cls.poste2 = Poste.objects.create(p_id='Poste2', formation_emploi=cls.fe1, p_domaine=cls.dom1, p_filiere=cls.fil1, p_categorie='Cat1', p_eip='eip2')
|
||||
cls.poste3 = Poste.objects.create(p_id='Poste3', formation_emploi=cls.fe2, p_domaine=cls.dom1, p_filiere=cls.fil1, p_categorie='Cat1', p_eip='eip3')
|
||||
cls.poste4 = Poste.objects.create(p_id='Poste4', formation_emploi=cls.fe2, p_domaine=cls.dom1, p_filiere=cls.fil1, p_categorie='Cat1', p_eip='eip4')
|
||||
cls.poste5 = Poste.objects.create(p_id='Poste5', p_specifique='ITD', p_eip='eip5')
|
||||
|
||||
cls.dec1 = Decision.objects.create(administre=cls.adm1, poste=cls.poste1, de_decision=DecisionChoices.PROPOSITION_FE)
|
||||
cls.dec2 = Decision.objects.create(administre=cls.adm3, poste=cls.poste3, de_decision=DecisionChoices.PROPOSITION_FE)
|
||||
|
||||
# Création du référentiel sous-vivier filiere
|
||||
cls.ref_sv_fil1 = RefSvFil.objects.create(ref_sv_fil_code='org40b', ref_sv_fil_dom='Dom1', ref_sv_fil_fil='Fil1', ref_sv_fil_cat='Cat1')
|
||||
|
||||
|
||||
# Création des clients de test
|
||||
cls.c0 = APIClient() # Client de test qui ne sera pas authentifié
|
||||
cls.c1 = APIClient()
|
||||
cls.c2 = APIClient()
|
||||
cls.c3 = APIClient()
|
||||
cls.c4 = APIClient()
|
||||
cls.c5 = APIClient()
|
||||
cls.c6 = APIClient()
|
||||
cls.c7 = APIClient()
|
||||
cls.c8 = APIClient()
|
||||
cls.c9 = APIClient()
|
||||
cls.c10 = APIClient()
|
||||
|
||||
# Authentification des clients de test
|
||||
cls.c1.force_authenticate(cls.gest1)
|
||||
cls.c2.force_authenticate(cls.gest2)
|
||||
cls.c3.force_authenticate(cls.gest3)
|
||||
cls.c4.force_authenticate(cls.gest4)
|
||||
cls.c5.force_authenticate(cls.gest5)
|
||||
cls.c6.force_authenticate(cls.gest6)
|
||||
cls.c7.force_authenticate(cls.gest7)
|
||||
cls.c8.force_authenticate(cls.gest8)
|
||||
cls.c9.force_authenticate(cls.gest9)
|
||||
cls.c10.force_authenticate(cls.gest10)
|
||||
|
||||
cls.list_clients = [cls.c1, cls.c2, cls.c3, cls.c4, cls.c5, cls.c6, cls.c7, cls.c8, cls.c9, cls.c10]
|
||||
|
||||
# Création des données utilsées pour les requêtes
|
||||
cls.patch_datas = {
|
||||
'data_p1': {
|
||||
'p_id': 'Poste1',
|
||||
'p_eip': 'eip2'
|
||||
},
|
||||
'data_a1': {
|
||||
'a_id_sap': 1,
|
||||
'a_eip': 'eip2'
|
||||
},
|
||||
'data_d1': {
|
||||
'pk': cls.adm1.pk,
|
||||
'de_decision': DecisionChoices.POSITIONNE
|
||||
},
|
||||
'data_p3': {
|
||||
'p_id': 'Poste3',
|
||||
'p_eip': 'eip4'
|
||||
},
|
||||
'data_a3': {
|
||||
'a_id_sap': 3,
|
||||
'a_eip': 'eip4'
|
||||
},
|
||||
'data_d3': {
|
||||
'pk': cls.adm3.pk,
|
||||
'de_decision': DecisionChoices.POSITIONNE
|
||||
},
|
||||
'data_p5': {
|
||||
'p_id': 'Poste5',
|
||||
'p_eip': 'eip6'
|
||||
}
|
||||
}
|
||||
|
||||
cls.put_datas = {
|
||||
'data_p1': [
|
||||
{'p_id': 'Poste1',
|
||||
'p_eip': 'eip2'
|
||||
},
|
||||
{'p_id': 'Poste2',
|
||||
'p_eip': 'eip3'
|
||||
}
|
||||
],
|
||||
'data_a1': [
|
||||
{'a_id_sap': 1,
|
||||
'a_eip': 'eip2'
|
||||
},
|
||||
{'a_id_sap': 2,
|
||||
'a_eip': 'eip3'
|
||||
},
|
||||
],
|
||||
'data_p3': [
|
||||
{'p_id': 'Poste3',
|
||||
'p_eip': 'eip4'
|
||||
},
|
||||
{'p_id': 'Poste4',
|
||||
'p_eip': 'eip5'
|
||||
}
|
||||
],
|
||||
'data_a3': [
|
||||
{'a_id_sap': 3,
|
||||
'a_eip': 'eip4'
|
||||
},
|
||||
{'a_id_sap': 4,
|
||||
'a_eip': 'eip5'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# Définition des liens sur lesquels les requêtes seront effectuées
|
||||
cls.urls = {
|
||||
'list_p': reverse('Poste-list'),
|
||||
'list_a': reverse('Administre-list'),
|
||||
'list_d': reverse('Decision-list'),
|
||||
'instance_p1': reverse('Poste-list') + 'Poste1/',
|
||||
'instance_a1': reverse('Administre-list') + '1/',
|
||||
'instance_d1': reverse('Decision-list') + '1/',
|
||||
'instance_p3': reverse('Poste-list') + 'Poste3/',
|
||||
'instance_a3': reverse('Administre-list') + '3/',
|
||||
'instance_d3': reverse('Decision-list') + '3/',
|
||||
'instance_p5': reverse('Poste-list') + 'Poste5/'
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
for client in cls.list_clients:
|
||||
client.logout()
|
||||
|
||||
|
||||
def test_get_not_authenticated(self):
|
||||
"""
|
||||
Teste la requete GET sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire n'est pas authentifié
|
||||
"""
|
||||
# Le test passe mais il y a également interdiction car c5 n'a pas de 'code_niv_org'...
|
||||
get_resp_p = self.c0.get(path=self.urls['list_p'], follow=True)
|
||||
get_resp_a = self.c0.get(path=self.urls['list_a'], follow=True)
|
||||
get_resp_d = self.c0.get(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(get_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_get_ok(self):
|
||||
"""
|
||||
Teste la requete GET sur les vues PosteView, AdministreView et DecisionView sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture
|
||||
"""
|
||||
get_resp_p = self.c1.get(path=self.urls['list_p'], follow=True)
|
||||
get_resp_a = self.c1.get(path=self.urls['list_a'], follow=True)
|
||||
get_resp_d = self.c1.get(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(get_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(get_resp_a.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(get_resp_d.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_get_no_code_niv_org(self):
|
||||
"""
|
||||
Teste la requete GET sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire n'a pas d'attribut code_niv_org
|
||||
"""
|
||||
get_resp_p = self.c2.get(path=self.urls['list_p'], follow=True)
|
||||
get_resp_a = self.c2.get(path=self.urls['list_a'], follow=True)
|
||||
get_resp_d = self.c2.get(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(get_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_get_no_reading_rights(self):
|
||||
"""
|
||||
Teste la requete GET sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire n'a pas les droits de lecture
|
||||
"""
|
||||
get_resp_p = self.c3.get(path=self.urls['list_p'], follow=True)
|
||||
get_resp_a = self.c3.get(path=self.urls['list_a'], follow=True)
|
||||
get_resp_d = self.c3.get(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(get_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_get_not_pcp_not_fil(self):
|
||||
"""
|
||||
Teste la requete GET sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire est ni pcp ni filiere
|
||||
"""
|
||||
get_resp_p = self.c4.get(path=self.urls['list_p'], follow=True)
|
||||
get_resp_a = self.c4.get(path=self.urls['list_a'], follow=True)
|
||||
get_resp_d = self.c4.get(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(get_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(get_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_put_ok_fe_fil(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture et d'écriture,
|
||||
- Qu'il est PCP et FIL,
|
||||
- Qu'il est associé à deux code_niv_org4,
|
||||
- Les instances qu'il édite sont dans son FE et dans sa filiere
|
||||
"""
|
||||
# Pas de test put pour les décisions car la modification de plusieurs décisions n'est pas possible dans Ogure
|
||||
put_resp_p = self.c1.put(path=self.urls['list_p'], data=self.put_datas['data_p1'], follow=True)
|
||||
put_resp_a = self.c1.put(path=self.urls['list_a'], data=self.put_datas['data_a1'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_put_ok_fe(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture et d'écriture,
|
||||
- Qu'il est PCP et FIL,
|
||||
- Qu'il est associé à un code_niv_org4,
|
||||
- Les instances qu'il édite sont dans son FE MAIS PAS dans sa FIL
|
||||
"""
|
||||
# Pas de test put pour les décisions car la modification de plusieurs décisions n'est pas possible dans Ogure
|
||||
put_resp_p = self.c5.put(path=self.urls['list_p'], data=self.put_datas['data_p3'], follow=True)
|
||||
put_resp_a = self.c5.put(path=self.urls['list_a'], data=self.put_datas['data_a3'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_put_no_writing_rights(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant qu'il n'a pas les droits d'écriture'
|
||||
"""
|
||||
put_resp_p = self.c6.put(path=self.urls['list_p'], data=self.put_datas['data_p1'], follow=True)
|
||||
put_resp_a = self.c6.put(path=self.urls['list_a'], data=self.put_datas['data_a1'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_put_no_fe_no_fil(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant qu'il n'a pas de FE ni de FIL associé'
|
||||
"""
|
||||
put_resp_p = self.c7.put(path=self.urls['list_p'], data=self.put_datas['data_p1'], follow=True)
|
||||
put_resp_a = self.c7.put(path=self.urls['list_a'], data=self.put_datas['data_a1'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_put_no_instances_ok(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant qu'il n'a pas d'instances dans son FE ou dans sa FIL
|
||||
"""
|
||||
put_resp_p = self.c8.put(path=self.urls['list_p'], data=self.put_datas['data_p1'], follow=True)
|
||||
put_resp_a = self.c8.put(path=self.urls['list_a'], data=self.put_datas['data_a1'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_put_not_ok(self):
|
||||
"""
|
||||
Teste la requete PUT sur des postes et des administrés sachant que les instances modifiées ne sont ni dans le FE ni dans la FIL du gestionnaire
|
||||
"""
|
||||
put_resp_p = self.c9.put(path=self.urls['list_p'], data=self.put_datas['data_p1'], follow=True)
|
||||
put_resp_a = self.c9.put(path=self.urls['list_a'], data=self.put_datas['data_a1'], follow=True)
|
||||
self.assertEqual(put_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(put_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_no_code_niv_org(self):
|
||||
"""
|
||||
Teste la requete PATCH sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire n'a pas d'attribut code_niv_org
|
||||
"""
|
||||
patch_resp_p = self.c2.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c2.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c2.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_no_reading_rights(self):
|
||||
"""
|
||||
Teste la requete PATCH sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire n'a pas les droits de lecture
|
||||
"""
|
||||
patch_resp_p = self.c3.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c3.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c3.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_not_pcp_not_fil_not_itd(self):
|
||||
"""
|
||||
Teste la requete PATCH sur les vues PosteView, AdministreView et DecisionView sachant que le gestionnaire est ni pcp ni filiere
|
||||
"""
|
||||
patch_resp_p = self.c4.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c4.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c4.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_ok_fe_fil(self):
|
||||
"""
|
||||
Teste la requete PATCH sur un poste, un administré et une décision sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture et d'écriture,
|
||||
- Qu'il est PCP et FIL,
|
||||
- Qu'il est associé à deux code_niv_org4,
|
||||
- Les instances qu'il édite sont dans son FE et dans sa filiere
|
||||
"""
|
||||
patch_resp_p = self.c1.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c1.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c1.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_patch_ok_fe(self):
|
||||
"""
|
||||
Teste la requete PATCH sur un poste, un administré et une décision sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture et d'écriture,
|
||||
- Qu'il est PCP et FIL,
|
||||
- Qu'il est associé à un code_niv_org4,
|
||||
- Les instances qu'il édite sont dans son FE MAIS PAS dans sa FIL
|
||||
"""
|
||||
patch_resp_p = self.c5.patch(path=self.urls['instance_p3'], data=self.patch_datas['data_p3'], follow=True)
|
||||
patch_resp_a = self.c5.patch(path=self.urls['instance_a3'], data=self.patch_datas['data_a3'], follow=True)
|
||||
patch_resp_d = self.c5.patch(path=self.urls['instance_d3'], data=self.patch_datas['data_d3'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_patch_ok_itd(self):
|
||||
"""
|
||||
Teste la requete PATCH sur un poste sachant que :
|
||||
- Le gestionnaire est authentifié,
|
||||
- Qu'il a les droits de lecture et d'écriture,
|
||||
- Qu'il est ITD,
|
||||
- Qu'il est associé à un code_niv_org4,
|
||||
- Le poste édité est marqué ITD
|
||||
"""
|
||||
patch_resp_p = self.c10.patch(path=self.urls['instance_p5'], data=self.patch_datas['data_p5'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_patch_no_writing_rights(self):
|
||||
"""
|
||||
Teste la requete PATCH sur des postes et des administrés sachant qu'il n'a pas les droits d'écriture'
|
||||
"""
|
||||
patch_resp_p = self.c6.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c6.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c6.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_no_niv_org(self):
|
||||
"""
|
||||
Teste la requete PATCH sur des postes et des administrés sachant qu'il n'a pas d'attribut niv_org'
|
||||
"""
|
||||
patch_resp_p = self.c7.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c7.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c7.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_no_instances_ok(self):
|
||||
"""
|
||||
Teste la requete PATCH sur des postes et des administrés sachant qu'il n'a pas d'instances dans son FE ou dans sa FIL
|
||||
"""
|
||||
patch_resp_p = self.c8.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c8.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c8.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_not_ok_fe_fil(self):
|
||||
"""
|
||||
Teste la requete PATCH sur un poste, un administré et une décision sachant que les instances modifiées ne sont ni dans le FE ni dans la FIL du gestionnaire
|
||||
"""
|
||||
patch_resp_p = self.c9.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
patch_resp_a = self.c9.patch(path=self.urls['instance_a1'], data=self.patch_datas['data_a1'], follow=True)
|
||||
patch_resp_d = self.c9.patch(path=self.urls['instance_d1'], data=self.patch_datas['data_d1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(patch_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_patch_not_ok_itd(self):
|
||||
"""
|
||||
Teste la requete PATCH sur un poste sachant que l'instance modifiée n'est pas marquée ITD
|
||||
"""
|
||||
patch_resp_p = self.c10.patch(path=self.urls['instance_p1'], data=self.patch_datas['data_p1'], follow=True)
|
||||
self.assertEqual(patch_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_delete_ok(self):
|
||||
delete_resp_p = self.c1.delete(path=self.urls['instance_p1'], follow=True)
|
||||
delete_resp_a = self.c1.delete(path=self.urls['instance_a1'], follow=True)
|
||||
self.assertEqual(delete_resp_p.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertEqual(delete_resp_a.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
def test_delete_decision_ok(self):
|
||||
# On teste la suppression de décision séparément des autres suppressions sans quoi instance_d ferait référence à un administré supprimé
|
||||
delete_resp_d = self.c1.delete(path=self.urls['instance_d1'], follow=True)
|
||||
self.assertEqual(delete_resp_d.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
def test_delete_not_ok(self):
|
||||
# delete_resp_p = self.c9.delete(path=self.urls['instance_p1'], follow=True)
|
||||
# delete_resp_a = self.c9.delete(path=self.urls['instance_a1'], follow=True)
|
||||
delete_resp_d = self.c9.delete(path=self.urls['instance_d1'], follow=True)
|
||||
# self.assertEqual(delete_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
# self.assertEqual(delete_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(delete_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_head_ok(self):
|
||||
head_resp_p = self.c1.head(path=self.urls['list_p'], follow=True)
|
||||
head_resp_a = self.c1.head(path=self.urls['list_a'], follow=True)
|
||||
head_resp_d = self.c1.head(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(head_resp_p.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(head_resp_a.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(head_resp_d.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_head_no_reading_rights(self):
|
||||
head_resp_p = self.c3.head(path=self.urls['list_p'], follow=True)
|
||||
head_resp_a = self.c3.head(path=self.urls['list_a'], follow=True)
|
||||
head_resp_d = self.c3.head(path=self.urls['list_d'], follow=True)
|
||||
self.assertEqual(head_resp_p.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(head_resp_a.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(head_resp_d.status_code, status.HTTP_403_FORBIDDEN)
|
||||
140
backend-django/backend/tests/initial.py
Normal file
140
backend-django/backend/tests/initial.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
Ce fichier n'est utilisé que pour les tests.
|
||||
"""
|
||||
# from ..utils_scoring import notations_test
|
||||
# from django.test import TestCase
|
||||
# from numpy import fliplr
|
||||
# from numpy.core.fromnumeric import shape
|
||||
# import pandas as pd
|
||||
# from .utils_scoring import encoding,notePonderee,notations_test
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
# class InsertModelTest(TestCase):
|
||||
# # Fonction pour la table Garnisons
|
||||
# def test_scoring(self):
|
||||
# """Pour tester la fonction de scoring
|
||||
# """
|
||||
# mut_test = notations_test()
|
||||
# data_test = mut_test.to_dict('records')
|
||||
# data_source = [{
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 1,
|
||||
# 'administres_id_sap': 9984,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.5,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''},
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 1,
|
||||
# 'administres_id_sap': 56754,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''},
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 1,
|
||||
# 'administres_id_sap': 78905,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 2,
|
||||
# 'administres_id_sap': 9984,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 2,
|
||||
# 'administres_id_sap': 56754,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.5,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 2,
|
||||
# 'administres_id_sap': 78905,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 3,
|
||||
# 'administres_id_sap': 9984,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 3,
|
||||
# 'administres_id_sap': 56754,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.0,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# },
|
||||
# {
|
||||
# 'mu_id': 0,
|
||||
# 'poste_id': 3,
|
||||
# 'administres_id_sap': 78905,
|
||||
# 'pam_id': 1,
|
||||
# 'mu_date_execution': '14/06/2021',
|
||||
# 'mu_note_militaire': 0.5,
|
||||
# 'mu_flag_cple_ideal': 0,
|
||||
# 'mu_decision': '',
|
||||
# 'mu_date_decision': '',
|
||||
# 'mu_notes_gestionnaire': '',
|
||||
# 'mu_notes_partagees': ''
|
||||
# }]
|
||||
# if data_source == data_test :
|
||||
# test_value = True
|
||||
# else :
|
||||
# test_value = False
|
||||
# self.assertIs(test_value,True)
|
||||
|
||||
3
backend-django/backend/tests/models/__init__.py
Normal file
3
backend-django/backend/tests/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .administre import *
|
||||
from .calcul import *
|
||||
from .poste import *
|
||||
39
backend-django/backend/tests/models/administre.py
Normal file
39
backend-django/backend/tests/models/administre.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from ...models import Administre, StatutPamChoices
|
||||
from django.db.utils import IntegrityError
|
||||
from django.test import TestCase
|
||||
|
||||
class AdministreTestCase(TestCase):
|
||||
|
||||
def test_attributes_statut_pam(self):
|
||||
""" vérifie que le comportement reste correct avec l'ajout de nouveaux attributs """
|
||||
|
||||
attr_calc = 'calc_enabled'
|
||||
attr_dec = 'dec_enabled'
|
||||
for choice in StatutPamChoices:
|
||||
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_calc), bool, f"{choice} : l'attribut {attr_calc} n'a pas le bon type")
|
||||
self.assertIsInstance(getattr(choice, attr_dec), bool, f"{choice} : l'attribut {attr_dec} n'a pas le bon type")
|
||||
|
||||
def test_constraint_statut_pam(self):
|
||||
""" vérifie qu'il n'est pas possible de stocker n'importe quoi en base """
|
||||
|
||||
valides = StatutPamChoices.values
|
||||
invalide = 'autre'
|
||||
|
||||
def given():
|
||||
self.assertTrue(valides, 'il devrait exister des choix valides')
|
||||
self.assertNotIn(invalide, valides, 'le test nécessite une valeur invalide')
|
||||
given()
|
||||
|
||||
id_sap = 1
|
||||
|
||||
# valide : création OK
|
||||
for valide in valides:
|
||||
Administre.objects.create(pk=id_sap, a_statut_pam=valide)
|
||||
id_sap = id_sap + 1
|
||||
|
||||
# invalide : création KO
|
||||
with self.assertRaises(IntegrityError):
|
||||
Administre.objects.create(pk=id_sap, a_statut_pam=invalide)
|
||||
34
backend-django/backend/tests/models/calcul.py
Normal file
34
backend-django/backend/tests/models/calcul.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from django.db.utils import IntegrityError
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from ...models.calcul import Calcul, SousVivier
|
||||
from ...models.calcul import StatutCalculChoices as StatutCalcul
|
||||
|
||||
|
||||
class CalculTestCase(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
for i in range(1, 15):
|
||||
SousVivier.objects.create(pk=str(i))
|
||||
|
||||
def test_constraint_statut(self):
|
||||
valides = StatutCalcul.values
|
||||
invalide = 'autre'
|
||||
|
||||
def given():
|
||||
self.assertTrue(valides, 'il devrait exister des choix valides')
|
||||
self.assertNotIn(invalide, valides, 'le test nécessite une valeur invalide')
|
||||
given()
|
||||
|
||||
i = 1
|
||||
|
||||
# valide : création OK
|
||||
for valide in valides:
|
||||
Calcul.objects.create(pk=str(i), ca_date_debut=timezone.now(), ca_statut=valide, ca_statut_pourcentage=0)
|
||||
i = i + 1
|
||||
|
||||
# invalide : création KO
|
||||
with self.assertRaises(IntegrityError):
|
||||
Calcul.objects.create(pk=str(i), ca_date_debut=timezone.now(), ca_statut=invalide, ca_statut_pourcentage=0)
|
||||
34
backend-django/backend/tests/models/poste.py
Normal file
34
backend-django/backend/tests/models/poste.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from ...models import AvisPosteChoices as AvisPoste, Poste, PropositionsArmementChoices as PropositionsArmement
|
||||
from django.db.utils import IntegrityError
|
||||
from django.test import TestCase
|
||||
|
||||
class PosteTestCase(TestCase):
|
||||
|
||||
def test_attributes_avis(self):
|
||||
""" vérifie que le comportement reste correct avec l'ajout de nouveaux attributs """
|
||||
|
||||
attr_calc = 'calc_enabled'
|
||||
attr_dec = 'dec_enabled'
|
||||
for choice in AvisPoste:
|
||||
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_calc), bool, f"{choice} : l'attribut {attr_calc} n'a pas le bon type")
|
||||
self.assertIsInstance(getattr(choice, attr_dec), bool, f"{choice} : l'attribut {attr_dec} n'a pas le bon type")
|
||||
|
||||
def test_constraint_propositions_armement(self):
|
||||
valides = PropositionsArmement.values
|
||||
invalide = 'autre'
|
||||
|
||||
def given():
|
||||
self.assertTrue(valides, 'il devrait exister des choix valides')
|
||||
self.assertNotIn(invalide, valides, 'le test nécessite une valeur invalide')
|
||||
given()
|
||||
|
||||
# valide : création OK
|
||||
for valide in valides:
|
||||
Poste.objects.create(pk=valide, propositions_armement=valide)
|
||||
|
||||
# invalide : création KO
|
||||
with self.assertRaises(IntegrityError):
|
||||
Poste.objects.create(pk=invalide, propositions_armement=invalide)
|
||||
75
backend-django/backend/tests/pam/__init__.py
Normal file
75
backend-django/backend/tests/pam/__init__.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from rest_framework import status
|
||||
import pandas as pd
|
||||
from rest_framework.test import APIClient, APITestCase
|
||||
from ...utils_extraction import to_table_pam
|
||||
|
||||
from ...models import (Administre, CustomUser, Decision, DecisionChoices,
|
||||
Domaine, Filiere, FormationEmploi, Garnison, Poste,
|
||||
RefGest, RefOrg, RefSvFil, SousVivier, Administres_Pams, Postes_Pams, PAM)
|
||||
|
||||
import datetime
|
||||
|
||||
|
||||
|
||||
class PamTestCase(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.date = datetime.date(2023,1,1)
|
||||
cls.pam_2022 = PAM.objects.create(pam_id='2022',pam_date=datetime.date(2022,7,15), pam_libelle= "PAM de l'année 2022", pam_statut='PAM en cours')
|
||||
cls.pam_2023 = PAM.objects.create(pam_id='2023',pam_date=datetime.date(2022,7,15), pam_libelle= "PAM de l'année 2023", pam_statut='PAM A+1')
|
||||
|
||||
|
||||
def test_extraction_pam(self):
|
||||
"""
|
||||
Construit la table PAM qui servira à récuperer l'année du PAM et piloter l'affichage des données en fonction du bon pam pour chaque tables
|
||||
Cloture le PAM en le sauvegardant dans un fichier excel
|
||||
"""
|
||||
annee_pam = str(self.date.year)
|
||||
annee_pam_suivant = str(self.date.year + 1)
|
||||
|
||||
pam=pd.DataFrame(columns = ['pam_id','pam_date', 'pam_libelle','pam_statut'])
|
||||
pam_id = annee_pam
|
||||
pam_id_suivant = annee_pam_suivant
|
||||
pam_libelle = f"PAM de l'année {annee_pam}"
|
||||
pam_libelle_suivant = f"PAM de l'année {annee_pam_suivant}"
|
||||
pam_date = self.date
|
||||
pam_date_suivant = pam_date
|
||||
pam_statut = "PAM en cours"
|
||||
pam_statut_suivant = "PAM A+1"
|
||||
|
||||
sorg_id = "SORG"
|
||||
sorg_libelle = "SORG"
|
||||
sorg_statut = "SORG"
|
||||
|
||||
pam['pam_id'] = [pam_id,pam_id_suivant, sorg_id]
|
||||
pam['pam_date'] = [pam_date,pam_date_suivant, pam_date]
|
||||
pam['pam_libelle'] = [pam_libelle,pam_libelle_suivant,sorg_libelle]
|
||||
pam['pam_statut'] = [pam_statut,pam_statut_suivant,sorg_statut]
|
||||
|
||||
return pam
|
||||
|
||||
|
||||
def test_insertion_pam(self):
|
||||
self.liste_create = []
|
||||
self.liste_update = []
|
||||
self.update_header = ['pam_date','pam_libelle','pam_statut']
|
||||
self.df = self.test_extraction_pam()
|
||||
for i in range(self.df.shape[0]):
|
||||
self.pams = PAM.objects.filter(pam_id=self.df.at[i,'pam_id'])
|
||||
self.pam = PAM(pam_id=self.df.at[i, 'pam_id'],pam_date=self.df.at[i, 'pam_date'], pam_libelle=self.df.at[i, 'pam_libelle'],
|
||||
pam_statut=self.df.at[i, 'pam_statut'])
|
||||
|
||||
if self.pam.pam_id in self.pams.values_list('pam_id', flat = True):
|
||||
self.liste_update.append(self.pam)
|
||||
else:
|
||||
cloture=PAM.objects.filter(pam_statut="PAM en cours")
|
||||
cloture.update(pam_statut ="PAM clôturé")
|
||||
self.liste_create.append(self.pam)
|
||||
|
||||
if self.liste_create:
|
||||
PAM.objects.bulk_create(self.liste_create)
|
||||
if self.liste_update:
|
||||
PAM.objects.bulk_update(self.liste_update, fields=self.update_header)
|
||||
6
backend-django/backend/tests/utils/__init__.py
Normal file
6
backend-django/backend/tests/utils/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from .alimentation import *
|
||||
from .decisions import *
|
||||
from .decorators import *
|
||||
from .functions import *
|
||||
from .logging import *
|
||||
from .predicates import *
|
||||
56
backend-django/backend/tests/utils/alimentation.py
Normal file
56
backend-django/backend/tests/utils/alimentation.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ...utils.alimentation import BOCols as Cols
|
||||
|
||||
|
||||
class BOColsTestCase(SimpleTestCase):
|
||||
""" tests pour BOCols """
|
||||
|
||||
def test_attributes(self):
|
||||
""" vérifie que les nouveaux attributs sont renseignés correctement """
|
||||
|
||||
for col in Cols:
|
||||
self.assertIsInstance(col.value, str, f"{col} : la valeur n'a pas le bon type")
|
||||
|
||||
def test_columns(self):
|
||||
""" vérifie les colonnes renvoyées """
|
||||
members = list(Cols)
|
||||
|
||||
col_names = [col.value for col in members]
|
||||
self.assertCountEqual(col_names, Cols.columns(), "les noms de colonnes (sans argument) ne sont pas les bons")
|
||||
|
||||
col = members[0]
|
||||
col_names = [col.value]
|
||||
self.assertCountEqual(col_names, Cols.columns(col), "les noms de colonnes (un argument) ne sont pas les bons")
|
||||
|
||||
col_list = members[0:2]
|
||||
col_names = [col.value for col in col_list]
|
||||
self.assertCountEqual(col_names, Cols.columns(*col_list), "les noms de colonnes (plusieurs arguments) ne sont pas les bons")
|
||||
|
||||
def test_col_mapping(self):
|
||||
""" vérifie les correspondances renvoyés """
|
||||
|
||||
members = list(Cols)
|
||||
std_mapping = {'a': 1, 'b': 'test'}
|
||||
enum_mapping = {members[0]: (2, 3), members[1]: members[1].name}
|
||||
mapping_before = {**enum_mapping, **std_mapping}
|
||||
mapping_after = Cols.col_mapping(mapping_before)
|
||||
self.assertTrue(all(k in mapping_after for k in std_mapping.keys()), "toutes les clés standard doivent faire partie du mapping final")
|
||||
self.assertTrue(all(v == mapping_after.get(k) for k, v in std_mapping.items()), "les valeurs de clés standard ne doivent pas changer")
|
||||
self.assertTrue(all(k.value in mapping_after for k in enum_mapping.keys()), f"tous les noms de colonnes de clés de type {Cols.__name__} doivent faire partie du mapping final")
|
||||
self.assertTrue(all(v == mapping_after.get(k.value) for k, v in enum_mapping.items()), f"les valeurs de clés de type {Cols.__name__} ne doivent pas changer")
|
||||
|
||||
def test_converters(self):
|
||||
""" vérifie les convertisseurs renvoyés """
|
||||
members = list(Cols)
|
||||
|
||||
col_names = [col.value for col in members if col.converter]
|
||||
self.assertCountEqual(col_names, Cols.converters().keys(), "les convertisseurs (sans argument) ne sont pas les bons")
|
||||
|
||||
col = members[0]
|
||||
col_names = [col.value]
|
||||
self.assertCountEqual(col_names, Cols.converters(col).keys(), "les convertisseurs (un argument) ne sont pas les bons")
|
||||
|
||||
col_list = members[0:2]
|
||||
col_names = [col.value for col in col_list]
|
||||
self.assertCountEqual(col_names, Cols.converters(*col_list).keys(), "les convertisseurs (plusieurs arguments) ne sont pas les bons")
|
||||
283
backend-django/backend/tests/utils/decisions.py
Normal file
283
backend-django/backend/tests/utils/decisions.py
Normal file
@@ -0,0 +1,283 @@
|
||||
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()))
|
||||
85
backend-django/backend/tests/utils/decorators.py
Normal file
85
backend-django/backend/tests/utils/decorators.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from .samples import MyClass
|
||||
from ...utils.decorators import class_logger, decorate_functions, CLASS_ATTR_LOGGER
|
||||
from ...utils.functions import find_class
|
||||
from ...utils.logging import get_logger_name
|
||||
from ...utils.predicates import func_name_is_in
|
||||
from django.test import SimpleTestCase
|
||||
from typing import Tuple
|
||||
import functools
|
||||
|
||||
|
||||
def double_result(func):
|
||||
""" décorateur pour doubler les résultats """
|
||||
@functools.wraps(func)
|
||||
def inner(*args, **kwargs):
|
||||
return 2 * func(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
|
||||
class DecoratorTest(SimpleTestCase):
|
||||
|
||||
def test_decorate_functions(self):
|
||||
num = 5
|
||||
a = 1
|
||||
b = 2
|
||||
res = a + b
|
||||
res_x2 = res * 2
|
||||
|
||||
def given():
|
||||
msg = 'le résultat initial est bien celui attendu'
|
||||
self.assertEqual(MyClass.class_met(a, b), res, msg)
|
||||
self.assertEqual(MyClass.static_met(a, b), res, msg)
|
||||
self.assertEqual(MyClass(num).std_met(a, b), res, msg)
|
||||
given()
|
||||
|
||||
# tout est décoré
|
||||
Type = decorate_functions(double_result, lambda func: True)(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res_x2)
|
||||
self.assertEqual(Type.static_met(a, b), res_x2)
|
||||
self.assertEqual(Type(num).std_met(a, b), res_x2)
|
||||
|
||||
# une seule méthode est décorée (1ère)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.class_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res_x2)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), res)
|
||||
|
||||
# une seule méthode est décorée (2ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.static_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res_x2)
|
||||
self.assertEqual(Type(num).std_met(a, b), res)
|
||||
|
||||
# une seule méthode est décorée (3ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.std_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), res_x2)
|
||||
|
||||
# une seule méthode est décorée deux fois (3ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.std_met.__name__,))(Type)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), 2 * res_x2)
|
||||
|
||||
# pas de changement au niveau de la classe d'origine
|
||||
self.assertEqual(MyClass.class_met(a, b), res)
|
||||
self.assertEqual(MyClass.static_met(a, b), res)
|
||||
self.assertEqual(MyClass(num).std_met(a, b), res)
|
||||
|
||||
def test_class_logger(self):
|
||||
def given():
|
||||
self.assertEqual(hasattr(MyClass, CLASS_ATTR_LOGGER), False, "la classe initiale n'a pas de logger")
|
||||
given()
|
||||
|
||||
Type = class_logger(MyClass)
|
||||
self.assertEqual(hasattr(Type, CLASS_ATTR_LOGGER), True)
|
||||
self.assertEqual(getattr(Type, CLASS_ATTR_LOGGER).name, get_logger_name(MyClass))
|
||||
|
||||
# 2ème décoration
|
||||
Type = class_logger(Type)
|
||||
self.assertEqual(hasattr(Type, CLASS_ATTR_LOGGER), True)
|
||||
self.assertEqual(getattr(Type, CLASS_ATTR_LOGGER).name, get_logger_name(MyClass))
|
||||
|
||||
# pas de changement au niveau de la classe d'origine
|
||||
self.assertEqual(hasattr(MyClass, CLASS_ATTR_LOGGER), False)
|
||||
30
backend-django/backend/tests/utils/functions.py
Normal file
30
backend-django/backend/tests/utils/functions.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from .samples import my_func, MyClass
|
||||
from ...utils.functions import find_class
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class FunctionsTest(SimpleTestCase):
|
||||
|
||||
def test_find_class(self):
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native : None
|
||||
self.assertIsNone(find_class(str.join))
|
||||
|
||||
# fonctions : None
|
||||
self.assertIsNone(find_class(local_func))
|
||||
self.assertIsNone(find_class(my_func))
|
||||
|
||||
# méthodes
|
||||
self.assertEqual(find_class(MainType.class_met), MainType)
|
||||
self.assertEqual(find_class(MainType.static_met), MainType)
|
||||
self.assertEqual(find_class(main_type.std_met), MainType)
|
||||
self.assertEqual(find_class(SubType.sub_class_met), SubType)
|
||||
self.assertEqual(find_class(SubType.sub_static_met), SubType)
|
||||
self.assertEqual(find_class(sub_type.sub_std_met), SubType)
|
||||
104
backend-django/backend/tests/utils/logging.py
Normal file
104
backend-django/backend/tests/utils/logging.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import random
|
||||
import string
|
||||
from unittest import mock
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ...utils.logging import (TAG_DATA_FEED, TAG_PERF, get_logger,
|
||||
get_logger_name)
|
||||
from .samples import MyClass, my_func
|
||||
|
||||
|
||||
class LoggingTest(SimpleTestCase):
|
||||
|
||||
def test_get_logger_name(self):
|
||||
module_name = __name__
|
||||
ext_module_name = my_func.__module__
|
||||
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
main_type_logger = f'{ext_module_name}.{MainType.__qualname__}'
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
sub_type_logger = f'{ext_module_name}.{SubType.__qualname__}'
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# None
|
||||
self.assertIsNone(get_logger_name())
|
||||
self.assertIsNone(get_logger_name(None))
|
||||
|
||||
# classes natives
|
||||
self.assertIsNone(get_logger_name(str))
|
||||
self.assertIsNone(get_logger_name(int))
|
||||
self.assertIsNone(get_logger_name(dict))
|
||||
self.assertIsNone(get_logger_name(list))
|
||||
self.assertIsNone(get_logger_name(tuple))
|
||||
|
||||
# instances de classes natives (mais pas str)
|
||||
self.assertIsNone(get_logger_name(1))
|
||||
self.assertIsNone(get_logger_name({'a': 'b'}))
|
||||
self.assertIsNone(get_logger_name(['c']))
|
||||
self.assertIsNone(get_logger_name(('d',)))
|
||||
|
||||
# fonctions natives
|
||||
self.assertIsNone(get_logger_name(str.join))
|
||||
|
||||
# str
|
||||
self.assertEqual(get_logger_name('test'), 'test')
|
||||
self.assertEqual(get_logger_name(''), None)
|
||||
|
||||
# classes
|
||||
self.assertEqual(get_logger_name(MainType), main_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType), sub_type_logger)
|
||||
|
||||
# instances de classes
|
||||
self.assertEqual(get_logger_name(main_type), main_type_logger)
|
||||
self.assertEqual(get_logger_name(sub_type), sub_type_logger)
|
||||
|
||||
# fonctions et méthodes
|
||||
self.assertEqual(get_logger_name(local_func), module_name)
|
||||
self.assertEqual(get_logger_name(my_func), ext_module_name)
|
||||
self.assertEqual(get_logger_name(MainType.class_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(MainType.static_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(main_type.std_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType.sub_class_met), sub_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType.sub_static_met), sub_type_logger)
|
||||
self.assertEqual(get_logger_name(sub_type.sub_std_met), sub_type_logger)
|
||||
|
||||
def test_get_logger_without_tags(self):
|
||||
func_1 = MyClass.class_met
|
||||
func_2 = MyClass.static_met
|
||||
|
||||
def given():
|
||||
self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
|
||||
given()
|
||||
|
||||
msg = "l'instance doit être la même"
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
self.assertIs(get_logger(logger_name), get_logger(logger_name), msg)
|
||||
self.assertIs(get_logger(func_1), get_logger(func_2), msg)
|
||||
|
||||
def test_get_logger_with_tags(self):
|
||||
func_1 = MyClass.class_met
|
||||
func_2 = MyClass.static_met
|
||||
|
||||
def given():
|
||||
self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
|
||||
given()
|
||||
|
||||
msg = "l'instance doit être la même"
|
||||
for tags in [TAG_PERF, TAG_DATA_FEED, ('1', '2'), ['3', '4'], set(['5', '6'])]:
|
||||
with self.subTest(tags=tags):
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
self.assertIs(get_logger(logger_name, tags), get_logger(logger_name, tags), msg)
|
||||
self.assertIs(get_logger(func_1, tags), get_logger(func_2, tags), msg)
|
||||
|
||||
prev_logger = None
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
for i, tags in enumerate([('1', '2', '3', '4'), ['3', '4', '1', '2'], set(['2', '1', '3', '4', '1'])]):
|
||||
curr_logger = get_logger(logger_name, tags)
|
||||
if i > 0:
|
||||
self.assertIs(curr_logger, prev_logger, msg)
|
||||
prev_logger = get_logger(logger_name, tags)
|
||||
127
backend-django/backend/tests/utils/predicates.py
Normal file
127
backend-django/backend/tests/utils/predicates.py
Normal file
@@ -0,0 +1,127 @@
|
||||
from .samples import my_func, _my_private_func, MyClass
|
||||
from ...utils.predicates import func_class_name_is_in, func_class_name_is_not_in, func_name_is_in, func_name_is_not_in, func_is_public
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class PredicatesTest(SimpleTestCase):
|
||||
|
||||
def __test_func_class_name_is_in(self, negation: bool = False):
|
||||
""" teste func_class_name_is_in et func_class_name_is_not_in """
|
||||
|
||||
func = func_class_name_is_not_in if negation else func_class_name_is_in
|
||||
result = negation is not True
|
||||
|
||||
own_name = self.__class__.__name__
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
main_type_name = MainType.__name__
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
sub_type_name = SubType.__name__
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native : None
|
||||
self.assertEqual(func(str.__name__)(str.join), False)
|
||||
|
||||
# fonction locale : None
|
||||
self.assertEqual(func(own_name)(local_func), False)
|
||||
|
||||
# méthodes
|
||||
predicate = func(main_type_name)
|
||||
self.assertEqual(predicate(MainType.class_met), result)
|
||||
self.assertEqual(predicate(MainType.static_met), result)
|
||||
self.assertEqual(predicate(main_type.std_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), not result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), not result)
|
||||
|
||||
predicate = func(sub_type_name)
|
||||
self.assertEqual(predicate(MainType.class_met), not result)
|
||||
self.assertEqual(predicate(MainType.static_met), not result)
|
||||
self.assertEqual(predicate(main_type.std_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), result)
|
||||
|
||||
def __test_func_name_is_in(self, negation: bool = False):
|
||||
""" teste func_name_is_in et func_name_is_not_in """
|
||||
|
||||
func = func_name_is_not_in if negation else func_name_is_in
|
||||
result = negation is not True
|
||||
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native
|
||||
self.assertEqual(func('join')(str.join), result)
|
||||
self.assertEqual(func('other', 'join')(str.join), result)
|
||||
|
||||
# autre fonction, fonction locale
|
||||
self.assertEqual(func('local_func')(local_func), result)
|
||||
self.assertEqual(func('other', 'local_func')(local_func), result)
|
||||
self.assertEqual(func('my_func')(my_func), result)
|
||||
self.assertEqual(func('other', 'my_func')(my_func), result)
|
||||
|
||||
|
||||
# méthodes
|
||||
predicate = func('class_met', 'std_met', 'sub_static_met')
|
||||
self.assertEqual(predicate(MainType.class_met), result)
|
||||
self.assertEqual(predicate(MainType.static_met), not result)
|
||||
self.assertEqual(predicate(main_type.std_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), not result)
|
||||
|
||||
predicate = func('static_met', 'sub_class_met', 'sub_std_met')
|
||||
self.assertEqual(predicate(MainType.class_met), not result)
|
||||
self.assertEqual(predicate(MainType.static_met), result)
|
||||
self.assertEqual(predicate(main_type.std_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), not result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), result)
|
||||
|
||||
|
||||
def test_func_class_name_is_in(self):
|
||||
self.__test_func_class_name_is_in()
|
||||
|
||||
def test_func_class_name_is_not_in(self):
|
||||
self.__test_func_class_name_is_in(negation=True)
|
||||
|
||||
def test_func_name_is_in(self):
|
||||
self.__test_func_name_is_in()
|
||||
|
||||
def test_func_name_is_not_in(self):
|
||||
self.__test_func_name_is_in(negation=True)
|
||||
|
||||
def test_func_is_public(self):
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native
|
||||
self.assertEqual(func_is_public(str.join), True)
|
||||
|
||||
# autre fonction, fonction locale
|
||||
self.assertEqual(func_is_public(local_func), True)
|
||||
self.assertEqual(func_is_public(my_func), True)
|
||||
self.assertEqual(func_is_public(_my_private_func), False)
|
||||
|
||||
# méthodes
|
||||
self.assertEqual(func_is_public(MainType._protected_met), False)
|
||||
self.assertEqual(func_is_public(MainType.class_met), True)
|
||||
self.assertEqual(func_is_public(MainType.static_met), True)
|
||||
self.assertEqual(func_is_public(main_type.std_met), True)
|
||||
self.assertEqual(func_is_public(SubType.sub_class_met), True)
|
||||
self.assertEqual(func_is_public(SubType.sub_static_met), True)
|
||||
self.assertEqual(func_is_public(sub_type.sub_std_met), True)
|
||||
58
backend-django/backend/tests/utils/samples.py
Normal file
58
backend-django/backend/tests/utils/samples.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# quelques définitions pour les tests ==>
|
||||
|
||||
def my_func(a: int, b: int):
|
||||
""" fonction sans classe """
|
||||
return a + b
|
||||
|
||||
|
||||
def _my_private_func(a: int, b: int):
|
||||
""" fonction sans classe (non importée par défaut avec import *) """
|
||||
return a + b
|
||||
|
||||
|
||||
class MyClass():
|
||||
""" classe pour tests """
|
||||
num = None
|
||||
|
||||
def __init__(self, num):
|
||||
""" la classe est paramétrée """
|
||||
self.num = num
|
||||
|
||||
def _protected_met(self, a: int, b: int):
|
||||
""" méthode standard (protected par convention) """
|
||||
return a + b
|
||||
|
||||
class MySubClass():
|
||||
sub_num = None
|
||||
|
||||
def __init__(self, num):
|
||||
""" la classe est paramétrée """
|
||||
self.sub_num = num
|
||||
|
||||
@classmethod
|
||||
def sub_class_met(cls):
|
||||
""" méthode de classe """
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def sub_static_met():
|
||||
""" méthode statique """
|
||||
return True
|
||||
|
||||
def sub_std_met():
|
||||
""" méthode standard """
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def class_met(cls, a: int, b: int):
|
||||
""" méthode de classe """
|
||||
return a + b
|
||||
|
||||
@staticmethod
|
||||
def static_met(a: int, b: int):
|
||||
""" méthode statique """
|
||||
return a + b
|
||||
|
||||
def std_met(self, a: int, b: int):
|
||||
""" méthode standard """
|
||||
return a + b
|
||||
2
backend-django/backend/tests/views/__init__.py
Normal file
2
backend-django/backend/tests/views/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .decision import *
|
||||
from .notation import *
|
||||
2
backend-django/backend/tests/views/constants.py
Normal file
2
backend-django/backend/tests/views/constants.py
Normal file
@@ -0,0 +1,2 @@
|
||||
USERNAME = 'test'
|
||||
PASSWORD = 'test'
|
||||
147
backend-django/backend/tests/views/decision.py
Normal file
147
backend-django/backend/tests/views/decision.py
Normal file
@@ -0,0 +1,147 @@
|
||||
from unittest import mock
|
||||
|
||||
from backend.models import Administre, Decision, DecisionChoices, Poste
|
||||
from backend.models import StatutPamChoices as StatutPam
|
||||
from backend.utils.decisions import (KEY_CREATE, KEY_UPDATE,
|
||||
get_available_decisions)
|
||||
from backend.utils.permissions import (KEY_READ, KEY_WRITE, Profiles,
|
||||
get_profiles_by_adm)
|
||||
from backend.views import DecisionView
|
||||
from django.contrib.auth import get_user_model
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from .constants import PASSWORD, USERNAME
|
||||
from .test_utils import TestUtilsMixin, disable_gestionnaire_permission
|
||||
|
||||
PK_SV_1 = 'SV1'
|
||||
VIEW_TYPE = DecisionView
|
||||
|
||||
class DecisionViewTest(APITestCase, TestUtilsMixin):
|
||||
|
||||
basename = 'Decision'
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
user = get_user_model().objects.create(id=1, username=USERNAME, is_superuser=True)
|
||||
user.set_password(PASSWORD)
|
||||
user.save()
|
||||
|
||||
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")
|
||||
logged_in = self.client.login(username=USERNAME, password=PASSWORD)
|
||||
self.assertTrue(logged_in, "l'utilisateur devrait être connecté")
|
||||
|
||||
def tearDown(self):
|
||||
""" supprime tous les administrés, les postes, les décisions en fin de test """
|
||||
|
||||
self.client.logout()
|
||||
Decision.objects.all().delete()
|
||||
Poste.objects.all().delete()
|
||||
Administre.objects.all().delete()
|
||||
|
||||
def test_list_anonymous(self):
|
||||
""" vérifie que l'accès anonyme est interdit """
|
||||
|
||||
self.client.logout()
|
||||
url = self._api_url()
|
||||
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
@disable_gestionnaire_permission(VIEW_TYPE)
|
||||
def test_list_authenticated(self):
|
||||
""" vérifie que l'utilisateur authentifié peut récupérer des décisions """
|
||||
|
||||
url = self._api_url()
|
||||
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
@disable_gestionnaire_permission(VIEW_TYPE)
|
||||
def test_crud(self):
|
||||
""" test de création, MAJ, suppression """
|
||||
try:
|
||||
statut_pam = next(x for x in StatutPam if x.dec_enabled)
|
||||
self.assertIsNotNone(statut_pam, 'il devrait exister un statut permettant les décisions')
|
||||
self.user = get_user_model().objects.first()
|
||||
self.adm = Administre.objects.create(pk=1, a_statut_pam=statut_pam)
|
||||
|
||||
@mock.patch(
|
||||
f'{get_available_decisions.__module__}.{get_profiles_by_adm.__name__}',
|
||||
return_value={self.adm.pk: {KEY_READ: (), KEY_WRITE: (Profiles.FILIERE, Profiles.PCP)}}
|
||||
)
|
||||
def do_with_mock_profiles(mock):
|
||||
user = self.user
|
||||
adm = self.adm
|
||||
decisions = get_available_decisions((adm,), user=user).get(adm.pk)
|
||||
self.assertTrue(decisions.get(KEY_CREATE), 'il devrait exister des décisions possibles (création)')
|
||||
|
||||
def create(poste_id, de_decision, adm_id=adm.pk, delete_former=None):
|
||||
return self.client.post(
|
||||
self._api_url(),
|
||||
{'administre_id': adm_id, 'poste_id': poste_id, 'de_decision': de_decision, **({'delete_former': delete_former} if isinstance(delete_former, bool) else {})}
|
||||
)
|
||||
|
||||
postes = (Poste.objects.create(pk='11'), Poste.objects.create(pk='13'))
|
||||
poste_1 = postes[0].pk
|
||||
poste_2 = postes[1].pk
|
||||
dec_status_1 = decisions.get(KEY_CREATE)[0]
|
||||
|
||||
# création initiale
|
||||
response = create(poste_1, dec_status_1)
|
||||
|
||||
qs_decision1 = Decision.objects.filter(pk=adm.pk, poste_id=poste_1, de_decision=dec_status_1)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(1, Decision.objects.count(), "il doit exister une seule décision")
|
||||
self.assertTrue(qs_decision1.exists(), "la décision n'a pas les bonnes données")
|
||||
|
||||
# création bis, pas possible sans forcer
|
||||
response = create(poste_2, dec_status_1)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(1, Decision.objects.count(), "il doit exister une seule décision")
|
||||
self.assertTrue(qs_decision1.exists(), "la première décision doit encore exister")
|
||||
|
||||
# création bis en forçant
|
||||
notes = 'notes'
|
||||
qs_decision1.update(de_notes_gestionnaire='notes')
|
||||
self.assertEqual(notes, qs_decision1.first().de_notes_gestionnaire, "les notes doivent être sauvegardées pour le prochain test")
|
||||
|
||||
response = create(poste_2, dec_status_1, delete_former=True)
|
||||
|
||||
qs_decision2 = Decision.objects.filter(pk=adm.pk, poste_id=poste_2, de_decision=dec_status_1)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(1, Decision.objects.count(), "il doit exister une seule décision")
|
||||
self.assertFalse(qs_decision1.exists(), "la première décision ne doit plus exister")
|
||||
self.assertTrue(qs_decision2.exists(), "la deuxième décision n'a pas les bonnes données")
|
||||
self.assertIsNone(qs_decision2.first().de_notes_gestionnaire, "il ne doit plus exister de notes dans la deuxième décision")
|
||||
|
||||
# MAJ
|
||||
adm = Administre.objects.filter(pk=adm.pk).first()
|
||||
decisions = get_available_decisions((adm,), user=user).get(adm.pk)
|
||||
self.assertTrue(decisions.get(KEY_UPDATE), 'il devrait exister des décisions possibles (MAJ) pour le prochain test')
|
||||
dec_status_2 = decisions.get(KEY_UPDATE)[0]
|
||||
|
||||
response = self.client.patch(self._api_url(adm.pk), data={'de_decision': dec_status_2})
|
||||
|
||||
qs_decision3 = Decision.objects.filter(pk=adm.pk, poste_id=poste_2, de_decision=dec_status_2)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(1, Decision.objects.count(), "il doit exister une seule décision")
|
||||
self.assertTrue(qs_decision3.exists(), "la deuxième décision doit changer de statut")
|
||||
|
||||
# suppression
|
||||
response = self.client.delete(self._api_url(adm.pk))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertEqual(0, Decision.objects.count(), "il ne doit plus exister de décision")
|
||||
|
||||
do_with_mock_profiles()
|
||||
finally:
|
||||
self.user = None
|
||||
self.adm = None
|
||||
46
backend-django/backend/tests/views/notation.py
Normal file
46
backend-django/backend/tests/views/notation.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from backend.views import NotationView
|
||||
from django.contrib.auth import get_user_model
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from .constants import PASSWORD, USERNAME
|
||||
from .test_utils import TestUtilsMixin, disable_gestionnaire_permission
|
||||
|
||||
VIEW_TYPE = NotationView
|
||||
|
||||
class NotationViewTest(APITestCase, TestUtilsMixin):
|
||||
|
||||
basename = 'Notation'
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
user = get_user_model().objects.create(id=1, username=USERNAME)
|
||||
user.set_password(PASSWORD)
|
||||
user.save()
|
||||
|
||||
def setUp(self):
|
||||
logged_in = self.client.login(username=USERNAME, password=PASSWORD)
|
||||
self.assertTrue(logged_in, "l'utilisateur devrait être connecté")
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_list_anonymous(self):
|
||||
""" vérifie que l'accès anonyme est interdit """
|
||||
|
||||
self.client.logout()
|
||||
url = self._api_url()
|
||||
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
@disable_gestionnaire_permission(VIEW_TYPE)
|
||||
def test_list_authenticated(self):
|
||||
""" vérifie que l'utilisateur authentifié peut récupérer des décisions """
|
||||
|
||||
url = self._api_url()
|
||||
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
44
backend-django/backend/tests/views/test_utils.py
Normal file
44
backend-django/backend/tests/views/test_utils.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from django.urls import reverse
|
||||
from typing import Any
|
||||
from unittest import mock
|
||||
|
||||
|
||||
def disable_gestionnaire_permission(type):
|
||||
"""
|
||||
Utilise "mock" pour ignorer le gestionnaire de permissions dans la vue.
|
||||
TODO trouver un mécanisme de mock plus précis
|
||||
|
||||
:param type: le type de la vue
|
||||
:type type: class:`ModelViewSet` par exemple
|
||||
|
||||
:return: résultat du mock
|
||||
:rtype: voir mock
|
||||
"""
|
||||
return mock.patch.object(type, 'permission_classes', [p for p in type.permission_classes if p.__name__ != 'GestionnairePermission'])
|
||||
|
||||
|
||||
def api_url(basename: str, pk: Any = None) -> str:
|
||||
"""
|
||||
renvoie l'URL selon qu'on a besoin d'un ID ou non
|
||||
nécessite l'utilisation de SimpleRouter ou DefaultRouter (voir urls.py)
|
||||
|
||||
:param basename: valeur de "basename"
|
||||
:type basename: str
|
||||
|
||||
:param pk: valeur qui permet de savoir s'il s'agit d'une URL "list" ou "detail" (voir https://www.django-rest-framework.org/api-guide/routers/#simplerouter)
|
||||
:type pk: Any
|
||||
|
||||
:return: URL
|
||||
:rtype: str
|
||||
"""
|
||||
return reverse(f'{basename}-list') if pk is None else reverse(f'{basename}-detail', args=[pk])
|
||||
|
||||
|
||||
class TestUtilsMixin:
|
||||
"""
|
||||
mixin à ajouter pour les tests
|
||||
"""
|
||||
|
||||
def _api_url(self, pk: Any = None) -> str:
|
||||
""" voir fonction "api_url", nécessite un champ "basename" pour remplir le paramètre """
|
||||
return api_url(self.basename, pk)
|
||||
Reference in New Issue
Block a user