chat/apps/chat/tests/test_messages.py
Ali Asadi e4cab3ab62 Merge branch 'master' into feature/minio-integration
# Conflicts:
#	apps/chat/serializers/messages.py
#	apps/chat/services/message.py
#	apps/chat/tests/test_messages.py
#	apps/chat/views/messages.py
2026-07-20 12:27:34 +03:30

148 lines
4.7 KiB
Python

import uuid
from unittest.mock import Mock
import pytest
from apps.chat.models import Conversation, MattermostAccountMapping
from apps.chat.services.message import MessageService
def _make_service(*, mm_post_id="post-1", download_url=None, publishers=None):
"""Return a MessageService with all external deps mocked."""
mm_client = Mock()
mm_client.post_message.return_value = mm_post_id
storage = Mock()
storage.get_download_url.return_value = download_url
return (
MessageService(
mattermost_client=mm_client,
storage_service=storage,
publishers=publishers if publishers is not None else [],
),
mm_client,
storage,
)
@pytest.mark.django_db
def test_send_text_message():
conv = Conversation.objects.create(mattermost_channel_id="ch-send-text")
sender_uuid = uuid.uuid4()
ws_publisher = Mock()
svc, mm_client, storage = _make_service(mm_post_id="post-abc", publishers=[ws_publisher])
result = svc.send(conv.uuid, sender_uuid, "text", text="Hello world")
mm_client.post_message.assert_called_once_with("ch-send-text", "Hello world")
storage.get_download_url.assert_not_called()
ws_publisher.publish.assert_called_once()
event = ws_publisher.publish.call_args[0][0]
assert event.post_id == "post-abc"
assert event.sender_uuid == sender_uuid
assert event.message_type == "text"
assert result["post_id"] == "post-abc"
assert result["text"] == "Hello world"
assert result["url"] is None
@pytest.mark.django_db
def test_send_image_message():
conv = Conversation.objects.create(mattermost_channel_id="ch-send-image")
sender_uuid = uuid.uuid4()
object_key = "images/abc123/photo.jpg"
download_url = "http://minio.local/chat/images/abc123/photo.jpg?X-Amz-Signature=..."
svc, mm_client, storage = _make_service(download_url=download_url, publishers=[])
result = svc.send(conv.uuid, sender_uuid, "image", object_key=object_key)
storage.get_download_url.assert_called_once_with(object_key)
mm_client.post_message.assert_called_once_with("ch-send-image", f"image:{object_key}")
assert result["url"] == download_url
assert result["message_type"] == "image"
@pytest.mark.django_db
def test_list_messages_normalized():
conv = Conversation.objects.create(mattermost_channel_id="ch-list")
sender_uuid = uuid.uuid4()
mm_user_id = "mm-user-xyz"
MattermostAccountMapping.objects.create(
user_uuid=sender_uuid, mattermost_user_id=mm_user_id
)
object_key = "voice/def456/clip.ogg"
raw_posts = [
{
"id": "p1",
"user_id": mm_user_id,
"message": "First message",
"create_at": 1700000000000,
},
{
"id": "p2",
"user_id": mm_user_id,
"message": f"voice:{object_key}",
"create_at": 1700000001000,
},
]
download_url = "http://minio.local/chat/voice/def456/clip.ogg?X-Amz-Signature=..."
mm_client = Mock()
mm_client.get_posts.return_value = raw_posts
svc, _, storage = _make_service(download_url=download_url, publishers=[])
svc._mm = mm_client # inject after construction to keep _make_service simple
messages = svc.list_messages(conv.uuid, page=0, per_page=20)
assert len(messages) == 2
text_msg = messages[0]
assert text_msg["post_id"] == "p1"
assert text_msg["sender_uuid"] == sender_uuid
assert text_msg["message_type"] == "text"
assert text_msg["text"] == "First message"
assert text_msg["url"] is None
voice_msg = messages[1]
assert voice_msg["post_id"] == "p2"
assert voice_msg["sender_uuid"] == sender_uuid
assert voice_msg["message_type"] == "voice"
assert voice_msg["url"] == download_url
assert voice_msg["text"] is None
storage.get_download_url.assert_called_once_with(object_key)
@pytest.mark.django_db
def test_list_messages_treats_colon_in_plain_text_as_text():
"""A plain-text message that happens to contain a colon but doesn't use
a recognized media-type prefix must not be mistaken for a media message.
"""
conv = Conversation.objects.create(mattermost_channel_id="ch-list-colon")
raw_posts = [
{
"id": "p1",
"user_id": None,
"message": "Meeting at 10:30",
"create_at": 1700000000000,
},
]
mm_client = Mock()
mm_client.get_posts.return_value = raw_posts
svc, _, storage = _make_service(publishers=[])
svc._mm = mm_client
messages = svc.list_messages(conv.uuid, page=0, per_page=20)
assert messages[0]["message_type"] == "text"
assert messages[0]["text"] == "Meeting at 10:30"
storage.get_download_url.assert_not_called()