"""Authentication flow tests.""" from __future__ import annotations from httpx import AsyncClient from tests.conftest import auth_header, signup async def test_health_is_public(client: AsyncClient): response = await client.get("/health") assert response.status_code == 200 assert response.json()["status"] == "ok" async def test_signup_returns_token_and_user(client: AsyncClient): body = await signup(client, "alice@example.com", name="آلیس") assert body["access_token"] assert body["user"]["email"] == "alice@example.com" assert body["user"]["name"] == "آلیس" assert body["user"]["is_platform_owner"] is False assert "password" not in str(body).lower() or "password_hash" not in str(body) async def test_signup_never_returns_password_hash(client: AsyncClient): body = await signup(client, "hashcheck@example.com") assert "password_hash" not in body["user"] assert "password" not in body["user"] async def test_signup_rejects_duplicate_email(client: AsyncClient): await signup(client, "dup@example.com") response = await client.post( "/api/auth/signup", json={"email": "dup@example.com", "password": "password123", "name": ""}, ) assert response.status_code == 409 assert response.json()["error"]["code"] == "conflict" async def test_signup_rejects_short_password(client: AsyncClient): response = await client.post( "/api/auth/signup", json={"email": "short@example.com", "password": "123", "name": ""}, ) assert response.status_code == 422 async def test_login_succeeds_with_correct_password(client: AsyncClient): await signup(client, "bob@example.com", password="password123") response = await client.post( "/api/auth/login", json={"email": "bob@example.com", "password": "password123"} ) assert response.status_code == 200 assert response.json()["access_token"] async def test_login_fails_with_wrong_password(client: AsyncClient): await signup(client, "carol@example.com", password="password123") response = await client.post( "/api/auth/login", json={"email": "carol@example.com", "password": "wrong-password"} ) assert response.status_code == 401 async def test_login_is_case_insensitive_on_email(client: AsyncClient): await signup(client, "Dave@Example.com", password="password123") response = await client.post( "/api/auth/login", json={"email": "dave@example.com", "password": "password123"} ) assert response.status_code == 200 async def test_me_requires_authentication(client: AsyncClient): response = await client.get("/api/auth/me") assert response.status_code == 401 async def test_me_rejects_garbage_token(client: AsyncClient): response = await client.get("/api/auth/me", headers=auth_header("not-a-real-token")) assert response.status_code == 401 async def test_me_returns_profile_and_organizations(client: AsyncClient): body = await signup(client, "erin@example.com", name="ارین") token = body["access_token"] response = await client.get("/api/auth/me", headers=auth_header(token)) assert response.status_code == 200 payload = response.json() assert payload["user"]["email"] == "erin@example.com" assert payload["organizations"] == [] async def test_logout_is_recorded_and_returns_204(client: AsyncClient): body = await signup(client, "frank@example.com") response = await client.post("/api/auth/logout", headers=auth_header(body["access_token"])) assert response.status_code == 204