212 lines
5.6 KiB
Python
212 lines
5.6 KiB
Python
"""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
|
|
|
|
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.utcnow().isoformat() + "Z",
|
|
created_at=datetime.utcnow().isoformat() + "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.utcnow().isoformat() + "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
|