import pytest from httpx import AsyncClient @pytest.fixture async def registered_user(client: AsyncClient): resp = await client.post("/api/v1/auth/register", json={ "email": "test@example.com", "username": "testuser", "password": "testpass123", "full_name": "Test User", }) assert resp.status_code == 201 return resp.json() async def test_health(client: AsyncClient): resp = await client.get("/api/v1/health") assert resp.status_code == 200 assert resp.json() == {"status": "ok"} async def test_register_success(client: AsyncClient): resp = await client.post("/api/v1/auth/register", json={ "email": "new@example.com", "username": "newuser", "password": "password123", }) assert resp.status_code == 201 data = resp.json() assert data["user"]["email"] == "new@example.com" assert data["user"]["username"] == "newuser" assert data["user"]["role"] == "user" assert "access_token" in data assert "refresh_token" in data async def test_register_duplicate_email(client: AsyncClient, registered_user): resp = await client.post("/api/v1/auth/register", json={ "email": "test@example.com", "username": "different", "password": "password123", }) assert resp.status_code == 409 async def test_register_short_password(client: AsyncClient): resp = await client.post("/api/v1/auth/register", json={ "email": "short@example.com", "username": "shortpw", "password": "short", }) assert resp.status_code == 422 async def test_login_success(client: AsyncClient, registered_user): resp = await client.post("/api/v1/auth/login", json={ "email": "test@example.com", "password": "testpass123", }) assert resp.status_code == 200 data = resp.json() assert data["user"]["email"] == "test@example.com" assert "access_token" in data assert "refresh_token" in data async def test_login_invalid_credentials(client: AsyncClient, registered_user): resp = await client.post("/api/v1/auth/login", json={ "email": "test@example.com", "password": "wrongpassword", }) assert resp.status_code == 401 async def test_login_nonexistent_user(client: AsyncClient): resp = await client.post("/api/v1/auth/login", json={ "email": "nobody@example.com", "password": "password123", }) assert resp.status_code == 401 async def test_me_authenticated(client: AsyncClient, registered_user): token = registered_user["access_token"] resp = await client.get("/api/v1/auth/me", headers={ "Authorization": f"Bearer {token}", }) assert resp.status_code == 200 assert resp.json()["email"] == "test@example.com" async def test_me_unauthenticated(client: AsyncClient): resp = await client.get("/api/v1/auth/me") assert resp.status_code == 401 async def test_me_invalid_token(client: AsyncClient): resp = await client.get("/api/v1/auth/me", headers={ "Authorization": "Bearer invalid_token_here", }) assert resp.status_code == 401 async def test_refresh_token(client: AsyncClient, registered_user): refresh = registered_user["refresh_token"] resp = await client.post("/api/v1/auth/refresh", json={ "refresh_token": refresh, }) assert resp.status_code == 200 data = resp.json() assert "access_token" in data assert "refresh_token" in data assert data["refresh_token"] != refresh # rotated async def test_refresh_invalid_token(client: AsyncClient): resp = await client.post("/api/v1/auth/refresh", json={ "refresh_token": "invalid_token", }) assert resp.status_code == 401 async def test_logout(client: AsyncClient, registered_user): refresh = registered_user["refresh_token"] resp = await client.post("/api/v1/auth/logout", json={ "refresh_token": refresh, }) assert resp.status_code == 204 # Refresh should fail after logout resp = await client.post("/api/v1/auth/refresh", json={ "refresh_token": refresh, }) assert resp.status_code == 401