Skip to content

Commit 256e648

Browse files
committed
feat: add helpdesk cases services and tests
1 parent d0c4a94 commit 256e648

File tree

11 files changed

+376
-0
lines changed

11 files changed

+376
-0
lines changed

mpt_api_client/mpt_client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
AsyncBilling,
99
AsyncCatalog,
1010
AsyncCommerce,
11+
AsyncHelpdesk,
1112
AsyncNotifications,
1213
Audit,
1314
Billing,
1415
Catalog,
1516
Commerce,
17+
Helpdesk,
1618
Notifications,
1719
)
1820

@@ -70,6 +72,11 @@ def notifications(self) -> AsyncNotifications:
7072
"""Notifications MPT API Client."""
7173
return AsyncNotifications(http_client=self.http_client)
7274

75+
@property
76+
def helpdesk(self) -> AsyncHelpdesk:
77+
"""Helpdesk MPT API Client."""
78+
return AsyncHelpdesk(http_client=self.http_client)
79+
7380

7481
class MPTClient:
7582
"""MPT API Client."""
@@ -128,3 +135,8 @@ def accounts(self) -> Accounts:
128135
def notifications(self) -> Notifications:
129136
"""Notifications MPT API Client."""
130137
return Notifications(http_client=self.http_client)
138+
139+
@property
140+
def helpdesk(self) -> Helpdesk:
141+
"""Helpdesk MPT API Client."""
142+
return Helpdesk(http_client=self.http_client)

mpt_api_client/resources/__init__.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.billing import AsyncBilling, Billing
44
from mpt_api_client.resources.catalog import AsyncCatalog, Catalog
55
from mpt_api_client.resources.commerce import AsyncCommerce, Commerce
6+
from mpt_api_client.resources.helpdesk import AsyncHelpdesk, Helpdesk
67
from mpt_api_client.resources.notifications import AsyncNotifications, Notifications
78

