diff --git a/mpt_api_client/resources/helpdesk/chat_messages.py b/mpt_api_client/resources/helpdesk/chat_messages.py new file mode 100644 index 0000000..3652e3f --- /dev/null +++ b/mpt_api_client/resources/helpdesk/chat_messages.py @@ -0,0 +1,46 @@ +from mpt_api_client.http import AsyncService, Service +from mpt_api_client.http.mixins import ( + AsyncCollectionMixin, + AsyncCreateMixin, + AsyncDeleteMixin, + AsyncUpdateMixin, + CollectionMixin, + CreateMixin, + DeleteMixin, + UpdateMixin, +) +from mpt_api_client.models import Model + + +class ChatMessage(Model): + """Helpdesk Chat Message resource.""" + + +class ChatMessagesServiceConfig: + """Helpdesk Chat Messages service configuration.""" + + _endpoint = "/public/v1/helpdesk/chats/{chat_id}/messages" + _model_class = ChatMessage + _collection_key = "data" + + +class ChatMessagesService( + CreateMixin[ChatMessage], + UpdateMixin[ChatMessage], + DeleteMixin, + CollectionMixin[ChatMessage], + Service[ChatMessage], + ChatMessagesServiceConfig, +): + """Helpdesk Chat Messages service.""" + + +class AsyncChatMessagesService( + AsyncCreateMixin[ChatMessage], + AsyncUpdateMixin[ChatMessage], + AsyncDeleteMixin, + AsyncCollectionMixin[ChatMessage], + AsyncService[ChatMessage], + ChatMessagesServiceConfig, +): + """Async Helpdesk Chat Messages service.""" diff --git a/mpt_api_client/resources/helpdesk/chats.py b/mpt_api_client/resources/helpdesk/chats.py index f2360ef..62dcbeb 100644 --- a/mpt_api_client/resources/helpdesk/chats.py +++ b/mpt_api_client/resources/helpdesk/chats.py @@ -10,6 +10,10 @@ UpdateMixin, ) from mpt_api_client.models import Model +from mpt_api_client.resources.helpdesk.chat_messages import ( + AsyncChatMessagesService, + ChatMessagesService, +) class Chat(Model): @@ -34,6 +38,12 @@ class ChatsService( ): """Helpdesk Chats service.""" + def messages(self, chat_id: str) -> ChatMessagesService: + """Return chat messages service.""" + return ChatMessagesService( + http_client=self.http_client, endpoint_params={"chat_id": chat_id} + ) + class AsyncChatsService( AsyncCreateMixin[Chat], @@ -44,3 +54,9 @@ class AsyncChatsService( ChatsServiceConfig, ): """Async Helpdesk Chats service.""" + + def messages(self, chat_id: str) -> AsyncChatMessagesService: + """Return async chat messages service.""" + return AsyncChatMessagesService( + http_client=self.http_client, endpoint_params={"chat_id": chat_id} + ) diff --git a/tests/e2e/helpdesk/chats/messages/__init__.py b/tests/e2e/helpdesk/chats/messages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/e2e/helpdesk/chats/messages/conftest.py b/tests/e2e/helpdesk/chats/messages/conftest.py new file mode 100644 index 0000000..43ebbba --- /dev/null +++ b/tests/e2e/helpdesk/chats/messages/conftest.py @@ -0,0 +1,44 @@ +import pytest + +from tests.e2e.helper import ( + async_create_fixture_resource_and_delete, + create_fixture_resource_and_delete, +) + + +@pytest.fixture +def chat_messages_service(mpt_ops, chat_id): + return mpt_ops.helpdesk.chats.messages(chat_id) + + +@pytest.fixture +def async_chat_messages_service(async_mpt_ops, chat_id): + return async_mpt_ops.helpdesk.chats.messages(chat_id) + + +@pytest.fixture +def chat_message_data(short_uuid): + return { + "content": f"e2e message - {short_uuid}", + } + + +@pytest.fixture +def created_chat_message(chat_messages_service, chat_message_data): + with create_fixture_resource_and_delete( + chat_messages_service, chat_message_data + ) as chat_message: + yield chat_message + + +@pytest.fixture +async def async_created_chat_message(async_chat_messages_service, chat_message_data): + async with async_create_fixture_resource_and_delete( + async_chat_messages_service, chat_message_data + ) as chat_message: + yield chat_message + + +@pytest.fixture +def invalid_chat_message_id(): + return "MSG-0000-0000-0000" diff --git a/tests/e2e/helpdesk/chats/messages/test_async_messages.py b/tests/e2e/helpdesk/chats/messages/test_async_messages.py new file mode 100644 index 0000000..203907f --- /dev/null +++ b/tests/e2e/helpdesk/chats/messages/test_async_messages.py @@ -0,0 +1,46 @@ +import pytest + +from mpt_api_client.exceptions import MPTAPIError + +pytestmark = [pytest.mark.flaky] + + +async def test_list_chat_messages(async_chat_messages_service): + result = await async_chat_messages_service.fetch_page(limit=1) + + assert len(result) > 0 + + +def test_create_chat_message(async_created_chat_message, chat_message_data): # noqa: AAA01 + assert async_created_chat_message.id is not None + assert async_created_chat_message.to_dict().get("content") == chat_message_data["content"] + + +async def test_update_chat_message_visibility( + async_chat_messages_service, async_created_chat_message +): + result = await async_chat_messages_service.update( + async_created_chat_message.id, + {"visibility": "Public"}, + ) + + assert result.id == async_created_chat_message.id + + +async def test_delete_chat_message(async_chat_messages_service, async_created_chat_message): + result = async_created_chat_message + + await async_chat_messages_service.delete(result.id) + + +async def test_update_chat_message_not_found(async_chat_messages_service, invalid_chat_message_id): + with pytest.raises(MPTAPIError, match=r"404 Not Found"): + await async_chat_messages_service.update( + invalid_chat_message_id, + {"visibility": "Public"}, + ) + + +async def test_delete_chat_message_not_found(async_chat_messages_service, invalid_chat_message_id): + with pytest.raises(MPTAPIError, match=r"404 Not Found"): + await async_chat_messages_service.delete(invalid_chat_message_id) diff --git a/tests/e2e/helpdesk/chats/messages/test_sync_messages.py b/tests/e2e/helpdesk/chats/messages/test_sync_messages.py new file mode 100644 index 0000000..24ecdd8 --- /dev/null +++ b/tests/e2e/helpdesk/chats/messages/test_sync_messages.py @@ -0,0 +1,38 @@ +import pytest + +from mpt_api_client.exceptions import MPTAPIError + +pytestmark = [pytest.mark.flaky] + + +def test_list_chat_messages(chat_messages_service): + result = chat_messages_service.fetch_page(limit=1) + + assert len(result) > 0 + + +def test_create_chat_message(created_chat_message, chat_message_data): # noqa: AAA01 + assert created_chat_message.id is not None + assert created_chat_message.to_dict().get("content") == chat_message_data["content"] + + +def test_update_chat_message_visibility(chat_messages_service, created_chat_message): + result = chat_messages_service.update(created_chat_message.id, {"visibility": "Public"}) + + assert result.id == created_chat_message.id + + +def test_delete_chat_message(chat_messages_service, created_chat_message): + result = created_chat_message + + chat_messages_service.delete(result.id) + + +def test_update_chat_message_not_found(chat_messages_service, invalid_chat_message_id): + with pytest.raises(MPTAPIError, match=r"404 Not Found"): + chat_messages_service.update(invalid_chat_message_id, {"visibility": "Public"}) + + +def test_delete_chat_message_not_found(chat_messages_service, invalid_chat_message_id): + with pytest.raises(MPTAPIError, match=r"404 Not Found"): + chat_messages_service.delete(invalid_chat_message_id) diff --git a/tests/unit/resources/helpdesk/test_chat_messages.py b/tests/unit/resources/helpdesk/test_chat_messages.py new file mode 100644 index 0000000..6518fb2 --- /dev/null +++ b/tests/unit/resources/helpdesk/test_chat_messages.py @@ -0,0 +1,48 @@ +import pytest + +from mpt_api_client.resources.helpdesk.chat_messages import ( + AsyncChatMessagesService, + ChatMessagesService, +) + + +@pytest.fixture +def chat_messages_service(http_client) -> ChatMessagesService: + return ChatMessagesService( + http_client=http_client, endpoint_params={"chat_id": "CHT-0000-0000-0001"} + ) + + +@pytest.fixture +def async_chat_messages_service(async_http_client) -> AsyncChatMessagesService: + return AsyncChatMessagesService( + http_client=async_http_client, endpoint_params={"chat_id": "CHT-0000-0000-0001"} + ) + + +def test_endpoint(chat_messages_service) -> None: + result = chat_messages_service.path == "/public/v1/helpdesk/chats/CHT-0000-0000-0001/messages" + + assert result is True + + +def test_async_endpoint(async_chat_messages_service) -> None: + result = ( + async_chat_messages_service.path == "/public/v1/helpdesk/chats/CHT-0000-0000-0001/messages" + ) + + assert result is True + + +@pytest.mark.parametrize("method", ["create", "update", "delete", "iterate"]) +def test_methods_present(chat_messages_service, method: str) -> None: + result = hasattr(chat_messages_service, method) + + assert result is True + + +@pytest.mark.parametrize("method", ["create", "update", "delete", "iterate"]) +def test_async_methods_present(async_chat_messages_service, method: str) -> None: + result = hasattr(async_chat_messages_service, method) + + assert result is True diff --git a/tests/unit/resources/helpdesk/test_chats.py b/tests/unit/resources/helpdesk/test_chats.py index 47cf24a..7ad72a9 100644 --- a/tests/unit/resources/helpdesk/test_chats.py +++ b/tests/unit/resources/helpdesk/test_chats.py @@ -1,5 +1,9 @@ import pytest +from mpt_api_client.resources.helpdesk.chat_messages import ( + AsyncChatMessagesService, + ChatMessagesService, +) from mpt_api_client.resources.helpdesk.chats import AsyncChatsService, ChatsService @@ -31,3 +35,17 @@ def test_async_mixins_present(async_chats_service, method): result = hasattr(async_chats_service, method) assert result is True + + +def test_messages_service(chats_service): + result = chats_service.messages("CHT-0000-0000-0001") + + assert isinstance(result, ChatMessagesService) + assert result.endpoint_params == {"chat_id": "CHT-0000-0000-0001"} + + +def test_async_messages_service(async_chats_service): + result = async_chats_service.messages("CHT-0000-0000-0001") + + assert isinstance(result, AsyncChatMessagesService) + assert result.endpoint_params == {"chat_id": "CHT-0000-0000-0001"}