- Extract store/platform context from Referer header for storefront API requests
(StoreContextMiddleware and PlatformContextMiddleware) so login POST works in
dev mode where API paths lack /platforms/{code}/ prefix
- Set customer token cookie path to "/" for cross-route compatibility
- Fix double storefront in URLs: replace {{ base_url }}storefront/ with {{ base_url }}
across all 24 storefront templates
- Fix auth error redirect to include platform prefix and use store_code
- Update seed script to output correct storefront login URLs
- Add 20 new unit tests covering all fixes; fix 9 pre-existing test failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
147 lines
4.8 KiB
Python
147 lines
4.8 KiB
Python
# tests/unit/utils/test_page_context.py
|
|
"""
|
|
Unit tests for page context utilities.
|
|
|
|
Tests cover:
|
|
- base_url calculation for storefront pages
|
|
- Dev mode (path-based) with platform prefix
|
|
- Prod mode (subdomain/custom domain)
|
|
- Ensures no double 'storefront/' in URLs
|
|
"""
|
|
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
from fastapi import Request
|
|
|
|
from app.modules.core.utils.page_context import get_storefront_context
|
|
|
|
|
|
def _make_storefront_request(
|
|
path="/storefront/TESTSHOP/products",
|
|
store=None,
|
|
store_context=None,
|
|
platform=None,
|
|
platform_original_path=None,
|
|
theme=None,
|
|
clean_path="/products",
|
|
language="en",
|
|
):
|
|
"""Create a mock request with storefront state."""
|
|
request = Mock(spec=Request)
|
|
request.url = Mock(path=path)
|
|
request.method = "GET"
|
|
request.headers = {"host": "localhost:8000"}
|
|
request.state = Mock()
|
|
request.state.store = store
|
|
request.state.store_context = store_context
|
|
request.state.clean_path = clean_path
|
|
request.state.platform = platform
|
|
request.state.platform_original_path = platform_original_path
|
|
request.state.theme = theme
|
|
request.state.language = language
|
|
request.state.subscription = None
|
|
request.state.subscription_tier = None
|
|
request.state.frontend_type = None
|
|
return request
|
|
|
|
|
|
def _make_store(store_code="TESTSHOP", subdomain="testshop"):
|
|
store = Mock()
|
|
store.store_code = store_code
|
|
store.subdomain = subdomain
|
|
store.id = 1
|
|
store.name = "Test Shop"
|
|
store.merchant_id = 1
|
|
return store
|
|
|
|
|
|
def _make_platform(code="loyalty", platform_id=3):
|
|
platform = Mock()
|
|
platform.code = code
|
|
platform.id = platform_id
|
|
return platform
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestBaseUrlCalculation:
|
|
"""Tests for base_url in storefront context -- prevents double 'storefront/' regression."""
|
|
|
|
def test_base_url_dev_mode_with_platform_prefix(self):
|
|
"""Dev mode: base_url includes /platforms/{code}/storefront/{store_code}/."""
|
|
store = _make_store(store_code="FASHIONHUB")
|
|
platform = _make_platform(code="loyalty")
|
|
store_context = {"detection_method": "path", "full_prefix": "/storefront/"}
|
|
|
|
request = _make_storefront_request(
|
|
store=store,
|
|
store_context=store_context,
|
|
platform=platform,
|
|
platform_original_path="/platforms/loyalty/storefront/FASHIONHUB/products",
|
|
)
|
|
|
|
# Mock the module-level context building to avoid DB calls
|
|
# We only need to test the base_url logic, so patch what's needed
|
|
context = get_storefront_context(request)
|
|
|
|
assert context["base_url"] == "/platforms/loyalty/storefront/FASHIONHUB/"
|
|
# Verify no double storefront when building links
|
|
assert "/storefront/storefront/" not in context["base_url"]
|
|
|
|
def test_base_url_dev_mode_without_platform_prefix(self):
|
|
"""Dev mode without /platforms/ prefix: base_url = /storefront/{store_code}/."""
|
|
store = _make_store(store_code="TESTSHOP")
|
|
store_context = {"detection_method": "path", "full_prefix": "/storefront/"}
|
|
|
|
request = _make_storefront_request(
|
|
store=store,
|
|
store_context=store_context,
|
|
platform=None,
|
|
platform_original_path=None,
|
|
)
|
|
|
|
context = get_storefront_context(request)
|
|
|
|
assert context["base_url"] == "/storefront/TESTSHOP/"
|
|
assert "/storefront/storefront/" not in context["base_url"]
|
|
|
|
def test_base_url_prod_mode_subdomain(self):
|
|
"""Prod mode with subdomain: base_url = /."""
|
|
store = _make_store()
|
|
store_context = {"detection_method": "subdomain", "subdomain": "testshop"}
|
|
|
|
request = _make_storefront_request(
|
|
store=store,
|
|
store_context=store_context,
|
|
)
|
|
|
|
context = get_storefront_context(request)
|
|
|
|
assert context["base_url"] == "/"
|
|
|
|
def test_base_url_no_store_context(self):
|
|
"""No store context: base_url = /."""
|
|
request = _make_storefront_request(store=None, store_context=None)
|
|
|
|
context = get_storefront_context(request)
|
|
|
|
assert context["base_url"] == "/"
|
|
|
|
def test_base_url_uses_store_code_not_subdomain(self):
|
|
"""base_url should use store_code (uppercase) not subdomain (lowercase)."""
|
|
store = _make_store(store_code="FASHIONHUB", subdomain="fashionhub")
|
|
platform = _make_platform(code="loyalty")
|
|
store_context = {"detection_method": "path", "full_prefix": "/storefront/"}
|
|
|
|
request = _make_storefront_request(
|
|
store=store,
|
|
store_context=store_context,
|
|
platform=platform,
|
|
platform_original_path="/platforms/loyalty/storefront/FASHIONHUB/products",
|
|
)
|
|
|
|
context = get_storefront_context(request)
|
|
|
|
assert "FASHIONHUB" in context["base_url"]
|
|
assert "fashionhub" not in context["base_url"]
|