import pytest from httpx import AsyncClient pytestmark = pytest.mark.asyncio REGISTER_URL = "/api/v1/auth/register" LOGIN_URL = "/api/v1/auth/login" REFRESH_URL = "/api/v1/auth/refresh" LOGOUT_URL = "/api/v1/auth/logout" RESET_URL = "/api/v1/auth/password-reset" ME_URL = "/api/v1/auth/me" async def test_register_success(client: AsyncClient): resp = await client.post(REGISTER_URL, json={ "company_name": "Acme GmbH", "first_name": "Erika", "last_name": "Muster", "email": "erika@acme.de", "password": "Secure123", }) assert resp.status_code == 201 body = resp.json() assert "access_token" in body assert "refresh_token" in body assert body["token_type"] == "bearer" async def test_register_duplicate_email(client: AsyncClient, registered_user): resp = await client.post(REGISTER_URL, json={ "company_name": "Other GmbH", "first_name": "Max", "last_name": "Mustermann", "email": registered_user["user"]["email"], "password": "Secret123", }) assert resp.status_code == 400 assert "already registered" in resp.json()["detail"] async def test_register_weak_password(client: AsyncClient): resp = await client.post(REGISTER_URL, json={ "company_name": "Weak Corp", "first_name": "A", "last_name": "B", "email": "weak@corp.de", "password": "nouppercase1", }) assert resp.status_code == 422 async def test_login_success(client: AsyncClient, registered_user): resp = await client.post(LOGIN_URL, json={ "email": registered_user["user"]["email"], "password": "Secret123", }) assert resp.status_code == 200 assert "access_token" in resp.json() async def test_login_wrong_password(client: AsyncClient, registered_user): resp = await client.post(LOGIN_URL, json={ "email": registered_user["user"]["email"], "password": "WrongPassword1", }) assert resp.status_code == 401 async def test_login_unknown_email(client: AsyncClient): resp = await client.post(LOGIN_URL, json={ "email": "nobody@nowhere.de", "password": "Secret123", }) assert resp.status_code == 401 async def test_me_authenticated(client: AsyncClient, registered_user): resp = await client.get( ME_URL, headers={"Authorization": f"Bearer {registered_user['tokens']['access_token']}"}, ) assert resp.status_code == 200 body = resp.json() assert body["email"] == registered_user["user"]["email"] assert body["role"] == "COMPANY_ADMIN" async def test_me_unauthenticated(client: AsyncClient): resp = await client.get(ME_URL) assert resp.status_code == 401 async def test_token_refresh(client: AsyncClient, registered_user): resp = await client.post(REFRESH_URL, json={ "refresh_token": registered_user["tokens"]["refresh_token"], }) assert resp.status_code == 200 new_tokens = resp.json() assert "access_token" in new_tokens # Old refresh token should now be invalid (rotation) resp2 = await client.post(REFRESH_URL, json={ "refresh_token": registered_user["tokens"]["refresh_token"], }) assert resp2.status_code == 401 async def test_logout(client: AsyncClient): reg = await client.post(REGISTER_URL, json={ "company_name": "Logout Corp", "first_name": "Hans", "last_name": "Logout", "email": "hans@logout.de", "password": "Secret123", }) tokens = reg.json() resp = await client.post(LOGOUT_URL, json={"refresh_token": tokens["refresh_token"]}) assert resp.status_code == 200 # Refresh should now fail resp2 = await client.post(REFRESH_URL, json={"refresh_token": tokens["refresh_token"]}) assert resp2.status_code == 401 async def test_password_reset_request(client: AsyncClient, registered_user): resp = await client.post(RESET_URL, json={"email": registered_user["user"]["email"]}) assert resp.status_code == 200 # Same response for unknown email (anti-enumeration) resp2 = await client.post(RESET_URL, json={"email": "nobody@x.de"}) assert resp2.status_code == 200