Skip to content

Commit 3493f2b

Browse files
committed
feat: add helpdesk chat answers services and tests
1 parent 609839f commit 3493f2b

File tree

14 files changed

+637
-0
lines changed

14 files changed

+637
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import AsyncCollectionMixin, CollectionMixin
3+
from mpt_api_client.models import Model
4+
5+
6+
class ChatAnswerParameter(Model):
7+
"""Helpdesk chat answer parameter resource."""
8+
9+
10+
class ChatAnswerParametersServiceConfig:
11+
"""Helpdesk chat answer parameters service configuration."""
12+
13+
_endpoint = "/public/v1/helpdesk/chats/{chat_id}/answers/{answer_id}/parameters"
14+
_model_class = ChatAnswerParameter
15+
_collection_key = "data"
16+
17+
18+
class ChatAnswerParametersService(
19+
CollectionMixin[ChatAnswerParameter],
20+
Service[ChatAnswerParameter],
21+
ChatAnswerParametersServiceConfig,
22+
):
23+
"""Helpdesk chat answer parameters service."""
24+
25+
26+
class AsyncChatAnswerParametersService(
27+
AsyncCollectionMixin[ChatAnswerParameter],
28+
AsyncService[ChatAnswerParameter],
29+
ChatAnswerParametersServiceConfig,
30+
):
31+
"""Async helpdesk chat answer parameters service."""
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from mpt_api_client.http import AsyncService, Service, mixins
2+
from mpt_api_client.models import Model, ResourceData
3+
from mpt_api_client.resources.helpdesk.chat_answer_parameters import (
4+
AsyncChatAnswerParametersService,
5+
ChatAnswerParametersService,
6+
)
7+
8+
9+
class ChatAnswer(Model):
10+
"""Helpdesk Chat Answer resource."""
11+
12+
13+
class ChatAnswersServiceConfig:
14+
"""Helpdesk Chat Answers service configuration."""
15+
16+
_endpoint = "/public/v1/helpdesk/chats/{chat_id}/answers"
17+
_model_class = ChatAnswer
18+
_collection_key = "data"
19+
20+
21+
class ChatAnswersService(
22+
mixins.CreateMixin[ChatAnswer],
23+
mixins.UpdateMixin[ChatAnswer],
24+
mixins.DeleteMixin,
25+
mixins.GetMixin[ChatAnswer],
26+
mixins.CollectionMixin[ChatAnswer],
27+
Service[ChatAnswer],
28+
ChatAnswersServiceConfig,
29+
):
30+
"""Helpdesk Chat Answers service."""
31+
32+
def submit(self, resource_id: str, resource_data: ResourceData | None = None) -> ChatAnswer:
33+
"""Switch answer to submitted state."""
34+
return self._resource_action(resource_id, "POST", "submit", json=resource_data)
35+
36+
def accept(self, resource_id: str, resource_data: ResourceData | None = None) -> ChatAnswer:
37+
"""Switch answer to accepted state."""
38+
return self._resource_action(resource_id, "POST", "accept", json=resource_data)
39+
40+
def query(self, resource_id: str, resource_data: ResourceData | None = None) -> ChatAnswer:
41+
"""Switch answer to query state."""
42+
return self._resource_action(resource_id, "POST", "query", json=resource_data)
43+
44+
def validate(self, resource_id: str, resource_data: ResourceData | None = None) -> ChatAnswer:
45+
"""Validate answer."""
46+
return self._resource_action(resource_id, "POST", "validate", json=resource_data)
47+
48+
def parameters(self, answer_id: str) -> ChatAnswerParametersService: # noqa: WPS110
49+
"""Return chat answer parameters service."""
50+
return ChatAnswerParametersService(
51+
http_client=self.http_client,
52+
endpoint_params={
53+
"chat_id": self.endpoint_params["chat_id"],
54+
"answer_id": answer_id,
55+
},
56+
)
57+
58+
59+
class AsyncChatAnswersService(
60+
mixins.AsyncCreateMixin[ChatAnswer],
61+
mixins.AsyncUpdateMixin[ChatAnswer],
62+
mixins.AsyncDeleteMixin,
63+
mixins.AsyncGetMixin[ChatAnswer],
64+
mixins.AsyncCollectionMixin[ChatAnswer],
65+
AsyncService[ChatAnswer],
66+
ChatAnswersServiceConfig,
67+
):
68+
"""Async Helpdesk Chat Answers service."""
69+
70+
async def submit(
71+
self,
72+
resource_id: str,
73+
resource_data: ResourceData | None = None,
74+
) -> ChatAnswer:
75+
"""Switch answer to submitted state."""
76+
return await self._resource_action(resource_id, "POST", "submit", json=resource_data)
77+
78+
async def accept(
79+
self,
80+
resource_id: str,
81+
resource_data: ResourceData | None = None,
82+
) -> ChatAnswer:
83+
"""Switch answer to accepted state."""
84+
return await self._resource_action(resource_id, "POST", "accept", json=resource_data)
85+
86+
async def query(
87+
self,
88+
resource_id: str,
89+
resource_data: ResourceData | None = None,
90+
) -> ChatAnswer:
91+
"""Switch answer to query state."""
92+
return await self._resource_action(resource_id, "POST", "query", json=resource_data)
93+
94+
async def validate(
95+
self,
96+
resource_id: str,
97+
resource_data: ResourceData | None = None,
98+
) -> ChatAnswer:
99+
"""Validate answer."""
100+
return await self._resource_action(resource_id, "POST", "validate", json=resource_data)
101+
102+
def parameters(self, answer_id: str) -> AsyncChatAnswerParametersService: # noqa: WPS110
103+
"""Return async chat answer parameters service."""
104+
return AsyncChatAnswerParametersService(
105+
http_client=self.http_client,
106+
endpoint_params={
107+
"chat_id": self.endpoint_params["chat_id"],
108+
"answer_id": answer_id,
109+
},
110+
)