89
__all__ = [ # noqa: WPS410
@@ -12,10 +13,12 @@
1213
"AsyncBilling",
1314
"AsyncCatalog",
1415
"AsyncCommerce",
16+
"AsyncHelpdesk",
1517
"AsyncNotifications",
1618
"Audit",
1719
"Billing",
1820
"Catalog",
1921
"Commerce",
22+
"Helpdesk",
2023
"Notifications",
2124
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from mpt_api_client.resources.helpdesk.helpdesk import AsyncHelpdesk, Helpdesk
2+
3+
__all__ = ["AsyncHelpdesk", "Helpdesk"] # noqa: WPS410
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import (
3+
AsyncCollectionMixin,
4+
AsyncCreateMixin,
5+
AsyncGetMixin,
6+
AsyncUpdateMixin,
7+
CollectionMixin,
8+
CreateMixin,
9+
GetMixin,
10+
UpdateMixin,
11+
)
12+
from mpt_api_client.models import Model, ResourceData
13+
14+
15+
class Case(Model):
16+
"""Helpdesk case resource."""
17+
18+
19+
class CasesServiceConfig:
20+
"""Cases service configuration."""
21+
22+
_endpoint = "/public/v1/helpdesk/cases"
23+
_model_class = Case
24+
_collection_key = "data"
25+
26+
27+
class CasesService(
28+
CollectionMixin[Case],
29+
CreateMixin[Case],
30+
GetMixin[Case],
31+
UpdateMixin[Case],
32+
Service[Case],
33+
CasesServiceConfig,
34+
):
35+
"""Cases service."""
36+
37+
def complete(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
38+
"""Switch case to complete state.
39+
40+
Args:
41+
resource_id: Case resource ID
42+
resource_data: Case data will be updated
43+
44+
Returns:
45+
Updated case resource
46+
"""
47+
return self._resource_action(resource_id, "POST", "complete", json=resource_data)
48+
49+
def process(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
50+
"""Switch case to process state.
51+
52+
Args:
53+
resource_id: Case resource ID
54+
resource_data: Case data will be updated
55+
56+
Returns:
57+
Updated case resource
58+
"""
59+
return self._resource_action(resource_id, "POST", "process", json=resource_data)
60+
61+
def query(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
62+
"""Switch case to query state.
63+
64+
Args:
65+
resource_id: Case resource ID
66+
resource_data: Case data will be updated
67+
68+
Returns:
69+
Updated case resource
70+
"""
71+
return self._resource_action(resource_id, "POST", "query", json=resource_data)
72+
73+
74+
class AsyncCasesService(
75+
AsyncCollectionMixin[Case],
76+
AsyncCreateMixin[Case],
77+
AsyncGetMixin[Case],
78+
AsyncUpdateMixin[Case],
79+
AsyncService[Case],
80+
CasesServiceConfig,
81+
):
82+
"""Async cases service."""
83+
84+
async def complete(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
85+
"""Switch case to complete state.
86+
87+
Args:
88+
resource_id: Case resource ID
89+
resource_data: Case data will be updated
90+
91+
Returns:
92+
Updated case resource
93+
"""
94+
return await self._resource_action(resource_id, "POST", "complete", json=resource_data)
95+
96+
async def process(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
97+
"""Switch case to process state.
98+
99+
Args:
100+
resource_id: Case resource ID
101+
resource_data: Case data will be updated
102+
103+
Returns:
104+
Updated case resource
105+
"""
106+
return await self._resource_action(resource_id, "POST", "process", json=resource_data)
107+
108+
async def query(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
109+
"""Switch case to query state.
110+
111+
Args:
112+
resource_id: Case resource ID
113+
resource_data: Case data will be updated
114+
115+
Returns:
116+
Updated case resource
117+
"""
118+
return await self._resource_action(resource_id, "POST", "query", json=resource_data)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
2+
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
3+
4+
5+
class Helpdesk:
6+
"""Helpdesk MPT API Module."""
7+
8+
def __init__(self, http_client: HTTPClient):
9+
self.http_client = http_client
10+
11+
@property
12+
def cases(self) -> CasesService:
13+
"""Cases service."""
14+
return CasesService(http_client=self.http_client)
15+
16+
17+
class AsyncHelpdesk:
18+
"""Async Helpdesk MPT API Module."""
19+
20+
def __init__(self, http_client: AsyncHTTPClient):
21+
self.http_client = http_client
22+
23+
@property
24+
def cases(self) -> AsyncCasesService:
25+
"""Cases service."""
26+
return AsyncCasesService(http_client=self.http_client)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import pytest
2+
3+
4+
def _queue_id_from_case(case):
5+
case_data = case.to_dict()
6+
queue_data = case_data.get("queue")
7+
if not isinstance(queue_data, dict):
8+
return None
9+
10+
queue_id = queue_data.get("id")
11+
if not isinstance(queue_id, str):
12+
return None
13+
14+
return queue_id
15+
16+
17+
@pytest.fixture
18+
def queue_id(mpt_ops):
19+
cases = mpt_ops.helpdesk.cases.fetch_page(limit=1)
20+
if not cases:
21+
pytest.skip("No support case available to infer queue for create test.")
22+
23+
queue_id = _queue_id_from_case(cases[0])
24+
if queue_id is None:
25+
pytest.skip("No queue id available to create support case.")
26+
27+
return queue_id
28+
29+
30+
@pytest.fixture
31+
def case_data(queue_id):
32+
return {"queue": {"id": queue_id}}
33+
34+
35+
@pytest.fixture
36+
def case_update_data():
37+
return {"awaiting": True}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [pytest.mark.flaky]
6+
7+
8+
@pytest.fixture
9+
async def created_case(async_mpt_ops, case_data):
10+
service = async_mpt_ops.helpdesk.cases
11+
try:
12+
return await service.create(case_data)
13+
except MPTAPIError as error:
14+
pytest.skip(f"Support case create is not available in this environment: {error.title}")
15+
16+
17+
def test_create_case(created_case):
18+
result = created_case.id
19+
20+
assert result is not None
21+
22+
23+
async def test_get_case(async_mpt_ops, created_case):
24+
service = async_mpt_ops.helpdesk.cases
25+
26+
result = await service.get(created_case.id)
27+
28+
assert result.id == created_case.id
29+
30+
31+
async def test_update_case(
32+
async_mpt_ops,
33+
created_case,
34+
case_update_data,
35+
):
36+
service = async_mpt_ops.helpdesk.cases
37+
38+
result = await service.update(created_case.id, case_update_data)
39+
40+
assert result.id == created_case.id
41+
42+
43+
async def test_list_cases(async_mpt_ops):
44+
service = async_mpt_ops.helpdesk.cases
45+
46+
result = await service.fetch_page(limit=1)
47+
48+
assert result is not None
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
5+
pytestmark = [pytest.mark.flaky]
6+
7+
8+
@pytest.fixture
9+
def created_case(mpt_ops, case_data):
10+
service = mpt_ops.helpdesk.cases
11+
try:
12+
return service.create(case_data)
13+
except MPTAPIError as error:
14+
pytest.skip(f"Support case create is not available in this environment: {error.title}")
15+
16+
17+
def test_create_case(created_case):
18+
result = created_case.id
19+
20+
assert result is not None
21+
22+
23+
def test_get_case(mpt_ops, created_case):
24+
service = mpt_ops.helpdesk.cases
25+
26+
result = service.get(created_case.id)
27+
28+
assert result.id == created_case.id
29+
30+
31+
def test_update_case(mpt_ops, created_case, case_update_data):
32+
service = mpt_ops.helpdesk.cases
33+
34+
result = service.update(created_case.id, case_update_data)
35+
36+
assert result.id == created_case.id
37+
38+
39+
def test_list_cases(mpt_ops):
40+
service = mpt_ops.helpdesk.cases
41+
42+
result = service.fetch_page(limit=1)
43+
44+
assert result is not None
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
3+
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
4+
5+
6+
@pytest.fixture
7+
def cases_service(http_client):
8+
return CasesService(http_client=http_client)
9+
10+
11+
@pytest.fixture
12+
def async_cases_service(async_http_client):
13+
return AsyncCasesService(http_client=async_http_client)
14+
15+
16+
@pytest.mark.parametrize(
17+
"method", ["complete", "create", "get", "iterate", "process", "query", "update"]
18+
)
19+
def test_mixins_present(cases_service, method):
20+
result = hasattr(cases_service, method)
21+
22+
assert result is True
23+
24+
25+
@pytest.mark.parametrize(
26+
"method", ["complete", "create", "get", "iterate", "process", "query", "update"]
27+
)
28+
def test_async_mixins_present(async_cases_service, method):
29+
result = hasattr(async_cases_service, method)
30+
31+
assert result is True
32+
33+
34+
def test_endpoint(cases_service):
35+
result = cases_service.path == "/public/v1/helpdesk/cases"
36+
37+
assert result is True
38+
39+
40+
def test_async_endpoint(async_cases_service):
41+
result = async_cases_service.path == "/public/v1/helpdesk/cases"
42+
43+
assert result is True

0 commit comments

Comments
 (0)