Files
social-app/backend/tests/unit/v1/inbox_messages/test_service.py
T

142 lines
3.9 KiB
Python

from datetime import datetime, timezone
from unittest.mock import AsyncMock, MagicMock
from uuid import UUID, uuid4
import pytest
from fastapi import HTTPException
from sqlalchemy.exc import SQLAlchemyError
from core.auth.models import CurrentUser
from models.inbox_messages import (
InboxMessage,
InboxMessageStatus as InboxMessageModelStatus,
InboxMessageType as InboxMessageModelType,
)
from v1.inbox_messages.service import InboxMessageService
def _build_message(
*,
message_id: UUID,
recipient_id: UUID,
status: InboxMessageModelStatus = InboxMessageModelStatus.PENDING,
message_type: InboxMessageModelType = InboxMessageModelType.CALENDAR,
schedule_item_id: UUID | None = None,
content: dict[str, object] = {"permission": 7},
) -> InboxMessage:
message = MagicMock(spec=InboxMessage)
message.id = message_id
message.recipient_id = recipient_id
message.sender_id = uuid4()
message.message_type = message_type
message.schedule_item_id = schedule_item_id
message.friendship_id = None
message.content = content
message.is_read = False
message.status = status
message.created_at = datetime(2026, 2, 28, 10, 0, 0, tzinfo=timezone.utc)
return message
@pytest.mark.asyncio
async def test_list_messages_returns_messages() -> None:
user_id = uuid4()
repo = AsyncMock()
repo.list_by_recipient.return_value = [
_build_message(
message_id=uuid4(),
recipient_id=user_id,
schedule_item_id=uuid4(),
)
]
session = AsyncMock()
service = InboxMessageService(
repository=repo,
session=session,
current_user=CurrentUser(id=user_id),
)
result = await service.list_messages()
assert len(result) == 1
assert result[0].recipient_id == user_id
assert result[0].status.value == "pending"
repo.list_by_recipient.assert_awaited_once_with(user_id, None)
@pytest.mark.asyncio
async def test_mark_as_read_updates_message() -> None:
user_id = uuid4()
message_id = uuid4()
updated_message = _build_message(
message_id=message_id,
recipient_id=user_id,
status=InboxMessageModelStatus.PENDING,
schedule_item_id=uuid4(),
)
updated_message.is_read = True
repo = AsyncMock()
repo.mark_as_read.return_value = updated_message
session = AsyncMock()
service = InboxMessageService(
repository=repo,
session=session,
current_user=CurrentUser(id=user_id),
)
result = await service.mark_as_read(message_id)
repo.mark_as_read.assert_awaited_once_with(message_id, user_id)
session.commit.assert_awaited_once()
assert result.is_read is True
@pytest.mark.asyncio
async def test_mark_as_read_raises_404_when_message_missing() -> None:
user_id = uuid4()
message_id = uuid4()
repo = AsyncMock()
repo.mark_as_read.return_value = None
session = AsyncMock()
service = InboxMessageService(
repository=repo,
session=session,
current_user=CurrentUser(id=user_id),
)
with pytest.raises(HTTPException) as exc_info:
await service.mark_as_read(message_id)
assert exc_info.value.status_code == 404
assert exc_info.value.detail == "Inbox message not found"
session.commit.assert_not_awaited()
@pytest.mark.asyncio
async def test_mark_as_read_store_error_returns_503() -> None:
user_id = uuid4()
message_id = uuid4()
repo = AsyncMock()
repo.mark_as_read.side_effect = SQLAlchemyError("boom")
session = AsyncMock()
service = InboxMessageService(
repository=repo,
session=session,
current_user=CurrentUser(id=user_id),
)
with pytest.raises(HTTPException) as exc_info:
await service.mark_as_read(message_id)
assert exc_info.value.status_code == 503
assert exc_info.value.detail == "Inbox message store unavailable"
session.rollback.assert_awaited_once()