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

363 lines
13 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
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 schemas.shared.user import UserContext
from v1.friendships.dependencies import get_friendship_service
from v1.friendships.schemas import (
FriendRequestCreate,
FriendRequestResponse,
FriendResponse,
)
from v1.friendships.service import FriendshipService
from v1.users.dependencies import get_current_user
def _raise_unauthorized() -> CurrentUser:
raise HTTPException(status_code=401, detail="Unauthorized")
class FakeFriendshipService(FriendshipService):
def __init__(self) -> None:
pass
async def send_request(self, request: FriendRequestCreate) -> FriendRequestResponse:
return FriendRequestResponse(
id=UUID("11111111-1111-1111-1111-111111111111"),
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(id="user-2", username="recipient", avatar_url=None),
content={"text": request.content} if request.content else None,
status="pending",
created_at=datetime.now(timezone.utc),
)
async def accept_request(self, friendship_id: UUID) -> FriendRequestResponse:
return FriendRequestResponse(
id=friendship_id,
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(id="user-2", username="recipient", avatar_url=None),
content={"text": "Hello!"},
status="accepted",
created_at=datetime.now(timezone.utc),
)
async def decline_request(self, friendship_id: UUID) -> FriendRequestResponse:
return FriendRequestResponse(
id=friendship_id,
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(id="user-2", username="recipient", avatar_url=None),
content={"text": "Hello!"},
status="rejected",
created_at=datetime.now(timezone.utc),
)
async def cancel_request(self, friendship_id: UUID) -> FriendRequestResponse:
return FriendRequestResponse(
id=friendship_id,
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(id="user-2", username="recipient", avatar_url=None),
content={"text": "Hello!"},
status="canceled",
created_at=datetime.now(timezone.utc),
)
async def get_inbox(self) -> list[FriendRequestResponse]:
return [
FriendRequestResponse(
id=UUID("11111111-1111-1111-1111-111111111111"),
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(
id="user-2", username="recipient", avatar_url=None
),
content={"text": "Hello!"},
status="pending",
created_at=datetime.now(timezone.utc),
)
]
async def get_outgoing_requests(self) -> list[FriendRequestResponse]:
return [
FriendRequestResponse(
id=UUID("22222222-2222-2222-2222-222222222222"),
sender=UserContext(id="user-1", username="sender", avatar_url=None),
recipient=UserContext(id="user-3", username="target", avatar_url=None),
content=None,
status="pending",
created_at=datetime.now(timezone.utc),
)
]
async def get_friends_list(self) -> list[FriendResponse]:
return [
FriendResponse(
id=UUID("33333333-3333-3333-3333-333333333333"),
friend=UserContext(id="user-2", username="friend", avatar_url=None),
status="active",
created_at=datetime.now(timezone.utc),
accepted_at=datetime.now(timezone.utc),
)
]
async def remove_friend(self, friend_id: UUID) -> FriendResponse:
return FriendResponse(
id=UUID("33333333-3333-3333-3333-333333333333"),
friend=UserContext(id=str(friend_id), username="friend", avatar_url=None),
status="active",
created_at=datetime.now(timezone.utc),
accepted_at=datetime.now(timezone.utc),
)
def _override_friendship_service(
service: FriendshipService,
) -> Callable[[], FriendshipService]:
def _get_service() -> FriendshipService:
return service
return _get_service
def _get_fake_current_user() -> CurrentUser:
return CurrentUser(
id=UUID("00000000-0000-0000-0000-000000000001"),
phone="+8613812345678",
)
class TestSendFriendRequest:
def test_send_friend_request_returns_201(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.post(
"/api/v1/friends/requests",
json={
"target_user_id": "22222222-2222-2222-2222-222222222222",
"content": "Hello!",
},
)
assert response.status_code == 201
body = response.json()
assert body["status"] == "pending"
assert body["sender"]["username"] == "sender"
assert body["recipient"]["username"] == "recipient"
finally:
app.dependency_overrides = {}
def test_send_friend_request_missing_target_returns_422(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.post("/api/v1/friends/requests", json={})
assert response.status_code == 422
assert response.headers["content-type"].startswith(
"application/problem+json"
)
finally:
app.dependency_overrides = {}
def test_send_friend_request_invalid_uuid_returns_422(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.post(
"/api/v1/friends/requests",
json={"target_user_id": "invalid-uuid"},
)
assert response.status_code == 422
assert response.headers["content-type"].startswith(
"application/problem+json"
)
finally:
app.dependency_overrides = {}
class TestGetInbox:
def test_get_inbox_returns_200(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.get("/api/v1/friends/requests/inbox")
assert response.status_code == 200
body = response.json()
assert isinstance(body, list)
assert len(body) == 1
assert body[0]["status"] == "pending"
finally:
app.dependency_overrides = {}
class TestGetOutgoingRequests:
def test_get_outgoing_requests_returns_200(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.get("/api/v1/friends/requests/outgoing")
assert response.status_code == 200
body = response.json()
assert isinstance(body, list)
assert len(body) == 1
assert body[0]["status"] == "pending"
finally:
app.dependency_overrides = {}
class TestAcceptFriendRequest:
def test_accept_friend_request_returns_200(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.post(
"/api/v1/friends/requests/11111111-1111-1111-1111-111111111111/accept",
json={},
)
assert response.status_code == 200
body = response.json()
assert body["status"] == "accepted"
finally:
app.dependency_overrides = {}
class TestDeclineFriendRequest:
def test_decline_friend_request_returns_200(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.post(
"/api/v1/friends/requests/11111111-1111-1111-1111-111111111111/decline",
json={},
)
assert response.status_code == 200
body = response.json()
assert body["status"] == "rejected"
finally:
app.dependency_overrides = {}
class TestCancelFriendRequest:
def test_cancel_friend_request_returns_204(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.delete(
"/api/v1/friends/requests/11111111-1111-1111-1111-111111111111"
)
assert response.status_code == 204
assert response.content == b""
finally:
app.dependency_overrides = {}
class TestGetFriendsList:
def test_get_friends_list_returns_200(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.get("/api/v1/friends")
assert response.status_code == 200
body = response.json()
assert isinstance(body, list)
assert len(body) == 1
assert body[0]["status"] == "active"
assert body[0]["friend"]["username"] == "friend"
finally:
app.dependency_overrides = {}
class TestRemoveFriend:
def test_remove_friend_returns_204(self) -> None:
app.dependency_overrides[get_friendship_service] = _override_friendship_service(
FakeFriendshipService()
)
app.dependency_overrides[get_current_user] = _get_fake_current_user
client = TestClient(app)
try:
response = client.delete(
"/api/v1/friends/33333333-3333-3333-3333-333333333333"
)
assert response.status_code == 204
assert response.content == b""
finally:
app.dependency_overrides = {}
class TestFriendshipRequiresAuth:
def test_send_request_without_auth_returns_401(self) -> None:
app.dependency_overrides[get_current_user] = _raise_unauthorized
client = TestClient(app)
try:
response = client.post(
"/api/v1/friends/requests",
json={
"target_user_id": "22222222-2222-2222-2222-222222222222",
},
)
assert response.status_code == 401
finally:
app.dependency_overrides = {}
def test_get_inbox_without_auth_returns_401(self) -> None:
app.dependency_overrides[get_current_user] = _raise_unauthorized
client = TestClient(app)
try:
response = client.get("/api/v1/friends/requests/inbox")
assert response.status_code == 401
finally:
app.dependency_overrides = {}
def test_get_friends_without_auth_returns_401(self) -> None:
app.dependency_overrides[get_current_user] = _raise_unauthorized
client = TestClient(app)
try:
response = client.get("/api/v1/friends")
assert response.status_code == 401
finally:
app.dependency_overrides = {}