Skip to content

Commit a34159c

Browse files
authored
Merge pull request #243
MPT-18370 Add helpdesk queues API services with unit and e2e test coverage
2 parents 1956bc6 + cb00019 commit a34159c

File tree

7 files changed

+308
-0
lines changed

7 files changed

+308
-0
lines changed

mpt_api_client/resources/helpdesk/helpdesk.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
22
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
33
from mpt_api_client.resources.helpdesk.chats import AsyncChatsService, ChatsService
4+
from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, QueuesService
45

56

67
class Helpdesk:
@@ -19,6 +20,11 @@ def cases(self) -> CasesService:
1920
"""Cases service."""
2021
return CasesService(http_client=self.http_client)
2122

23+
@property
24+
def queues(self) -> QueuesService:
25+
"""Queues service."""
26+
return QueuesService(http_client=self.http_client)
27+
2228

2329
class AsyncHelpdesk:
2430
"""Async Helpdesk MPT API Module."""
@@ -35,3 +41,8 @@ def chats(self) -> AsyncChatsService:
3541
def cases(self) -> AsyncCasesService:
3642
"""Async Cases service."""
3743
return AsyncCasesService(http_client=self.http_client)
44+
45+
@property
46+
def queues(self) -> AsyncQueuesService:
47+
"""Async Queues service."""
48+
return AsyncQueuesService(http_client=self.http_client)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import (
3+
AsyncCollectionMixin,
4+
AsyncManagedResourceMixin,
5+
CollectionMixin,
6+
ManagedResourceMixin,
7+
)
8+
from mpt_api_client.models import Model, ResourceData
9+
10+
11+
class Queue(Model):
12+
"""Helpdesk Queue resource."""
13+
14+
15+
class QueuesServiceConfig:
16+
"""Helpdesk Queues service configuration."""
17+
18+
_endpoint = "/public/v1/helpdesk/queues"
19+
_model_class = Queue
20+
_collection_key = "data"
21+
22+
23+
class QueuesService(
24+
ManagedResourceMixin[Queue],
25+
CollectionMixin[Queue],
26+
Service[Queue],
27+
QueuesServiceConfig,
28+
):
29+
"""Helpdesk Queues service."""
30+
31+
def activate(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
32+
"""Switch queue to active state."""
33+
return self._resource_action(resource_id, "POST", "activate", json=resource_data)
34+
35+
def disable(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
36+
"""Switch queue to disabled state."""
37+
return self._resource_action(resource_id, "POST", "disable", json=resource_data)
38+
39+
40+
class AsyncQueuesService(
41+
AsyncManagedResourceMixin[Queue],
42+
AsyncCollectionMixin[Queue],
43+
AsyncService[Queue],
44+
QueuesServiceConfig,
45+
):
46+
"""Async Helpdesk Queues service."""
47+
48+
async def activate(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
49+
"""Switch queue to active state."""
50+
return await self._resource_action(resource_id, "POST", "activate", json=resource_data)
51+
52+
async def disable(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
53+
"""Switch queue to disabled state."""
54+
return await self._resource_action(resource_id, "POST", "disable", json=resource_data)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 queue_data(short_uuid):
11+
return {
12+
"name": f"E2E Queue {short_uuid}",
13+
"description": "E2E Created Helpdesk Queue",
14+
}
15+
16+
17+
@pytest.fixture
18+
def invalid_queue_id():
19+
return "HQU-0000-0000"
20+
21+
22+
@pytest.fixture
23+
def created_queue(mpt_ops, queue_data):
24+
with create_fixture_resource_and_delete(mpt_ops.helpdesk.queues, queue_data) as queue:
25+
yield queue
26+
27+
28+
@pytest.fixture
29+
async def async_created_queue(async_mpt_ops, queue_data):
30+
async with async_create_fixture_resource_and_delete(
31+
async_mpt_ops.helpdesk.queues, queue_data
32+
) as queue:
33+
yield queue
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [pytest.mark.flaky]
6+
7+
8+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
9+
async def test_get_queue(async_mpt_ops, async_created_queue):
10+
result = await async_mpt_ops.helpdesk.queues.get(async_created_queue.id)
11+
12+
assert result.id == async_created_queue.id
13+
14+
15+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
16+
async def test_list_queues(async_mpt_ops):
17+
result = await async_mpt_ops.helpdesk.queues.fetch_page(limit=1)
18+
19+
assert len(result) > 0
20+
21+
22+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
23+
def test_create_queue(async_created_queue):
24+
result = async_created_queue
25+
26+
assert result is not None
27+
28+
29+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
30+
async def test_update_queue(async_mpt_ops, async_created_queue, short_uuid):
31+
update_data = {"description": f"e2e update {short_uuid}"}
32+
33+
result = await async_mpt_ops.helpdesk.queues.update(async_created_queue.id, update_data)
34+
35+
assert result.id == async_created_queue.id
36+
assert result.to_dict().get("description") == update_data["description"]
37+
38+
39+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
40+
async def test_activate_queue(async_mpt_ops, async_created_queue):
41+
result = await async_mpt_ops.helpdesk.queues.activate(async_created_queue.id)
42+
43+
assert result is not None
44+
45+
46+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
47+
async def test_disable_queue(async_mpt_ops, async_created_queue):
48+
result = await async_mpt_ops.helpdesk.queues.disable(async_created_queue.id)
49+
50+
assert result is not None
51+
52+
53+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
54+
async def test_delete_queue(async_mpt_ops, async_created_queue):
55+
await async_mpt_ops.helpdesk.queues.delete(async_created_queue.id) # act
56+
57+
58+
async def test_not_found(async_mpt_ops, invalid_queue_id):
59+
with pytest.raises(MPTAPIError):
60+
await async_mpt_ops.helpdesk.queues.get(invalid_queue_id)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [pytest.mark.flaky]
6+
7+
8+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
9+
def test_get_queue(mpt_ops, created_queue):
10+
result = mpt_ops.helpdesk.queues.get(created_queue.id)
11+
12+
assert result.id == created_queue.id
13+
14+
15+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
16+
def test_list_queues(mpt_ops):
17+
result = mpt_ops.helpdesk.queues.fetch_page(limit=1)
18+
19+
assert len(result) > 0
20+
21+
22+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
23+
def test_create_queue(created_queue):
24+
result = created_queue
25+
26+
assert result is not None
27+
28+
29+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
30+
def test_update_queue(mpt_ops, created_queue, short_uuid):
31+
update_data = {"description": f"e2e update {short_uuid}"}
32+
33+
result = mpt_ops.helpdesk.queues.update(created_queue.id, update_data)
34+
35+
assert result.id == created_queue.id
36+
assert result.to_dict().get("description") == update_data["description"]
37+
38+
39+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
40+
def test_activate_queue(mpt_ops, created_queue):
41+
result = mpt_ops.helpdesk.queues.activate(created_queue.id)
42+
43+
assert result is not None
44+
45+
46+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
47+
def test_disable_queue(mpt_ops, created_queue):
48+
result = mpt_ops.helpdesk.queues.disable(created_queue.id)
49+
50+
assert result is not None
51+
52+
53+
@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
54+
def test_delete_queue(mpt_ops, created_queue):
55+
mpt_ops.helpdesk.queues.delete(created_queue.id) # act
56+
57+
58+
def test_not_found(mpt_ops, invalid_queue_id):
59+
with pytest.raises(MPTAPIError):
60+
mpt_ops.helpdesk.queues.get(invalid_queue_id)

tests/unit/resources/helpdesk/test_helpdesk.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from mpt_api_client.resources.helpdesk import AsyncHelpdesk, Helpdesk
44
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
55
from mpt_api_client.resources.helpdesk.chats import AsyncChatsService, ChatsService
6+
from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, QueuesService
67

78

89
def test_helpdesk_init(http_client):
@@ -24,6 +25,7 @@ def test_async_helpdesk_init(async_http_client):
2425
[
2526
("chats", ChatsService),
2627
("cases", CasesService),
28+
("queues", QueuesService),
2729
],
2830
)
2931
def test_helpdesk_properties(http_client, attr_name, expected):
@@ -39,6 +41,7 @@ def test_helpdesk_properties(http_client, attr_name, expected):
3941
[
4042
("chats", AsyncChatsService),
4143
("cases", AsyncCasesService),
44+
("queues", AsyncQueuesService),
4245
],
4346
)
4447
def test_async_helpdesk_properties(async_http_client, attr_name, expected):
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import httpx
2+
import pytest
3+
import respx
4+
5+
from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, Queue, QueuesService
6+
7+
8+
def _request_content(action: str) -> bytes:
9+
if action == "activate":
10+
return b'{"id":"HQU-1234-5678","status":"Active"}'
11+
return b'{"id":"HQU-1234-5678","status":"Disabled"}'
12+
13+
14+
@pytest.fixture
15+
def queues_service(http_client):
16+
return QueuesService(http_client=http_client)
17+
18+
19+
@pytest.fixture
20+
def async_queues_service(async_http_client):
21+
return AsyncQueuesService(http_client=async_http_client)
22+
23+
24+
@pytest.mark.parametrize(
25+
"method",
26+
["get", "create", "update", "delete", "fetch_page", "iterate", "activate", "disable"],
27+
)
28+
def test_methods_present(queues_service, method):
29+
result = hasattr(queues_service, method)
30+
31+
assert result is True
32+
33+
34+
@pytest.mark.parametrize(
35+
"method",
36+
["get", "create", "update", "delete", "fetch_page", "iterate", "activate", "disable"],
37+
)
38+
def test_async_methods_present(async_queues_service, method):
39+
result = hasattr(async_queues_service, method)
40+
41+
assert result is True
42+
43+
44+
@pytest.mark.parametrize("action", ["activate", "disable"])
45+
def test_custom_resource_actions(queues_service, action):
46+
response_expected_data = {"id": "HQU-1234-5678", "status": "Updated"}
47+
with respx.mock:
48+
mock_route = respx.post(
49+
f"https://api.example.com/public/v1/helpdesk/queues/HQU-1234-5678/{action}"
50+
).mock(
51+
return_value=httpx.Response(
52+
status_code=httpx.codes.OK,
53+
headers={"content-type": "application/json"},
54+
json=response_expected_data,
55+
)
56+
)
57+
58+
result = getattr(queues_service, action)("HQU-1234-5678")
59+
60+
assert mock_route.call_count == 1
61+
request = mock_route.calls[0].request
62+
assert request.content == b""
63+
assert result.to_dict() == response_expected_data
64+
assert isinstance(result, Queue)
65+
66+
67+
@pytest.mark.parametrize("action", ["activate", "disable"])
68+
async def test_async_custom_resource_actions(async_queues_service, action):
69+
response_expected_data = {"id": "HQU-1234-5678", "status": "Updated"}
70+
with respx.mock:
71+
mock_route = respx.post(
72+
f"https://api.example.com/public/v1/helpdesk/queues/HQU-1234-5678/{action}"
73+
).mock(
74+
return_value=httpx.Response(
75+
status_code=httpx.codes.OK,
76+
headers={"content-type": "application/json"},
77+
json=response_expected_data,
78+
)
79+
)
80+
81+
result = await getattr(async_queues_service, action)("HQU-1234-5678")
82+
83+
assert mock_route.call_count == 1
84+
request = mock_route.calls[0].request
85+
assert request.content == b""
86+
assert result.to_dict() == response_expected_data
87+
assert isinstance(result, Queue)

0 commit comments

Comments
 (0)