"""API tests for user endpoints.""" from __future__ import annotations import pytest from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker from app.core.security import password_hasher from app.models.user import User async def _seed_user( session_factory: async_sessionmaker[AsyncSession], *, email: str, name: str, ) -> int: async with session_factory() as session: user = User( email=email, hashed_password=password_hasher.hash("SeedPass123!"), name=name, is_active=True, ) session.add(user) await session.commit() return user.id @pytest.mark.asyncio async def test_create_user_endpoint_persists_user( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: payload = { "email": "api-user@example.com", "name": "API User", "password": "UserPass123!", } response = await client.post("/api/v1/users/", json=payload) assert response.status_code == 201 body = response.json() assert body["email"] == payload["email"] async with session_factory() as session: user = await session.get(User, body["id"]) assert user is not None assert user.email == payload["email"] assert user.hashed_password != payload["password"] @pytest.mark.asyncio async def test_list_users_endpoint_returns_existing_users( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: await _seed_user(session_factory, email="list-a@example.com", name="List A") await _seed_user(session_factory, email="list-b@example.com", name="List B") response = await client.get("/api/v1/users/") assert response.status_code == 200 data = response.json() emails = {item["email"] for item in data} assert {"list-a@example.com", "list-b@example.com"}.issubset(emails) @pytest.mark.asyncio async def test_get_user_endpoint_returns_single_user( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: user_id = await _seed_user(session_factory, email="detail@example.com", name="Detail User") response = await client.get(f"/api/v1/users/{user_id}") assert response.status_code == 200 payload = response.json() assert payload["id"] == user_id assert payload["email"] == "detail@example.com" @pytest.mark.asyncio async def test_get_user_endpoint_returns_404_for_missing_user(client: AsyncClient) -> None: response = await client.get("/api/v1/users/999") assert response.status_code == 404