# tests/integration/middleware/test_vendor_context_flow.py """ Integration tests for vendor context detection end-to-end flow. These tests verify that vendor detection works correctly through real HTTP requests for all routing modes: subdomain, custom domain, and path-based. """ from unittest.mock import patch import pytest @pytest.mark.integration @pytest.mark.middleware @pytest.mark.vendor class TestVendorContextFlow: """Test vendor context detection through real HTTP requests.""" # ======================================================================== # Subdomain Detection Tests # ======================================================================== def test_subdomain_vendor_detection(self, client, vendor_with_subdomain): """Test vendor detection via subdomain routing.""" from fastapi import Request from main import app @app.get("/test-subdomain-detection") async def test_subdomain(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_id": ( request.state.vendor_id if hasattr(request.state, "vendor_id") else None ), "vendor_code": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), "vendor_name": ( request.state.vendor.name if hasattr(request.state, "vendor") and request.state.vendor else None ), "detection_method": "subdomain", } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-subdomain-detection", headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"}, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is True assert data["vendor_id"] == vendor_with_subdomain.id assert data["vendor_code"] == vendor_with_subdomain.vendor_code assert data["vendor_name"] == vendor_with_subdomain.name def test_subdomain_with_port_detection(self, client, vendor_with_subdomain): """Test vendor detection via subdomain with port number.""" from fastapi import Request from main import app @app.get("/test-subdomain-port") async def test_subdomain_port(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_code": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-subdomain-port", headers={ "host": f"{vendor_with_subdomain.subdomain}.platform.com:8000" }, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is True assert data["vendor_code"] == vendor_with_subdomain.vendor_code def test_nonexistent_subdomain_returns_no_vendor(self, client): """Test that nonexistent subdomain doesn't crash and returns no vendor.""" from fastapi import Request from main import app @app.get("/test-nonexistent-subdomain") async def test_nonexistent(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor": ( request.state.vendor if hasattr(request.state, "vendor") else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-nonexistent-subdomain", headers={"host": "nonexistent.platform.com"}, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is False # ======================================================================== # Custom Domain Detection Tests # ======================================================================== def test_custom_domain_vendor_detection(self, client, vendor_with_custom_domain): """Test vendor detection via custom domain.""" from fastapi import Request from main import app @app.get("/test-custom-domain") async def test_custom_domain(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_id": ( request.state.vendor_id if hasattr(request.state, "vendor_id") else None ), "vendor_code": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), "detection_method": "custom_domain", } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-custom-domain", headers={"host": "customdomain.com"} ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is True assert data["vendor_id"] == vendor_with_custom_domain.id assert data["vendor_code"] == vendor_with_custom_domain.vendor_code def test_custom_domain_with_www_detection(self, client, vendor_with_custom_domain): """Test vendor detection via custom domain with www prefix.""" from fastapi import Request from main import app @app.get("/test-custom-domain-www") async def test_custom_domain_www(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_code": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" # Test with www prefix - should still detect vendor response = client.get( "/test-custom-domain-www", headers={"host": "www.customdomain.com"} ) # This might fail if your implementation doesn't strip www # Adjust assertion based on your actual behavior assert response.status_code == 200 # ======================================================================== # Path-Based Detection Tests (Development Mode) # ======================================================================== def test_path_based_vendor_detection_vendors_prefix( self, client, vendor_with_subdomain ): """Test vendor detection via path-based routing with /vendors/ prefix.""" from fastapi import Request from main import app @app.get("/vendors/{vendor_code}/test-path") async def test_path_based(vendor_code: str, request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_code_param": vendor_code, "vendor_code_state": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), "clean_path": ( request.state.clean_path if hasattr(request.state, "clean_path") else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( f"/vendors/{vendor_with_subdomain.vendor_code}/test-path", headers={"host": "localhost:8000"}, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is True assert data["vendor_code_param"] == vendor_with_subdomain.vendor_code assert data["vendor_code_state"] == vendor_with_subdomain.vendor_code def test_path_based_vendor_detection_vendor_prefix( self, client, vendor_with_subdomain ): """Test vendor detection via path-based routing with /vendor/ prefix.""" from fastapi import Request from main import app @app.get("/vendor/{vendor_code}/test") async def test_vendor_path(vendor_code: str, request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None, "vendor_code": ( request.state.vendor.vendor_code if hasattr(request.state, "vendor") and request.state.vendor else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( f"/vendor/{vendor_with_subdomain.vendor_code}/test", headers={"host": "localhost:8000"}, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is True assert data["vendor_code"] == vendor_with_subdomain.vendor_code # ======================================================================== # Clean Path Extraction Tests # ======================================================================== def test_clean_path_extracted_from_vendor_prefix( self, client, vendor_with_subdomain ): """Test that clean_path is correctly extracted from path-based routing.""" from fastapi import Request from main import app @app.get("/vendors/{vendor_code}/shop/products") async def test_clean_path(vendor_code: str, request: Request): return { "clean_path": ( request.state.clean_path if hasattr(request.state, "clean_path") else None ), "original_path": request.url.path, } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( f"/vendors/{vendor_with_subdomain.vendor_code}/shop/products", headers={"host": "localhost:8000"}, ) assert response.status_code == 200 data = response.json() # Clean path should have vendor prefix removed assert data["clean_path"] == "/shop/products" assert ( f"/vendors/{vendor_with_subdomain.vendor_code}/shop/products" in data["original_path"] ) def test_clean_path_unchanged_for_subdomain(self, client, vendor_with_subdomain): """Test that clean_path equals original path for subdomain routing.""" from fastapi import Request from main import app @app.get("/shop/test-clean-path") async def test_subdomain_clean_path(request: Request): return { "clean_path": ( request.state.clean_path if hasattr(request.state, "clean_path") else None ), "original_path": request.url.path, } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/shop/test-clean-path", headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"}, ) assert response.status_code == 200 data = response.json() # For subdomain routing, clean path should equal original path assert data["clean_path"] == data["original_path"] assert data["clean_path"] == "/shop/test-clean-path" # ======================================================================== # Vendor State Injection Tests # ======================================================================== def test_vendor_id_injected_into_request_state(self, client, vendor_with_subdomain): """Test that vendor_id is correctly injected into request.state.""" from fastapi import Request from main import app @app.get("/test-vendor-id-injection") async def test_vendor_id(request: Request): return { "has_vendor_id": hasattr(request.state, "vendor_id"), "vendor_id": ( request.state.vendor_id if hasattr(request.state, "vendor_id") else None ), "vendor_id_type": ( type(request.state.vendor_id).__name__ if hasattr(request.state, "vendor_id") else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-vendor-id-injection", headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"}, ) assert response.status_code == 200 data = response.json() assert data["has_vendor_id"] is True assert data["vendor_id"] == vendor_with_subdomain.id assert data["vendor_id_type"] == "int" def test_vendor_object_injected_into_request_state( self, client, vendor_with_subdomain ): """Test that full vendor object is injected into request.state.""" from fastapi import Request from main import app @app.get("/test-vendor-object-injection") async def test_vendor_object(request: Request): vendor = ( request.state.vendor if hasattr(request.state, "vendor") and request.state.vendor else None ) return { "has_vendor": vendor is not None, "vendor_attributes": ( { "id": vendor.id if vendor else None, "name": vendor.name if vendor else None, "code": vendor.vendor_code if vendor else None, "subdomain": vendor.subdomain if vendor else None, "is_active": vendor.is_active if vendor else None, } if vendor else None ), } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-vendor-object-injection", headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"}, ) assert response.status_code == 200 data = response.json() assert data["has_vendor"] is True assert data["vendor_attributes"]["id"] == vendor_with_subdomain.id assert data["vendor_attributes"]["name"] == vendor_with_subdomain.name assert data["vendor_attributes"]["code"] == vendor_with_subdomain.vendor_code assert data["vendor_attributes"]["is_active"] is True # ======================================================================== # Edge Cases and Error Handling # ======================================================================== def test_inactive_vendor_not_detected(self, client, middleware_inactive_vendor): """Test that inactive vendors are not detected.""" from fastapi import Request from main import app @app.get("/test-inactive-vendor-detection") async def test_inactive(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-inactive-vendor-detection", headers={ "host": f"{middleware_inactive_vendor.subdomain}.platform.com" }, ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is False def test_platform_domain_without_subdomain_no_vendor(self, client): """Test that platform domain without subdomain doesn't detect vendor.""" from fastapi import Request from main import app @app.get("/test-platform-domain") async def test_platform(request: Request): return { "vendor_detected": hasattr(request.state, "vendor") and request.state.vendor is not None } with patch("app.core.config.settings") as mock_settings: mock_settings.platform_domain = "platform.com" response = client.get( "/test-platform-domain", headers={"host": "platform.com"} ) assert response.status_code == 200 data = response.json() assert data["vendor_detected"] is False