Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions mpt_api_client/mpt_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
AsyncBilling,
AsyncCatalog,
AsyncCommerce,
AsyncHelpdesk,
AsyncNotifications,
Audit,
Billing,
Catalog,
Commerce,
Helpdesk,
Notifications,
)

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

@property
def helpdesk(self) -> AsyncHelpdesk:
"""Helpdesk MPT API Client."""
return AsyncHelpdesk(http_client=self.http_client)


class MPTClient:
"""MPT API Client."""
Expand Down Expand Up @@ -128,3 +135,8 @@ def accounts(self) -> Accounts:
def notifications(self) -> Notifications:
"""Notifications MPT API Client."""
return Notifications(http_client=self.http_client)

@property
def helpdesk(self) -> Helpdesk:
"""Helpdesk MPT API Client."""
return Helpdesk(http_client=self.http_client)
3 changes: 3 additions & 0 deletions mpt_api_client/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from mpt_api_client.resources.billing import AsyncBilling, Billing
from mpt_api_client.resources.catalog import AsyncCatalog, Catalog
from mpt_api_client.resources.commerce import AsyncCommerce, Commerce
from mpt_api_client.resources.helpdesk import AsyncHelpdesk, Helpdesk
from mpt_api_client.resources.notifications import AsyncNotifications, Notifications

__all__ = [ # noqa: WPS410
Expand All @@ -12,10 +13,12 @@
"AsyncBilling",
"AsyncCatalog",
"AsyncCommerce",
"AsyncHelpdesk",
"AsyncNotifications",
"Audit",
"Billing",
"Catalog",
"Commerce",
"Helpdesk",
"Notifications",
]
3 changes: 3 additions & 0 deletions mpt_api_client/resources/helpdesk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from mpt_api_client.resources.helpdesk.helpdesk import AsyncHelpdesk, Helpdesk

__all__ = ["AsyncHelpdesk", "Helpdesk"] # noqa: WPS410
118 changes: 118 additions & 0 deletions mpt_api_client/resources/helpdesk/cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from mpt_api_client.http import AsyncService, Service
from mpt_api_client.http.mixins import (
AsyncCollectionMixin,
AsyncCreateMixin,
AsyncGetMixin,
AsyncUpdateMixin,
CollectionMixin,
CreateMixin,
GetMixin,
UpdateMixin,
)
from mpt_api_client.models import Model, ResourceData


class Case(Model):
"""Helpdesk case resource."""


class CasesServiceConfig:
"""Cases service configuration."""

_endpoint = "/public/v1/helpdesk/cases"
_model_class = Case
_collection_key = "data"


class CasesService(
CollectionMixin[Case],
CreateMixin[Case],
GetMixin[Case],
UpdateMixin[Case],
Service[Case],
CasesServiceConfig,
):
"""Cases service."""

