from unittest.mock import Mock, patch import pytest from django.http import HttpResponse from django.test import RequestFactory from apps.core.middleware import MigrationMaintenanceMiddleware @pytest.mark.parametrize("method,path,allowed", [ ("GET", "/health/ready/", True), ("HEAD", "/health/live/", True), ("POST", "/health/ready/", False), ("GET", "/health/ready", False), ("GET", "/", False), ("POST", "/accounts/login/", False), ("OPTIONS", "/health/live/", False), ]) def test_held_candidate_only_allows_exact_safe_health(method, path, allowed): downstream = Mock(return_value=HttpResponse("ok")) with patch("apps.core.middleware.hold_active", return_value=True): response = MigrationMaintenanceMiddleware(downstream)( RequestFactory().generic(method, path) ) assert response.status_code == (200 if allowed else 503) assert downstream.called is allowed if not allowed: assert response["Cache-Control"] == "no-store" @pytest.mark.parametrize("failure", [PermissionError(), RuntimeError()]) def test_marker_errors_block_ordinary_traffic(failure): downstream = Mock() with patch("apps.core.middleware.hold_active", side_effect=failure): response = MigrationMaintenanceMiddleware(downstream)(RequestFactory().get("/")) assert response.status_code == 503 downstream.assert_not_called() def test_normal_runtime_unchanged_and_middleware_is_first(settings): assert settings.MIDDLEWARE[0] == "apps.core.middleware.MigrationMaintenanceMiddleware" downstream = Mock(return_value=HttpResponse("ok")) with patch("apps.core.middleware.hold_active", return_value=False): response = MigrationMaintenanceMiddleware(downstream)(RequestFactory().post("/")) assert response.status_code == 200