refactor: remove legacy /shop and /api/v1/shop dead code
After the storefront migration, no live routes mount under /api/v1/shop/. Remove all dead code that detected/handled shop API requests: the is_shop_api_request() method, the shop API dispatch branch in middleware, the RequestContext.SHOP enum member (renamed to STOREFRONT), legacy path prefixes in FrontendDetector, and all associated tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@ from main import app
|
||||
from tests.integration.middleware.middleware_test_routes import (
|
||||
admin_router,
|
||||
api_router,
|
||||
shop_router,
|
||||
storefront_router,
|
||||
store_router,
|
||||
)
|
||||
from tests.integration.middleware.middleware_test_routes import (
|
||||
@@ -39,7 +39,7 @@ if not any(r.path.startswith("/middleware-test") for r in app.routes if hasattr(
|
||||
app.include_router(api_router)
|
||||
app.include_router(admin_router)
|
||||
app.include_router(store_router)
|
||||
app.include_router(shop_router)
|
||||
app.include_router(storefront_router)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -10,7 +10,7 @@ IMPORTANT: Routes are organized by prefix to avoid conflicts:
|
||||
- /api/middleware-test/* - API context testing
|
||||
- /admin/middleware-test/* - Admin context testing
|
||||
- /store/middleware-test/* - Store dashboard context testing
|
||||
- /shop/middleware-test/* - Shop context testing
|
||||
- /storefront/middleware-test/* - Storefront context testing
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
@@ -531,15 +531,15 @@ async def test_store_dashboard_theme(request: Request):
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Shop Context Test Router
|
||||
# Storefront Context Test Router
|
||||
# =============================================================================
|
||||
|
||||
shop_router = APIRouter(prefix="/shop/middleware-test")
|
||||
storefront_router = APIRouter(prefix="/storefront/middleware-test")
|
||||
|
||||
|
||||
@shop_router.get("/context")
|
||||
async def test_shop_context(request: Request):
|
||||
"""Test shop context detection."""
|
||||
@storefront_router.get("/context")
|
||||
async def test_storefront_context(request: Request):
|
||||
"""Test storefront context detection."""
|
||||
context_type = getattr(request.state, "context_type", None)
|
||||
store = getattr(request.state, "store", None)
|
||||
theme = getattr(request.state, "theme", None)
|
||||
@@ -552,9 +552,9 @@ async def test_shop_context(request: Request):
|
||||
}
|
||||
|
||||
|
||||
@shop_router.get("/custom-domain-context")
|
||||
async def test_shop_custom_domain_context(request: Request):
|
||||
"""Test shop context with custom domain."""
|
||||
@storefront_router.get("/custom-domain-context")
|
||||
async def test_storefront_custom_domain_context(request: Request):
|
||||
"""Test storefront context with custom domain."""
|
||||
context_type = getattr(request.state, "context_type", None)
|
||||
store = getattr(request.state, "store", None)
|
||||
return {
|
||||
@@ -564,9 +564,9 @@ async def test_shop_custom_domain_context(request: Request):
|
||||
}
|
||||
|
||||
|
||||
@shop_router.get("/theme")
|
||||
async def test_shop_theme(request: Request):
|
||||
"""Test theme in shop context."""
|
||||
@storefront_router.get("/theme")
|
||||
async def test_storefront_theme(request: Request):
|
||||
"""Test theme in storefront context."""
|
||||
context_type = getattr(request.state, "context_type", None)
|
||||
theme = getattr(request.state, "theme", None)
|
||||
colors = theme.get("colors", {}) if theme else {}
|
||||
|
||||
@@ -7,7 +7,6 @@ Tests cover:
|
||||
- Path-based detection (dev mode)
|
||||
- Subdomain-based detection (prod mode)
|
||||
- Custom domain detection
|
||||
- Legacy /shop/ path support
|
||||
- Priority order of detection methods
|
||||
"""
|
||||
|
||||
@@ -103,15 +102,6 @@ class TestFrontendDetectorStorefront:
|
||||
)
|
||||
assert result == FrontendType.STOREFRONT
|
||||
|
||||
def test_detect_storefront_legacy_shop_path(self):
|
||||
"""Test storefront detection from legacy /shop path."""
|
||||
result = FrontendDetector.detect(host="localhost", path="/shop/products")
|
||||
assert result == FrontendType.STOREFRONT
|
||||
|
||||
def test_detect_storefront_legacy_shop_api_path(self):
|
||||
"""Test storefront detection from legacy /api/v1/shop path."""
|
||||
result = FrontendDetector.detect(host="localhost", path="/api/v1/shop/cart")
|
||||
assert result == FrontendType.STOREFRONT
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
|
||||
@@ -32,7 +32,7 @@ class TestRequestContextEnumBackwardCompatibility:
|
||||
assert RequestContext.API.value == "api"
|
||||
assert RequestContext.ADMIN.value == "admin"
|
||||
assert RequestContext.STORE_DASHBOARD.value == "store"
|
||||
assert RequestContext.SHOP.value == "shop"
|
||||
assert RequestContext.STOREFRONT.value == "storefront"
|
||||
assert RequestContext.FALLBACK.value == "fallback"
|
||||
|
||||
def test_request_context_types(self):
|
||||
@@ -101,7 +101,7 @@ class TestGetRequestContextBackwardCompatibility:
|
||||
assert context == RequestContext.STORE_DASHBOARD
|
||||
|
||||
def test_get_request_context_maps_storefront(self):
|
||||
"""Test get_request_context maps FrontendType.STOREFRONT to RequestContext.SHOP."""
|
||||
"""Test get_request_context maps FrontendType.STOREFRONT to RequestContext.STOREFRONT."""
|
||||
from app.modules.enums import FrontendType
|
||||
|
||||
request = Mock(spec=Request)
|
||||
@@ -113,7 +113,7 @@ class TestGetRequestContextBackwardCompatibility:
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
context = get_request_context(request)
|
||||
|
||||
assert context == RequestContext.SHOP
|
||||
assert context == RequestContext.STOREFRONT
|
||||
|
||||
def test_get_request_context_maps_platform_to_fallback(self):
|
||||
"""Test get_request_context maps FrontendType.PLATFORM to RequestContext.FALLBACK."""
|
||||
|
||||
@@ -102,10 +102,10 @@ class TestStoreContextManager:
|
||||
"""Test path-based detection with /store/ prefix."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "localhost"}
|
||||
request.url = Mock(path="/store/store1/shop")
|
||||
request.url = Mock(path="/store/store1/storefront")
|
||||
# Set platform_clean_path to simulate PlatformContextMiddleware output
|
||||
request.state = Mock()
|
||||
request.state.platform_clean_path = "/store/store1/shop"
|
||||
request.state.platform_clean_path = "/store/store1/storefront"
|
||||
|
||||
context = StoreContextManager.detect_store_context(request)
|
||||
|
||||
@@ -119,10 +119,10 @@ class TestStoreContextManager:
|
||||
"""Test path-based detection with /stores/ prefix."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "localhost"}
|
||||
request.url = Mock(path="/stores/store1/shop")
|
||||
request.url = Mock(path="/stores/store1/storefront")
|
||||
# Set platform_clean_path to simulate PlatformContextMiddleware output
|
||||
request.state = Mock()
|
||||
request.state.platform_clean_path = "/stores/store1/shop"
|
||||
request.state.platform_clean_path = "/stores/store1/storefront"
|
||||
|
||||
context = StoreContextManager.detect_store_context(request)
|
||||
|
||||
@@ -310,24 +310,24 @@ class TestStoreContextManager:
|
||||
def test_extract_clean_path_from_store_path(self):
|
||||
"""Test extracting clean path from /store/ prefix."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/store/store1/shop/products")
|
||||
request.url = Mock(path="/store/store1/storefront/products")
|
||||
|
||||
store_context = {"detection_method": "path", "path_prefix": "/store/store1"}
|
||||
|
||||
clean_path = StoreContextManager.extract_clean_path(request, store_context)
|
||||
|
||||
assert clean_path == "/shop/products"
|
||||
assert clean_path == "/storefront/products"
|
||||
|
||||
def test_extract_clean_path_from_stores_path(self):
|
||||
"""Test extracting clean path from /stores/ prefix."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/stores/store1/shop/products")
|
||||
request.url = Mock(path="/stores/store1/storefront/products")
|
||||
|
||||
store_context = {"detection_method": "path", "path_prefix": "/stores/store1"}
|
||||
|
||||
clean_path = StoreContextManager.extract_clean_path(request, store_context)
|
||||
|
||||
assert clean_path == "/shop/products"
|
||||
assert clean_path == "/storefront/products"
|
||||
|
||||
def test_extract_clean_path_root(self):
|
||||
"""Test extracting clean path when result is empty (should return /)."""
|
||||
@@ -343,22 +343,22 @@ class TestStoreContextManager:
|
||||
def test_extract_clean_path_no_path_context(self):
|
||||
"""Test extracting clean path for non-path detection methods."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/shop/products")
|
||||
request.url = Mock(path="/storefront/products")
|
||||
|
||||
store_context = {"detection_method": "subdomain", "subdomain": "store1"}
|
||||
|
||||
clean_path = StoreContextManager.extract_clean_path(request, store_context)
|
||||
|
||||
assert clean_path == "/shop/products"
|
||||
assert clean_path == "/storefront/products"
|
||||
|
||||
def test_extract_clean_path_no_context(self):
|
||||
"""Test extracting clean path with no store context."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/shop/products")
|
||||
request.url = Mock(path="/storefront/products")
|
||||
|
||||
clean_path = StoreContextManager.extract_clean_path(request, None)
|
||||
|
||||
assert clean_path == "/shop/products"
|
||||
assert clean_path == "/storefront/products"
|
||||
|
||||
# ========================================================================
|
||||
# Request Type Detection Tests
|
||||
@@ -392,7 +392,7 @@ class TestStoreContextManager:
|
||||
"""Test non-admin request."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "store1.platform.com"}
|
||||
request.url = Mock(path="/shop")
|
||||
request.url = Mock(path="/storefront")
|
||||
|
||||
assert StoreContextManager.is_admin_request(request) is False
|
||||
|
||||
@@ -406,49 +406,10 @@ class TestStoreContextManager:
|
||||
def test_is_not_api_request(self):
|
||||
"""Test non-API request."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/shop/products")
|
||||
request.url = Mock(path="/storefront/products")
|
||||
|
||||
assert StoreContextManager.is_api_request(request) is False
|
||||
|
||||
# ========================================================================
|
||||
# Shop API Request Detection Tests
|
||||
# ========================================================================
|
||||
|
||||
def test_is_shop_api_request(self):
|
||||
"""Test shop API request detection."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/api/v1/shop/products")
|
||||
|
||||
assert StoreContextManager.is_shop_api_request(request) is True
|
||||
|
||||
def test_is_shop_api_request_cart(self):
|
||||
"""Test shop API request detection for cart endpoint."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/api/v1/shop/cart")
|
||||
|
||||
assert StoreContextManager.is_shop_api_request(request) is True
|
||||
|
||||
def test_is_not_shop_api_request_admin(self):
|
||||
"""Test non-shop API request (admin API)."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/api/v1/admin/stores")
|
||||
|
||||
assert StoreContextManager.is_shop_api_request(request) is False
|
||||
|
||||
def test_is_not_shop_api_request_store(self):
|
||||
"""Test non-shop API request (store API)."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/api/v1/store/products")
|
||||
|
||||
assert StoreContextManager.is_shop_api_request(request) is False
|
||||
|
||||
def test_is_not_shop_api_request_non_api(self):
|
||||
"""Test non-shop API request (non-API path)."""
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/shop/products")
|
||||
|
||||
assert StoreContextManager.is_shop_api_request(request) is False
|
||||
|
||||
# ========================================================================
|
||||
# Extract Store From Referer Tests
|
||||
# ========================================================================
|
||||
@@ -457,7 +418,7 @@ class TestStoreContextManager:
|
||||
"""Test extracting store from referer with /stores/ path."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {
|
||||
"referer": "http://localhost:8000/stores/wizamart/shop/products"
|
||||
"referer": "http://localhost:8000/stores/wizamart/storefront/products"
|
||||
}
|
||||
|
||||
context = StoreContextManager.extract_store_from_referer(request)
|
||||
@@ -472,7 +433,7 @@ class TestStoreContextManager:
|
||||
"""Test extracting store from referer with /store/ path."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {
|
||||
"referer": "http://localhost:8000/store/myshop/shop/products"
|
||||
"referer": "http://localhost:8000/store/myshop/storefront/products"
|
||||
}
|
||||
|
||||
context = StoreContextManager.extract_store_from_referer(request)
|
||||
@@ -486,7 +447,7 @@ class TestStoreContextManager:
|
||||
def test_extract_store_from_referer_subdomain(self):
|
||||
"""Test extracting store from referer with subdomain."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"referer": "http://wizamart.platform.com/shop/products"}
|
||||
request.headers = {"referer": "http://wizamart.platform.com/storefront/products"}
|
||||
|
||||
with patch("middleware.store_context.settings") as mock_settings:
|
||||
mock_settings.platform_domain = "platform.com"
|
||||
@@ -501,7 +462,7 @@ class TestStoreContextManager:
|
||||
def test_extract_store_from_referer_custom_domain(self):
|
||||
"""Test extracting store from referer with custom domain."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"referer": "http://my-custom-shop.com/shop/products"}
|
||||
request.headers = {"referer": "http://my-custom-shop.com/storefront/products"}
|
||||
|
||||
with patch("middleware.store_context.settings") as mock_settings:
|
||||
mock_settings.platform_domain = "platform.com"
|
||||
@@ -525,7 +486,7 @@ class TestStoreContextManager:
|
||||
def test_extract_store_from_referer_origin_header(self):
|
||||
"""Test extracting store from origin header when referer is missing."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"origin": "http://localhost:8000/stores/testshop/shop"}
|
||||
request.headers = {"origin": "http://localhost:8000/stores/testshop/storefront"}
|
||||
|
||||
context = StoreContextManager.extract_store_from_referer(request)
|
||||
|
||||
@@ -548,7 +509,7 @@ class TestStoreContextManager:
|
||||
def test_extract_store_from_referer_ignores_www_subdomain(self):
|
||||
"""Test that www subdomain is not extracted from referer."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"referer": "http://www.platform.com/shop"}
|
||||
request.headers = {"referer": "http://www.platform.com/storefront"}
|
||||
|
||||
with patch("middleware.store_context.settings") as mock_settings:
|
||||
mock_settings.platform_domain = "platform.com"
|
||||
@@ -560,7 +521,7 @@ class TestStoreContextManager:
|
||||
def test_extract_store_from_referer_localhost_not_custom_domain(self):
|
||||
"""Test that localhost is not treated as custom domain."""
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"referer": "http://localhost:8000/shop"}
|
||||
request.headers = {"referer": "http://localhost:8000/storefront"}
|
||||
|
||||
with patch("middleware.store_context.settings") as mock_settings:
|
||||
mock_settings.platform_domain = "platform.com"
|
||||
@@ -601,7 +562,7 @@ class TestStoreContextManager:
|
||||
@pytest.mark.parametrize(
|
||||
"path",
|
||||
[
|
||||
"/shop/products",
|
||||
"/storefront/products",
|
||||
"/admin/dashboard",
|
||||
"/api/stores",
|
||||
"/about",
|
||||
@@ -686,7 +647,7 @@ class TestStoreContextMiddleware:
|
||||
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "store1.platform.com"}
|
||||
request.url = Mock(path="/shop/products")
|
||||
request.url = Mock(path="/storefront/products")
|
||||
request.state = Mock()
|
||||
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
@@ -714,7 +675,7 @@ class TestStoreContextMiddleware:
|
||||
patch.object(
|
||||
StoreContextManager,
|
||||
"extract_clean_path",
|
||||
return_value="/shop/products",
|
||||
return_value="/storefront/products",
|
||||
),
|
||||
patch("middleware.store_context.get_db", return_value=iter([mock_db])),
|
||||
):
|
||||
@@ -722,7 +683,7 @@ class TestStoreContextMiddleware:
|
||||
|
||||
assert request.state.store is mock_store
|
||||
assert request.state.store_context == store_context
|
||||
assert request.state.clean_path == "/shop/products"
|
||||
assert request.state.clean_path == "/storefront/products"
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -732,7 +693,7 @@ class TestStoreContextMiddleware:
|
||||
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "nonexistent.platform.com"}
|
||||
request.url = Mock(path="/shop")
|
||||
request.url = Mock(path="/storefront")
|
||||
request.state = Mock()
|
||||
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
@@ -756,7 +717,7 @@ class TestStoreContextMiddleware:
|
||||
|
||||
assert request.state.store is None
|
||||
assert request.state.store_context == store_context
|
||||
assert request.state.clean_path == "/shop"
|
||||
assert request.state.clean_path == "/storefront"
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -820,146 +781,6 @@ class TestStoreContextMiddleware:
|
||||
assert request.state.clean_path == path
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
# ========================================================================
|
||||
# Shop API Request Handling Tests
|
||||
# ========================================================================
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_middleware_shop_api_with_referer_store_found(self):
|
||||
"""Test middleware handles shop API request with store from Referer."""
|
||||
middleware = StoreContextMiddleware(app=None)
|
||||
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {
|
||||
"host": "localhost",
|
||||
"referer": "http://localhost:8000/stores/wizamart/shop/products",
|
||||
}
|
||||
request.url = Mock(path="/api/v1/shop/cart")
|
||||
request.state = Mock()
|
||||
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
mock_store = Mock()
|
||||
mock_store.id = 1
|
||||
mock_store.name = "Wizamart"
|
||||
mock_store.subdomain = "wizamart"
|
||||
|
||||
store_context = {
|
||||
"subdomain": "wizamart",
|
||||
"detection_method": "path",
|
||||
"path_prefix": "/stores/wizamart",
|
||||
"full_prefix": "/stores/",
|
||||
}
|
||||
|
||||
mock_db = MagicMock()
|
||||
|
||||
with (
|
||||
patch.object(StoreContextManager, "is_admin_request", return_value=False),
|
||||
patch.object(
|
||||
StoreContextManager, "is_static_file_request", return_value=False
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager, "is_shop_api_request", return_value=True
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager,
|
||||
"extract_store_from_referer",
|
||||
return_value=store_context,
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager,
|
||||
"get_store_from_context",
|
||||
return_value=mock_store,
|
||||
),
|
||||
patch("middleware.store_context.get_db", return_value=iter([mock_db])),
|
||||
):
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
assert request.state.store is mock_store
|
||||
assert request.state.store_context == store_context
|
||||
assert request.state.clean_path == "/api/v1/shop/cart"
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_middleware_shop_api_with_referer_store_not_found(self):
|
||||
"""Test middleware handles shop API when store from Referer not in database."""
|
||||
middleware = StoreContextMiddleware(app=None)
|
||||
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {
|
||||
"host": "localhost",
|
||||
"referer": "http://localhost:8000/stores/nonexistent/shop/products",
|
||||
}
|
||||
request.url = Mock(path="/api/v1/shop/cart")
|
||||
request.state = Mock()
|
||||
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
store_context = {
|
||||
"subdomain": "nonexistent",
|
||||
"detection_method": "path",
|
||||
"path_prefix": "/stores/nonexistent",
|
||||
"full_prefix": "/stores/",
|
||||
}
|
||||
|
||||
mock_db = MagicMock()
|
||||
|
||||
with (
|
||||
patch.object(StoreContextManager, "is_admin_request", return_value=False),
|
||||
patch.object(
|
||||
StoreContextManager, "is_static_file_request", return_value=False
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager, "is_shop_api_request", return_value=True
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager,
|
||||
"extract_store_from_referer",
|
||||
return_value=store_context,
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager, "get_store_from_context", return_value=None
|
||||
),
|
||||
patch("middleware.store_context.get_db", return_value=iter([mock_db])),
|
||||
):
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
assert request.state.store is None
|
||||
assert request.state.store_context == store_context
|
||||
assert request.state.clean_path == "/api/v1/shop/cart"
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_middleware_shop_api_without_referer(self):
|
||||
"""Test middleware handles shop API request without Referer header."""
|
||||
middleware = StoreContextMiddleware(app=None)
|
||||
|
||||
request = Mock(spec=Request)
|
||||
request.headers = {"host": "localhost"}
|
||||
request.url = Mock(path="/api/v1/shop/products")
|
||||
request.state = Mock()
|
||||
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
with (
|
||||
patch.object(StoreContextManager, "is_admin_request", return_value=False),
|
||||
patch.object(
|
||||
StoreContextManager, "is_static_file_request", return_value=False
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager, "is_shop_api_request", return_value=True
|
||||
),
|
||||
patch.object(
|
||||
StoreContextManager, "extract_store_from_referer", return_value=None
|
||||
),
|
||||
):
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
assert request.state.store is None
|
||||
assert request.state.store_context is None
|
||||
assert request.state.clean_path == "/api/v1/shop/products"
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.stores
|
||||
|
||||
Reference in New Issue
Block a user