animetix-web / tests /api /test_app_config.py
MissawB's picture
Upload folder using huggingface_hub (part 5)
a7a6a87 verified
Raw
History Blame Contribute Delete
4.65 kB
"""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
@pytest.fixture
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/
# --------------------------------------------------------------------------- #
@pytest.mark.django_db
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"]
@pytest.mark.django_db
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"
@pytest.mark.django_db
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
# --------------------------------------------------------------------------- #
@pytest.mark.django_db
def test_middleware_off_passthrough(api_client):
_set_maintenance(False)
resp = api_client.get(reverse("api_transparency"))
assert resp.status_code != 503
@pytest.mark.django_db
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
@pytest.mark.django_db
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
@pytest.mark.django_db
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
@pytest.mark.django_db
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
@pytest.mark.django_db
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)