Files
social-app/backend/tests/integration/test_profile_routes.py
T

205 lines
6.3 KiB
Python

from __future__ import annotations
from typing import Callable
from uuid import UUID
from fastapi import HTTPException
from fastapi.testclient import TestClient
from app import app
from core.auth.models import CurrentUser
from v1.profile.dependencies import get_current_user, get_profile_service
from v1.profile.schemas import ProfileResponse, ProfileUpdateRequest
from v1.profile.service import ProfileService
class FakeProfileService:
"""Fake service for integration testing."""
def __init__(self, profile: ProfileResponse) -> None:
self._profile = profile
async def get_me(self) -> ProfileResponse:
if self._profile.id is None:
raise HTTPException(status_code=404, detail="Profile not found")
return self._profile
async def update_me(self, update: ProfileUpdateRequest) -> ProfileResponse:
if self._profile.id is None:
raise HTTPException(status_code=404, detail="Profile not found")
return ProfileResponse(
id=self._profile.id,
username=(
update.username
if update.username is not None
else self._profile.username
),
avatar_url=(
update.avatar_url
if update.avatar_url is not None
else self._profile.avatar_url
),
bio=update.bio if update.bio is not None else self._profile.bio,
)
async def get_by_username(self, username: str) -> ProfileResponse:
if username != self._profile.username:
raise HTTPException(status_code=404, detail="Profile not found")
return self._profile
def _override_profile_service(
service: FakeProfileService,
) -> Callable[[], ProfileService]:
def _get_service() -> ProfileService:
return service # type: ignore[return-value]
return _get_service
def _override_current_user(user_id: UUID) -> Callable[[], CurrentUser]:
def _get_user() -> CurrentUser:
return CurrentUser(id=user_id)
return _get_user
def test_get_me_returns_profile() -> None:
user_id = UUID("00000000-0000-0000-0000-000000000001")
profile = ProfileResponse(
id=str(user_id),
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
client = TestClient(app)
try:
response = client.get("/api/v1/profile/me")
assert response.status_code == 200
body = response.json()
assert body["username"] == "demo"
finally:
app.dependency_overrides = {}
def test_patch_me_updates_profile() -> None:
user_id = UUID("00000000-0000-0000-0000-000000000001")
profile = ProfileResponse(
id=str(user_id),
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
client = TestClient(app)
try:
response = client.patch(
"/api/v1/profile/me",
json={"username": "updated"},
)
assert response.status_code == 200
body = response.json()
assert body["username"] == "updated"
finally:
app.dependency_overrides = {}
def test_get_profile_by_username() -> None:
profile = ProfileResponse(
id="00000000-0000-0000-0000-000000000001",
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
client = TestClient(app)
try:
response = client.get("/api/v1/profile/demo")
assert response.status_code == 200
body = response.json()
assert body["username"] == "demo"
finally:
app.dependency_overrides = {}
def test_profile_not_found_returns_problem_details() -> None:
profile = ProfileResponse(
id="00000000-0000-0000-0000-000000000001",
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
client = TestClient(app)
try:
response = client.get("/api/v1/profile/unknown")
assert response.status_code == 404
assert response.headers["content-type"].startswith("application/problem+json")
body = response.json()
assert body["title"] == "Not Found"
assert body["status"] == 404
finally:
app.dependency_overrides = {}
def test_patch_me_validation_error_returns_problem_details() -> None:
user_id = UUID("00000000-0000-0000-0000-000000000001")
profile = ProfileResponse(
id=str(user_id),
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
client = TestClient(app)
try:
response = client.patch("/api/v1/profile/me", json={})
assert response.status_code == 422
assert response.headers["content-type"].startswith("application/problem+json")
body = response.json()
assert body["title"] == "Unprocessable Content"
assert body["status"] == 422
finally:
app.dependency_overrides = {}
def test_patch_me_rejects_display_name_field() -> None:
user_id = UUID("00000000-0000-0000-0000-000000000001")
profile = ProfileResponse(
id=str(user_id),
username="demo",
avatar_url=None,
bio=None,
)
app.dependency_overrides[get_profile_service] = _override_profile_service(
FakeProfileService(profile)
)
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
client = TestClient(app)
try:
response = client.patch("/api/v1/profile/me", json={"display_name": "x"})
assert response.status_code == 422
assert response.headers["content-type"].startswith("application/problem+json")
finally:
app.dependency_overrides = {}