mpt_api_client/resources/helpdesk/chats.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
UpdateMixin,
1111
)
1212
from mpt_api_client.models import Model
13+
from mpt_api_client.resources.helpdesk.chat_answers import (
14+
AsyncChatAnswersService,
15+
ChatAnswersService,
16+
)
1317
from mpt_api_client.resources.helpdesk.chat_attachments import (
1418
AsyncChatAttachmentsService,
1519
ChatAttachmentsService,
@@ -72,6 +76,12 @@ def participants(self, chat_id: str) -> ChatParticipantsService:
7276
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
7377
)
7478

79+
def answers(self, chat_id: str) -> ChatAnswersService:
80+
"""Return chat answers service."""
81+
return ChatAnswersService(
82+
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
83+
)
84+
7585

7686
class AsyncChatsService(
7787
AsyncCreateMixin[Chat],
@@ -106,3 +116,9 @@ def participants(self, chat_id: str) -> AsyncChatParticipantsService:
106116
return AsyncChatParticipantsService(
107117
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
108118
)
119+
120+
def answers(self, chat_id: str) -> AsyncChatAnswersService:
121+
"""Return async chat answers service."""
122+
return AsyncChatAnswersService(
123+
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
124+
)

tests/e2e/helpdesk/chats/answers/__init__.py

Whitespace-only changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from tests.e2e.helper import (
4+
async_create_fixture_resource_and_delete,
5+
create_fixture_resource_and_delete,
6+
)
7+
8+
9+
@pytest.fixture
10+
def chat_answers_service(mpt_ops, chat_id):
11+
return mpt_ops.helpdesk.chats.answers(chat_id)
12+
13+
14+
@pytest.fixture
15+
def async_chat_answers_service(async_mpt_ops, chat_id):
16+
return async_mpt_ops.helpdesk.chats.answers(chat_id)
17+
18+
19+
@pytest.fixture
20+
def chat_answer_data(short_uuid):
21+
return {
22+
"name": f"e2e answer {short_uuid}",
23+
}
24+
25+
26+
@pytest.fixture
27+
def created_chat_answer(chat_answers_service, chat_answer_data):
28+
with create_fixture_resource_and_delete(chat_answers_service, chat_answer_data) as chat_answer:
29+
yield chat_answer
30+
31+
32+
@pytest.fixture
33+
async def async_created_chat_answer(async_chat_answers_service, chat_answer_data):
34+
async with async_create_fixture_resource_and_delete(
35+
async_chat_answers_service, chat_answer_data
36+
) as chat_answer:
37+
yield chat_answer
38+
39+
40+
@pytest.fixture
41+
def invalid_chat_answer_id():
42+
return "ANS-0000-0000"

tests/e2e/helpdesk/chats/answers/parameters/__init__.py

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def chat_answer_parameters_service(mpt_ops, chat_id, created_chat_answer):
6+
return mpt_ops.helpdesk.chats.answers(chat_id).parameters(created_chat_answer.id)
7+
8+
9+
@pytest.fixture
10+
def async_chat_answer_parameters_service(async_mpt_ops, chat_id, async_created_chat_answer):
11+
return async_mpt_ops.helpdesk.chats.answers(chat_id).parameters(async_created_chat_answer.id)
12+
13+
14+
@pytest.fixture
15+
def invalid_chat_answer_parameter_id():
16+
return "PAR-0000-0000"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [
6+
pytest.mark.flaky,
7+
pytest.mark.skip(reason="Unskip after MPT-19124 completed"),
8+
]
9+
10+
11+
async def test_list_chat_answer_parameters(async_chat_answer_parameters_service):
12+
result = await async_chat_answer_parameters_service.fetch_page(limit=20)
13+
14+
assert len(result) >= 0
15+
16+
17+
async def test_iterate_chat_answer_parameters(async_chat_answer_parameters_service):
18+
iterator = async_chat_answer_parameters_service.iterate(limit=20)
19+
result = await anext(iterator, None)
20+
21+
assert result is None or result.id is not None
22+
23+
24+
async def test_not_found(async_mpt_ops, chat_id):
25+
service = async_mpt_ops.helpdesk.chats.answers(chat_id).parameters("ANS-0000-0000")
26+
27+
with pytest.raises(MPTAPIError):
28+
await service.fetch_page(limit=20)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [
6+
pytest.mark.flaky,
7+
pytest.mark.skip(reason="Unskip after MPT-19124 completed"),
8+
]
9+
10+
11+
def test_list_chat_answer_parameters(chat_answer_parameters_service):
12+
result = chat_answer_parameters_service.fetch_page(limit=20)
13+
14+
assert len(result) >= 0
15+
16+
17+
def test_iterate_chat_answer_parameters(chat_answer_parameters_service):
18+
iterator = chat_answer_parameters_service.iterate(limit=20)
19+
20+
result = next(iterator, None)
21+
22+
assert result is None or result.id is not None
23+
24+
25+
def test_not_found(mpt_ops, chat_id):
26+
service = mpt_ops.helpdesk.chats.answers(chat_id).parameters("ANS-0000-0000")
27+
28+
with pytest.raises(MPTAPIError):
29+
service.fetch_page(limit=20)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [
6+
pytest.mark.flaky,
7+
pytest.mark.skip(reason="Unskip after MPT-19124 completed"),
8+
]
9+
10+
11+
async def test_get_chat_answer(async_chat_answers_service, async_created_chat_answer):
12+
result = await async_chat_answers_service.get(async_created_chat_answer.id)
13+
14+
assert result.id == async_created_chat_answer.id
15+
16+
17+
async def test_list_chat_answers(async_chat_answers_service):
18+
result = await async_chat_answers_service.fetch_page(limit=1)
19+
20+
assert len(result) > 0
21+
22+
23+
def test_create_chat_answer(async_created_chat_answer):
24+
result = async_created_chat_answer
25+
26+
assert result is not None
27+
28+
29+
async def test_update_chat_answer(
30+
async_chat_answers_service, async_created_chat_answer, short_uuid
31+
):
32+
update_data = {"name": f"e2e updated answer {short_uuid}"}
33+
34+
result = await async_chat_answers_service.update(async_created_chat_answer.id, update_data)
35+
36+
assert result.id == async_created_chat_answer.id
37+
assert result.to_dict().get("name") == update_data["name"]
38+
39+
40+
async def test_submit_chat_answer(async_chat_answers_service, async_created_chat_answer):
41+
result = await async_chat_answers_service.submit(async_created_chat_answer.id)
42+
43+
assert result is not None
44+
45+
46+
async def test_query_chat_answer(async_chat_answers_service, async_created_chat_answer):
47+
submitted_chat_answer = await async_chat_answers_service.submit(async_created_chat_answer.id)
48+
49+
result = await async_chat_answers_service.query(submitted_chat_answer.id)
50+
51+
assert result is not None
52+
53+
54+
async def test_validate_chat_answer(async_chat_answers_service, async_created_chat_answer):
55+
result = await async_chat_answers_service.validate(
56+
async_created_chat_answer.id,
57+
{"parameters": []},
58+
)
59+
60+
assert result is not None
61+
62+
63+
async def test_accept_chat_answer(async_chat_answers_service, async_created_chat_answer):
64+
result = await async_chat_answers_service.accept(async_created_chat_answer.id)
65+
66+
assert result is not None
67+
68+
69+
async def test_delete_chat_answer(async_chat_answers_service, async_created_chat_answer):
70+
await async_chat_answers_service.delete(async_created_chat_answer.id) # act
71+
72+
73+
async def test_not_found(async_chat_answers_service, invalid_chat_answer_id):
74+
with pytest.raises(MPTAPIError):
75+
await async_chat_answers_service.get(invalid_chat_answer_id)

0 commit comments

Comments
 (0)