189 lines
5.5 KiB
Python
189 lines
5.5 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.users.dependencies import get_current_user, get_user_service
|
|
from v1.users.schemas import UserResponse, UserSearchRequest, UserUpdateRequest
|
|
from v1.users.service import UserService
|
|
|
|
|
|
class FakeUserService:
|
|
"""Fake service for integration testing."""
|
|
|
|
def __init__(self, user: UserResponse) -> None:
|
|
self._user = user
|
|
self._search_results: list[UserResponse] = []
|
|
|
|
def set_search_results(self, results: list[UserResponse]) -> None:
|
|
self._search_results = results
|
|
|
|
async def get_me(self) -> UserResponse:
|
|
if self._user.id is None:
|
|
raise HTTPException(status_code=404, detail="User not found")
|
|
return self._user
|
|
|
|
async def update_me(self, update: UserUpdateRequest) -> UserResponse:
|
|
if self._user.id is None:
|
|
raise HTTPException(status_code=404, detail="User not found")
|
|
return UserResponse(
|
|
id=self._user.id,
|
|
username=(
|
|
update.username if update.username is not None else self._user.username
|
|
),
|
|
avatar_url=(
|
|
update.avatar_url
|
|
if update.avatar_url is not None
|
|
else self._user.avatar_url
|
|
),
|
|
bio=update.bio if update.bio is not None else self._user.bio,
|
|
)
|
|
|
|
async def search_users(self, request: UserSearchRequest) -> list[UserResponse]:
|
|
if request.query:
|
|
return self._search_results if self._search_results else [self._user]
|
|
return []
|
|
|
|
|
|
def _override_user_service(
|
|
service: FakeUserService,
|
|
) -> Callable[[], UserService]:
|
|
def _get_service() -> UserService:
|
|
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_user() -> None:
|
|
user_id = UUID("00000000-0000-0000-0000-000000000001")
|
|
user = UserResponse(
|
|
id=str(user_id),
|
|
username="demo",
|
|
avatar_url=None,
|
|
bio=None,
|
|
)
|
|
app.dependency_overrides[get_user_service] = _override_user_service(
|
|
FakeUserService(user)
|
|
)
|
|
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
|
|
|
|
client = TestClient(app)
|
|
try:
|
|
response = client.get("/api/v1/users/me")
|
|
assert response.status_code == 200
|
|
body = response.json()
|
|
assert body["username"] == "demo"
|
|
finally:
|
|
app.dependency_overrides = {}
|
|
|
|
|
|
def test_patch_me_updates_user() -> None:
|
|
user_id = UUID("00000000-0000-0000-0000-000000000001")
|
|
user = UserResponse(
|
|
id=str(user_id),
|
|
username="demo",
|
|
avatar_url=None,
|
|
bio=None,
|
|
)
|
|
app.dependency_overrides[get_user_service] = _override_user_service(
|
|
FakeUserService(user)
|
|
)
|
|
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
|
|
|
|
client = TestClient(app)
|
|
try:
|
|
response = client.patch(
|
|
"/api/v1/users/me",
|
|
json={"username": "updated"},
|
|
)
|
|
assert response.status_code == 200
|
|
body = response.json()
|
|
assert body["username"] == "updated"
|
|
finally:
|
|
app.dependency_overrides = {}
|
|
|
|
|
|
def test_patch_me_validation_error_returns_problem_details() -> None:
|
|
user_id = UUID("00000000-0000-0000-0000-000000000001")
|
|
user = UserResponse(
|
|
id=str(user_id),
|
|
username="demo",
|
|
avatar_url=None,
|
|
bio=None,
|
|
)
|
|
app.dependency_overrides[get_user_service] = _override_user_service(
|
|
FakeUserService(user)
|
|
)
|
|
app.dependency_overrides[get_current_user] = _override_current_user(user_id)
|
|
|
|
client = TestClient(app)
|
|
try:
|
|
response = client.patch("/api/v1/users/me", json={})
|
|
assert response.status_code == 422
|
|
assert response.headers["content-type"].startswith("application/problem+json")
|
|
body = response.json()
|
|
assert body["title"] in {"Unprocessable Content", "Unprocessable Entity"}
|
|
assert body["status"] == 422
|
|
finally:
|
|
app.dependency_overrides = {}
|
|
|
|
|
|
def test_search_users_returns_list() -> None:
|
|
user_id = UUID("00000000-0000-0000-0000-000000000001")
|
|
user = UserResponse(
|
|
id=str(user_id),
|
|
username="demo",
|
|
avatar_url=None,
|
|
bio=None,
|
|
)
|
|
app.dependency_overrides[get_user_service] = _override_user_service(
|
|
FakeUserService(user)
|
|
)
|
|
|
|
client = TestClient(app)
|
|
try:
|
|
response = client.post(
|
|
"/api/v1/users/search",
|
|
json={"query": "demo"},
|
|
)
|
|
assert response.status_code == 200
|
|
body = response.json()
|
|
assert isinstance(body, list)
|
|
finally:
|
|
app.dependency_overrides = {}
|
|
|
|
|
|
def test_search_users_empty_query_returns_422() -> None:
|
|
user_id = UUID("00000000-0000-0000-0000-000000000001")
|
|
user = UserResponse(
|
|
id=str(user_id),
|
|
username="demo",
|
|
avatar_url=None,
|
|
bio=None,
|
|
)
|
|
app.dependency_overrides[get_user_service] = _override_user_service(
|
|
FakeUserService(user)
|
|
)
|
|
|
|
client = TestClient(app)
|
|
try:
|
|
response = client.post(
|
|
"/api/v1/users/search",
|
|
json={"query": ""},
|
|
)
|
|
assert response.status_code == 422
|
|
finally:
|
|
app.dependency_overrides = {}
|