from collections.abc import Mapping from http import HTTPStatus as status from uuid import uuid4 from dishka import FromDishka from httpx import AsyncClient, Response from tests.web_api.ioc import DatabaseClearer, inject DEFAULT_PASSWORD = "Sup3rSecret" # noqa: S105 def _unique_email() -> str: return f"user-{uuid4().hex}@example.com" def _auth_headers(token: str) -> Mapping[str, str]: return {"Authorization": f"Bearer {token}"} async def _sign_up_and_get_token(client: AsyncClient, email: str) -> str: response = await client.post( "/auth/sign_up/email", json={"email": email, "password": DEFAULT_PASSWORD}, ) assert response.status_code == status.OK, response.text body = response.json() return str(body["access_token"]) async def _get_profile(client: AsyncClient, token: str) -> Response: return await client.get("/profile", headers=_auth_headers(token)) async def _patch_profile( client: AsyncClient, token: str, payload: Mapping[str, str | None], ) -> Response: return await client.patch("/profile", headers=_auth_headers(token), json=payload) @inject async def test_get_profile_returns_current_user( http_client: FromDishka[AsyncClient], database_clearer: FromDishka[DatabaseClearer], ) -> None: await database_clearer.clear() email = _unique_email() token = await _sign_up_and_get_token(http_client, email) response = await _get_profile(http_client, token) body = response.json() assert response.status_code == status.OK assert body["email"] == email assert body["display_name"] is None @inject async def test_patch_profile_updates_profile_data( http_client: FromDishka[AsyncClient], database_clearer: FromDishka[DatabaseClearer], ) -> None: await database_clearer.clear() email = _unique_email() token = await _sign_up_and_get_token(http_client, email) payload = { "display_name": "Alice", "first_name": "Alice", "last_name": "Smith", "avatar_url": "https://example.com/avatar.png", "phone": "+1234567890", } patch_response = await _patch_profile(http_client, token, payload) patch_body = patch_response.json() assert patch_response.status_code == status.OK assert patch_body["display_name"] == payload["display_name"] assert patch_body["first_name"] == payload["first_name"] assert patch_body["last_name"] == payload["last_name"] assert patch_body["avatar_url"] == payload["avatar_url"] assert patch_body["phone"] == payload["phone"] assert patch_body["email"] == email get_response = await _get_profile(http_client, token) get_body = get_response.json() assert get_body["display_name"] == payload["display_name"] assert get_body["first_name"] == payload["first_name"] assert get_body["last_name"] == payload["last_name"] assert get_body["avatar_url"] == payload["avatar_url"] assert get_body["phone"] == payload["phone"] @inject async def test_profile_routes_require_authentication( http_client: FromDishka[AsyncClient], database_clearer: FromDishka[DatabaseClearer], ) -> None: await database_clearer.clear() response_get = await http_client.get("/profile") response_patch = await http_client.patch("/profile", json={}) assert response_get.status_code == status.FORBIDDEN assert response_patch.status_code == status.FORBIDDEN