def complete(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to complete state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return self._resource_action(resource_id, "POST", "complete", json=resource_data)

def process(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to process state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return self._resource_action(resource_id, "POST", "process", json=resource_data)

def query(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to query state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return self._resource_action(resource_id, "POST", "query", json=resource_data)


class AsyncCasesService(
AsyncCollectionMixin[Case],
AsyncCreateMixin[Case],
AsyncGetMixin[Case],
AsyncUpdateMixin[Case],
AsyncService[Case],
CasesServiceConfig,
):
"""Async cases service."""

async def complete(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to complete state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return await self._resource_action(resource_id, "POST", "complete", json=resource_data)

async def process(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to process state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return await self._resource_action(resource_id, "POST", "process", json=resource_data)

async def query(self, resource_id: str, resource_data: ResourceData | None = None) -> Case:
"""Switch case to query state.

Args:
resource_id: Case resource ID
resource_data: Case data will be updated

Returns:
Updated case resource
"""
return await self._resource_action(resource_id, "POST", "query", json=resource_data)
26 changes: 26 additions & 0 deletions mpt_api_client/resources/helpdesk/helpdesk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService


class Helpdesk:
"""Helpdesk MPT API Module."""

def __init__(self, http_client: HTTPClient):
self.http_client = http_client

@property
def cases(self) -> CasesService:
"""Cases service."""
return CasesService(http_client=self.http_client)


class AsyncHelpdesk:
"""Async Helpdesk MPT API Module."""

def __init__(self, http_client: AsyncHTTPClient):
self.http_client = http_client

@property
def cases(self) -> AsyncCasesService:
"""Cases service."""
return AsyncCasesService(http_client=self.http_client)
37 changes: 37 additions & 0 deletions tests/e2e/helpdesk/cases/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest


def _queue_id_from_case(case):
case_data = case.to_dict()
queue_data = case_data.get("queue")
if not isinstance(queue_data, dict):
return None

queue_id = queue_data.get("id")
if not isinstance(queue_id, str):
return None

return queue_id


@pytest.fixture
def queue_id(mpt_ops):
cases = mpt_ops.helpdesk.cases.fetch_page(limit=1)
if not cases:
pytest.skip("No support case available to infer queue for create test.")

queue_id = _queue_id_from_case(cases[0])
if queue_id is None:
pytest.skip("No queue id available to create support case.")

return queue_id


@pytest.fixture
def case_data(queue_id):
return {"queue": {"id": queue_id}}


@pytest.fixture
def case_update_data():
return {"awaiting": True}
48 changes: 48 additions & 0 deletions tests/e2e/helpdesk/cases/test_async_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import pytest

from mpt_api_client.exceptions import MPTAPIError

pytestmark = [pytest.mark.flaky]


@pytest.fixture
async def created_case(async_mpt_ops, case_data):
service = async_mpt_ops.helpdesk.cases
try:
return await service.create(case_data)
except MPTAPIError as error:
pytest.skip(f"Support case create is not available in this environment: {error.title}")


def test_create_case(created_case):
result = created_case.id

assert result is not None


async def test_get_case(async_mpt_ops, created_case):
service = async_mpt_ops.helpdesk.cases

result = await service.get(created_case.id)

assert result.id == created_case.id


async def test_update_case(
async_mpt_ops,
created_case,
case_update_data,
):
service = async_mpt_ops.helpdesk.cases

result = await service.update(created_case.id, case_update_data)

assert result.id == created_case.id


async def test_list_cases(async_mpt_ops):
service = async_mpt_ops.helpdesk.cases

result = await service.fetch_page(limit=1)

assert result is not None
44 changes: 44 additions & 0 deletions tests/e2e/helpdesk/cases/test_sync_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest

from mpt_api_client.exceptions import MPTAPIError

pytestmark = [pytest.mark.flaky]


@pytest.fixture
def created_case(mpt_ops, case_data):
service = mpt_ops.helpdesk.cases
try:
return service.create(case_data)
except MPTAPIError as error:
pytest.skip(f"Support case create is not available in this environment: {error.title}")


def test_create_case(created_case):
result = created_case.id

assert result is not None


def test_get_case(mpt_ops, created_case):
service = mpt_ops.helpdesk.cases

result = service.get(created_case.id)

assert result.id == created_case.id


def test_update_case(mpt_ops, created_case, case_update_data):
service = mpt_ops.helpdesk.cases

result = service.update(created_case.id, case_update_data)

assert result.id == created_case.id


def test_list_cases(mpt_ops):
service = mpt_ops.helpdesk.cases

result = service.fetch_page(limit=1)

assert result is not None
43 changes: 43 additions & 0 deletions tests/unit/resources/helpdesk/test_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pytest

from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService


@pytest.fixture
def cases_service(http_client):
return CasesService(http_client=http_client)


@pytest.fixture
def async_cases_service(async_http_client):
return AsyncCasesService(http_client=async_http_client)


@pytest.mark.parametrize(
"method", ["complete", "create", "get", "iterate", "process", "query", "update"]
)
def test_mixins_present(cases_service, method):
result = hasattr(cases_service, method)

assert result is True


@pytest.mark.parametrize(
"method", ["complete", "create", "get", "iterate", "process", "query", "update"]
)
def test_async_mixins_present(async_cases_service, method):
result = hasattr(async_cases_service, method)

assert result is True


def test_endpoint(cases_service):
result = cases_service.path == "/public/v1/helpdesk/cases"

assert result is True


def test_async_endpoint(async_cases_service):
result = async_cases_service.path == "/public/v1/helpdesk/cases"

assert result is True
Loading