Major architecture change to unify frontend detection: ## Problem Solved - Eliminated code duplication across 3 middleware files - Fixed incomplete path detection (now detects /api/v1/admin/*) - Unified on FrontendType enum (deprecates RequestContext) - Added request.state.frontend_type for all requests ## New Components - app/core/frontend_detector.py: Centralized FrontendDetector class - middleware/frontend_type.py: FrontendTypeMiddleware (replaces ContextMiddleware) - docs/architecture/frontend-detection.md: Complete architecture documentation ## Changes - main.py: Use FrontendTypeMiddleware instead of ContextMiddleware - middleware/context.py: Deprecated (kept for backwards compatibility) - middleware/platform_context.py: Use FrontendDetector.is_admin() - middleware/vendor_context.py: Use FrontendDetector.is_admin() - middleware/language.py: Use FrontendType instead of context_value - app/exceptions/handler.py: Use FrontendType.STOREFRONT - app/exceptions/error_renderer.py: Use FrontendType - Customer routes: Cookie path changed from /shop to /storefront ## Documentation - docs/architecture/frontend-detection.md: New comprehensive docs - docs/architecture/middleware.md: Updated for new system - docs/architecture/request-flow.md: Updated for FrontendType - docs/backend/middleware-reference.md: Updated API reference ## Tests - tests/unit/core/test_frontend_detector.py: 37 new tests - tests/unit/middleware/test_frontend_type.py: 11 new tests - tests/unit/middleware/test_context.py: Updated for compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
132 lines
4.8 KiB
Python
132 lines
4.8 KiB
Python
# tests/unit/middleware/test_context.py
|
|
"""
|
|
DEPRECATED: Tests for backward compatibility of middleware.context module.
|
|
|
|
The ContextMiddleware and ContextManager classes have been replaced by:
|
|
- FrontendTypeMiddleware (middleware/frontend_type.py)
|
|
- FrontendDetector (app/core/frontend_detector.py)
|
|
|
|
These tests verify the backward compatibility layer still works for code
|
|
that uses the deprecated RequestContext enum and get_request_context() function.
|
|
|
|
For new tests, see:
|
|
- tests/unit/core/test_frontend_detector.py
|
|
- tests/unit/middleware/test_frontend_type.py
|
|
"""
|
|
|
|
import warnings
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
from fastapi import Request
|
|
|
|
from middleware.context import RequestContext, get_request_context
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestRequestContextEnumBackwardCompatibility:
|
|
"""Test suite for deprecated RequestContext enum."""
|
|
|
|
def test_request_context_values(self):
|
|
"""Test RequestContext enum has correct values."""
|
|
assert RequestContext.API.value == "api"
|
|
assert RequestContext.ADMIN.value == "admin"
|
|
assert RequestContext.VENDOR_DASHBOARD.value == "vendor"
|
|
assert RequestContext.SHOP.value == "shop"
|
|
assert RequestContext.FALLBACK.value == "fallback"
|
|
|
|
def test_request_context_types(self):
|
|
"""Test RequestContext enum values are strings."""
|
|
for context in RequestContext:
|
|
assert isinstance(context.value, str)
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestGetRequestContextBackwardCompatibility:
|
|
"""Test suite for deprecated get_request_context() function."""
|
|
|
|
def test_get_request_context_returns_api_for_api_paths(self):
|
|
"""Test get_request_context returns API for /api/ paths."""
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/api/v1/vendors")
|
|
request.state = Mock()
|
|
request.state.frontend_type = None
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
context = get_request_context(request)
|
|
|
|
assert context == RequestContext.API
|
|
|
|
def test_get_request_context_deprecation_warning(self):
|
|
"""Test get_request_context raises DeprecationWarning."""
|
|
from app.modules.enums import FrontendType
|
|
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/admin/dashboard")
|
|
request.state = Mock()
|
|
request.state.frontend_type = FrontendType.ADMIN
|
|
|
|
with pytest.warns(DeprecationWarning, match="get_request_context.*deprecated"):
|
|
get_request_context(request)
|
|
|
|
def test_get_request_context_maps_admin(self):
|
|
"""Test get_request_context maps FrontendType.ADMIN to RequestContext.ADMIN."""
|
|
from app.modules.enums import FrontendType
|
|
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/admin/dashboard")
|
|
request.state = Mock()
|
|
request.state.frontend_type = FrontendType.ADMIN
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
context = get_request_context(request)
|
|
|
|
assert context == RequestContext.ADMIN
|
|
|
|
def test_get_request_context_maps_vendor(self):
|
|
"""Test get_request_context maps FrontendType.VENDOR to RequestContext.VENDOR_DASHBOARD."""
|
|
from app.modules.enums import FrontendType
|
|
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/vendor/settings")
|
|
request.state = Mock()
|
|
request.state.frontend_type = FrontendType.VENDOR
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
context = get_request_context(request)
|
|
|
|
assert context == RequestContext.VENDOR_DASHBOARD
|
|
|
|
def test_get_request_context_maps_storefront(self):
|
|
"""Test get_request_context maps FrontendType.STOREFRONT to RequestContext.SHOP."""
|
|
from app.modules.enums import FrontendType
|
|
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/storefront/products")
|
|
request.state = Mock()
|
|
request.state.frontend_type = FrontendType.STOREFRONT
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
context = get_request_context(request)
|
|
|
|
assert context == RequestContext.SHOP
|
|
|
|
def test_get_request_context_maps_platform_to_fallback(self):
|
|
"""Test get_request_context maps FrontendType.PLATFORM to RequestContext.FALLBACK."""
|
|
from app.modules.enums import FrontendType
|
|
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path="/pricing")
|
|
request.state = Mock()
|
|
request.state.frontend_type = FrontendType.PLATFORM
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
context = get_request_context(request)
|
|
|
|
assert context == RequestContext.FALLBACK
|