"""Pytest fixtures and configuration.""" import os from pathlib import Path # Load test environment variables BEFORE importing app test_env_path = Path(__file__).parent.parent / ".env.test" if test_env_path.exists(): from dotenv import load_dotenv load_dotenv(test_env_path) import pytest from unittest.mock import AsyncMock, MagicMock from fastapi.testclient import TestClient from datetime import datetime, timedelta, UTC from app.main import app from app.dependencies import get_db_client, get_current_user from app.interfaces.db_api_client import DBApiClient from app.models.auth import UserResponse from app.models.settings import UserSettings, EnvironmentSettings from app.utils.security import create_access_token # ============================================ # Mock DB Client # ============================================ @pytest.fixture def mock_db_client(): """Mock DB API client.""" client = AsyncMock(spec=DBApiClient) return client # ============================================ # Test User # ============================================ @pytest.fixture def test_user(): """Test user data.""" return { "user_id": "test-user-123", "login": "12345678" } @pytest.fixture def test_user_response(test_user): """Test user response from DB API.""" return UserResponse( user_id=test_user["user_id"], login=test_user["login"], last_login_at=datetime.now(UTC).isoformat().replace('+00:00', 'Z'), created_at=datetime.now(UTC).isoformat().replace('+00:00', 'Z') ) # ============================================ # JWT Token # ============================================ @pytest.fixture def test_token(test_user): """Generate test JWT token.""" return create_access_token(test_user) @pytest.fixture def expired_token(test_user): """Generate expired JWT token.""" return create_access_token( test_user, expires_delta=timedelta(seconds=-10) # Expired 10 seconds ago ) # ============================================ # Test Settings # ============================================ @pytest.fixture def test_settings(): """Test user settings.""" env_settings = EnvironmentSettings( apiMode="bench", bearerToken="test-bearer-token", systemPlatform="test-platform", systemPlatformUser="test-user", platformUserId="platform-user-123", platformId="platform-123", withClassify=False, resetSessionMode=True ) return UserSettings( user_id="test-user-123", settings={ "ift": env_settings, "psi": env_settings.model_copy(), "prod": env_settings.model_copy() }, updated_at=datetime.now(UTC).isoformat().replace('+00:00', 'Z') ) # ============================================ # FastAPI Test Client # ============================================ @pytest.fixture def client(mock_db_client, test_user): """FastAPI test client with mocked dependencies.""" # Override get_current_user to return test user async def mock_get_current_user(): return test_user # Override get_db_client to return mock def mock_get_db_client(): return mock_db_client app.dependency_overrides[get_current_user] = mock_get_current_user app.dependency_overrides[get_db_client] = mock_get_db_client with TestClient(app) as test_client: yield test_client # Clear overrides after test app.dependency_overrides.clear() @pytest.fixture def unauthenticated_client(): """FastAPI test client without authentication.""" with TestClient(app) as test_client: yield test_client # ============================================ # Mock RAG Responses # ============================================ @pytest.fixture def mock_bench_response(): """Mock RAG backend bench response (matches format.py structure).""" return { "answers": [ { "body_research": "Test research answer 1", "body_analytical_hub": "Test analytical hub answer 1", "docs_from_vectorstore": { "research": [], "analytical_hub": [] }, "docs_to_llm": { "research": [], "analytical_hub": [] }, "processing_time_sec": 1.5, "question": "Test question 1" }, { "body_research": "Test research answer 2", "body_analytical_hub": "Test analytical hub answer 2", "docs_from_vectorstore": { "research": [], "analytical_hub": [] }, "docs_to_llm": { "research": [], "analytical_hub": [] }, "processing_time_sec": 2.3, "question": "Test question 2" } ] } @pytest.fixture def mock_backend_response(): """Mock RAG backend single response.""" return { "answer": "Test answer", "confidence": 0.92, "docs": [] } # ============================================ # Mock httpx Client # ============================================ @pytest.fixture def mock_httpx_client(): """Mock httpx.AsyncClient.""" client = AsyncMock() # Mock response mock_response = MagicMock() mock_response.status_code = 200 mock_response.json.return_value = {"test": "response"} mock_response.raise_for_status = MagicMock() client.post.return_value = mock_response client.get.return_value = mock_response client.aclose = AsyncMock() return client