"""API test fixtures.""" from collections.abc import AsyncGenerator from unittest.mock import AsyncMock, MagicMock, patch from uuid import uuid4 import pytest from httpx import ASGITransport, AsyncClient from app.application.dtos import PostResponseDTO from app.infrastructure.auth.models import TokenInfo from app.main import app_factory class MockKeycloakClient: def __init__(self, token_info: TokenInfo) -> None: self._token_info = token_info async def introspect_token(self, token: str) -> TokenInfo: return self._token_info @pytest.fixture def user_token_info() -> TokenInfo: return TokenInfo( active=True, user_id="test-user-id", username="testuser", email="test@example.com", roles=["user"], ) @pytest.fixture def admin_token_info() -> TokenInfo: return TokenInfo( active=True, user_id="admin-user-id", username="adminuser", email="admin@example.com", roles=["admin", "user"], ) @pytest.fixture def mock_keycloak_client(user_token_info: TokenInfo) -> MagicMock: mock_client = AsyncMock() mock_client.introspect_token.return_value = user_token_info return mock_client @pytest.fixture async def client(mock_keycloak_client: MagicMock) -> AsyncGenerator[AsyncClient]: with patch( "app.presentation.api.deps.KeycloakAuthClient", return_value=mock_keycloak_client, ): app = app_factory() transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as ac: yield ac @pytest.fixture async def auth_client(user_token_info: TokenInfo) -> AsyncGenerator[AsyncClient]: mock_client = MockKeycloakClient(user_token_info) with patch( "app.presentation.api.deps.get_keycloak_client", return_value=mock_client, ): app = app_factory() transport = ASGITransport(app=app) async with AsyncClient( transport=transport, base_url="http://test", headers={"Authorization": "Bearer user_token"}, ) as ac: yield ac @pytest.fixture async def admin_client(admin_token_info: TokenInfo) -> AsyncGenerator[AsyncClient]: mock_client = MockKeycloakClient(admin_token_info) with patch( "app.presentation.api.deps.get_keycloak_client", return_value=mock_client, ): app = app_factory() transport = ASGITransport(app=app) async with AsyncClient( transport=transport, base_url="http://test", headers={"Authorization": "Bearer admin_token"}, ) as ac: yield ac @pytest.fixture def auth_headers() -> dict[str, str]: return {"Authorization": "Bearer test_token"} @pytest.fixture def unauthorized_keycloak_client() -> MagicMock: mock_client = AsyncMock() mock_client.introspect_token.return_value = TokenInfo( active=False, user_id="", username="", email="", roles=[], ) return mock_client @pytest.fixture def sample_post_dto() -> PostResponseDTO: return PostResponseDTO( id=uuid4(), title="Test Post", content="This is test content for the blog post", slug="test-post", author_id="test-user-id", published=True, tags=["python", "testing"], created_at=__import__("datetime").datetime.now(), updated_at=__import__("datetime").datetime.now(), ) @pytest.fixture def sample_unpublished_post_dto() -> PostResponseDTO: return PostResponseDTO( id=uuid4(), title="Draft Post", content="This is a draft post", slug="draft-post", author_id="test-user-id", published=False, tags=["draft"], created_at=__import__("datetime").datetime.now(), updated_at=__import__("datetime").datetime.now(), )