""" Tests unitaires pour le module School. Vérifie que tous les endpoints (Speciality, Teacher, SchoolClass, Planning, Fee, Discount, PaymentPlan, PaymentMode, Competency, EstablishmentCompetency) requièrent une authentification JWT. """ from django.test import TestCase, override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APIClient from rest_framework_simplejwt.tokens import RefreshToken from Auth.models import Profile def create_user(email="school_test@example.com", password="testpassword123"): return Profile.objects.create_user(username=email, email=email, password=password) def get_jwt_token(user): refresh = RefreshToken.for_user(user) return str(refresh.access_token) TEST_REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), } TEST_CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}} OVERRIDE_SETTINGS = dict( CACHES=TEST_CACHES, SESSION_ENGINE='django.contrib.sessions.backends.db', REST_FRAMEWORK=TEST_REST_FRAMEWORK, ) def _assert_endpoint_requires_auth(test_case, method, url, payload=None): """Utilitaire : vérifie qu'un endpoint retourne 401 sans authentification.""" client = APIClient() call = getattr(client, method) kwargs = {} if payload is not None: import json kwargs = {"data": json.dumps(payload), "content_type": "application/json"} response = call(url, **kwargs) test_case.assertEqual( response.status_code, status.HTTP_401_UNAUTHORIZED, msg=f"{method.upper()} {url} devrait retourner 401 sans auth, reçu {response.status_code}", ) # --------------------------------------------------------------------------- # Speciality # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class SpecialityEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints Speciality.""" def setUp(self): self.client = APIClient() self.list_url = reverse("School:speciality_list_create") self.user = create_user() def test_get_specialities_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_speciality_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"name": "Piano"} ) def test_get_speciality_detail_sans_auth_retourne_401(self): url = reverse("School:speciality_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "get", url) def test_put_speciality_sans_auth_retourne_401(self): url = reverse("School:speciality_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "put", url, payload={"name": "Violon"}) def test_delete_speciality_sans_auth_retourne_401(self): url = reverse("School:speciality_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "delete", url) def test_get_specialities_avec_auth_retourne_200(self): """GET /School/specialities avec token valide doit retourner 200.""" token = get_jwt_token(self.user) self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}") response = self.client.get(self.list_url, {"establishment_id": 1}) self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_400_BAD_REQUEST]) # --------------------------------------------------------------------------- # Teacher # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class TeacherEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints Teacher.""" def setUp(self): self.list_url = reverse("School:teacher_list_create") def test_get_teachers_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_teacher_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"first_name": "Jean"} ) def test_get_teacher_detail_sans_auth_retourne_401(self): url = reverse("School:teacher_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "get", url) def test_put_teacher_sans_auth_retourne_401(self): url = reverse("School:teacher_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "put", url, payload={"first_name": "Pierre"}) def test_delete_teacher_sans_auth_retourne_401(self): url = reverse("School:teacher_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "delete", url) # --------------------------------------------------------------------------- # SchoolClass # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class SchoolClassEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints SchoolClass.""" def setUp(self): self.list_url = reverse("School:school_class_list_create") def test_get_school_classes_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_school_class_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"name": "Classe A"} ) def test_get_school_class_detail_sans_auth_retourne_401(self): url = reverse("School:school_class_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "get", url) # --------------------------------------------------------------------------- # Fee # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class FeeEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints Fee.""" def setUp(self): self.list_url = reverse("School:fee_list_create") def test_get_fees_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_fee_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"amount": 100} ) def test_get_fee_detail_sans_auth_retourne_401(self): url = reverse("School:fee_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "get", url) def test_put_fee_sans_auth_retourne_401(self): url = reverse("School:fee_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "put", url, payload={"amount": 200}) def test_delete_fee_sans_auth_retourne_401(self): url = reverse("School:fee_detail", kwargs={"id": 1}) _assert_endpoint_requires_auth(self, "delete", url) # --------------------------------------------------------------------------- # Discount # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class DiscountEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints Discount.""" def setUp(self): self.list_url = reverse("School:discount_list_create") def test_get_discounts_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_discount_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"rate": 10} ) # --------------------------------------------------------------------------- # PaymentPlan # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class PaymentPlanEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints PaymentPlan.""" def setUp(self): self.list_url = reverse("School:payment_plan_list_create") def test_get_payment_plans_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_payment_plan_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"name": "Plan A"} ) # --------------------------------------------------------------------------- # PaymentMode # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class PaymentModeEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints PaymentMode.""" def setUp(self): self.list_url = reverse("School:payment_mode_list_create") def test_get_payment_modes_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_payment_mode_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"name": "Virement"} ) # --------------------------------------------------------------------------- # Competency # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class CompetencyEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints Competency.""" def setUp(self): self.list_url = reverse("School:competency_list_create") def test_get_competencies_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_competency_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"name": "Lecture"} ) # --------------------------------------------------------------------------- # EstablishmentCompetency # --------------------------------------------------------------------------- @override_settings(**OVERRIDE_SETTINGS) class EstablishmentCompetencyEndpointAuthTest(TestCase): """Tests d'authentification sur les endpoints EstablishmentCompetency.""" def setUp(self): self.list_url = reverse("School:establishment_competency_list_create") def test_get_establishment_competencies_sans_auth_retourne_401(self): _assert_endpoint_requires_auth(self, "get", self.list_url) def test_post_establishment_competency_sans_auth_retourne_401(self): _assert_endpoint_requires_auth( self, "post", self.list_url, payload={"competency": 1} )