Spaces:
Sleeping
Sleeping
| """Tests du mode maintenance : endpoint /api/v1/config/ + middleware. | |
| Le middleware bloque les requêtes /api/ en 503 quand le flag est ON, avec | |
| exemptions (config, monitoring, staff). L'endpoint config est public, sans | |
| throttle, et reflète le singleton SiteConfiguration. | |
| """ | |
| import pytest | |
| from animetix.models import SiteConfiguration | |
| from django.contrib.auth.models import User | |
| from django.urls import reverse | |
| from rest_framework.test import APIClient | |
| def api_client(): | |
| return APIClient() | |
| def _set_maintenance(on: bool, message: str = "", until=None): | |
| config = SiteConfiguration.get_solo() | |
| config.maintenance_mode = on | |
| config.maintenance_message = message | |
| config.maintenance_until = until | |
| config.save() | |
| return config | |
| # --------------------------------------------------------------------------- # | |
| # GET /api/v1/config/ | |
| # --------------------------------------------------------------------------- # | |
| def test_config_endpoint_defaults(api_client): | |
| resp = api_client.get(reverse("api_config")) | |
| assert resp.status_code == 200 | |
| data = resp.json() | |
| assert data["maintenance_mode"] is False | |
| assert data["maintenance_message"] == "" | |
| assert data["maintenance_until"] is None | |
| assert data["version"] | |
| def test_config_endpoint_reflects_flag(api_client): | |
| _set_maintenance(True, message="Retour à 18h") | |
| data = api_client.get(reverse("api_config")).json() | |
| assert data["maintenance_mode"] is True | |
| assert data["maintenance_message"] == "Retour à 18h" | |
| def test_config_singleton_single_row(): | |
| SiteConfiguration.get_solo() | |
| other = SiteConfiguration(maintenance_mode=True) | |
| other.save() # save() force pk=1 : pas de deuxième ligne | |
| assert SiteConfiguration.objects.count() == 1 | |
| assert SiteConfiguration.get_solo().maintenance_mode is True | |
| # --------------------------------------------------------------------------- # | |
| # MaintenanceModeMiddleware | |
| # --------------------------------------------------------------------------- # | |
| def test_middleware_off_passthrough(api_client): | |
| _set_maintenance(False) | |
| resp = api_client.get(reverse("api_transparency")) | |
| assert resp.status_code != 503 | |
| def test_middleware_on_blocks_api(api_client): | |
| _set_maintenance(True) | |
| resp = api_client.get(reverse("api_transparency")) | |
| assert resp.status_code == 503 | |
| data = resp.json() | |
| assert data["maintenance"] is True | |
| def test_middleware_on_config_exempt(api_client): | |
| _set_maintenance(True) | |
| resp = api_client.get(reverse("api_config")) | |
| assert resp.status_code == 200 | |
| assert resp.json()["maintenance_mode"] is True | |
| def test_middleware_on_staff_session_bypass(api_client): | |
| _set_maintenance(True) | |
| staff = User.objects.create_user("cfgstaff", password="x", is_staff=True) | |
| api_client.force_login(staff) | |
| resp = api_client.get(reverse("api_transparency")) | |
| assert resp.status_code != 503 | |
| def test_middleware_on_non_staff_user_blocked(api_client): | |
| _set_maintenance(True) | |
| user = User.objects.create_user("cfguser", password="x") | |
| api_client.force_login(user) | |
| resp = api_client.get(reverse("api_transparency")) | |
| assert resp.status_code == 503 | |
| def test_middleware_ignores_non_api_paths(api_client): | |
| _set_maintenance(True) | |
| # Hors /api/ (SPA, statiques, admin) : jamais bloqué par le middleware. | |
| resp = api_client.get("/admin/login/") | |
| assert resp.status_code != 503 | |
| def test_middleware_fails_open_without_database(): | |
| """Base indisponible (tests sans django_db, outage) → passthrough. | |
| Régression CI 2026-07-10 : le middleware interrogeait la base sur chaque | |
| requête /api/, faisant échouer en RuntimeError les tests d'endpoints qui | |
| n'ont pas besoin de la base (billing webhook, eventarc). La maintenance | |
| est un état déclaré, jamais l'effet de bord d'une panne. | |
| """ | |
| from unittest.mock import MagicMock, patch | |
| from animetix.middleware import MaintenanceModeMiddleware | |
| from django.test import RequestFactory | |
| get_response = MagicMock(return_value="ok") | |
| middleware = MaintenanceModeMiddleware(get_response) | |
| request = RequestFactory().get("/api/v1/transparency/") | |
| with patch( | |
| "animetix.models.SiteConfiguration.get_solo", | |
| side_effect=RuntimeError("Database access not allowed"), | |
| ): | |
| result = middleware(request) | |
| assert result == "ok" | |
| get_response.assert_called_once_with(request) | |