# tests/unit/middleware/test_storefront_gate_bypass.py """ Unit tests for the storefront gate bypass safety net. Ensures that when frontend_type is None (upstream middleware failed), storefront paths are BLOCKED rather than passed through. Non-storefront paths with None frontend_type should pass through unchanged. """ from unittest.mock import AsyncMock, Mock, patch import pytest from fastapi import Request from starlette.responses import JSONResponse from middleware.storefront_access import ( StorefrontAccessMiddleware, _looks_like_storefront, ) @pytest.mark.unit @pytest.mark.middleware class TestLooksLikeStorefront: """Test the _looks_like_storefront helper.""" def test_storefront_page_path(self): assert _looks_like_storefront("/storefront/products") is True def test_storefront_api_path(self): assert _looks_like_storefront("/api/v1/storefront/cart") is True def test_admin_path(self): assert _looks_like_storefront("/admin/dashboard") is False def test_static_path(self): assert _looks_like_storefront("/static/css/style.css") is False def test_store_path(self): assert _looks_like_storefront("/store/ACME/login") is False def test_root_path(self): assert _looks_like_storefront("/") is False @pytest.mark.unit @pytest.mark.middleware class TestStorefrontGateBypass: """Test that None frontend_type can't bypass the storefront gate.""" @pytest.mark.asyncio async def test_none_frontend_type_storefront_page_blocked(self): """frontend_type=None + /storefront/ path → blocked with HTML 403.""" middleware = StorefrontAccessMiddleware(app=None) request = Mock(spec=Request) request.url = Mock(path="/storefront/products") request.state = Mock() request.state.frontend_type = None request.state.store = None request.state.language = "en" request.state.theme = None call_next = AsyncMock() with patch("app.templates_config.templates") as mock_templates: mock_templates.TemplateResponse.return_value = Mock(status_code=403) await middleware.dispatch(request, call_next) call_next.assert_not_called() @pytest.mark.asyncio async def test_none_frontend_type_storefront_api_blocked(self): """frontend_type=None + /api/v1/storefront/ path → JSON 403.""" middleware = StorefrontAccessMiddleware(app=None) request = Mock(spec=Request) request.url = Mock(path="/api/v1/storefront/cart") request.state = Mock() request.state.frontend_type = None call_next = AsyncMock() response = await middleware.dispatch(request, call_next) call_next.assert_not_called() assert isinstance(response, JSONResponse) assert response.status_code == 403 @pytest.mark.asyncio async def test_none_frontend_type_admin_passes_through(self): """frontend_type=None + /admin/ path → passes through (not storefront).""" middleware = StorefrontAccessMiddleware(app=None) request = Mock(spec=Request) request.url = Mock(path="/admin/dashboard") request.state = Mock() request.state.frontend_type = None call_next = AsyncMock(return_value=Mock()) await middleware.dispatch(request, call_next) call_next.assert_called_once_with(request) @pytest.mark.asyncio async def test_none_frontend_type_static_passes_through(self): """frontend_type=None + /static/ path → passes through.""" middleware = StorefrontAccessMiddleware(app=None) request = Mock(spec=Request) request.url = Mock(path="/static/css/style.css") request.state = Mock() request.state.frontend_type = None call_next = AsyncMock(return_value=Mock()) await middleware.dispatch(request, call_next) call_next.assert_called_once_with(request) @pytest.mark.asyncio async def test_none_frontend_type_root_passes_through(self): """frontend_type=None + / path → passes through.""" middleware = StorefrontAccessMiddleware(app=None) request = Mock(spec=Request) request.url = Mock(path="/") request.state = Mock() request.state.frontend_type = None call_next = AsyncMock(return_value=Mock()) await middleware.dispatch(request, call_next) call_next.assert_called_once_with(request)