142 lines
3.9 KiB
Python
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()
|