Skip to content
Merged
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
11 changes: 11 additions & 0 deletions mpt_api_client/resources/helpdesk/helpdesk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
from mpt_api_client.resources.helpdesk.chats import AsyncChatsService, ChatsService
from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, QueuesService


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

@property
def queues(self) -> QueuesService:
"""Queues service."""
return QueuesService(http_client=self.http_client)


class AsyncHelpdesk:
"""Async Helpdesk MPT API Module."""
Expand All @@ -35,3 +41,8 @@ def chats(self) -> AsyncChatsService:
def cases(self) -> AsyncCasesService:
"""Async Cases service."""
return AsyncCasesService(http_client=self.http_client)

@property
def queues(self) -> AsyncQueuesService:
"""Async Queues service."""
return AsyncQueuesService(http_client=self.http_client)
54 changes: 54 additions & 0 deletions mpt_api_client/resources/helpdesk/queues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from mpt_api_client.http import AsyncService, Service
from mpt_api_client.http.mixins import (
AsyncCollectionMixin,
AsyncManagedResourceMixin,
CollectionMixin,
ManagedResourceMixin,
)
from mpt_api_client.models import Model, ResourceData


class Queue(Model):
"""Helpdesk Queue resource."""


class QueuesServiceConfig:
"""Helpdesk Queues service configuration."""

_endpoint = "/public/v1/helpdesk/queues"
_model_class = Queue
_collection_key = "data"


class QueuesService(
ManagedResourceMixin[Queue],
CollectionMixin[Queue],
Service[Queue],
QueuesServiceConfig,
):
"""Helpdesk Queues service."""

def activate(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
"""Switch queue to active state."""
return self._resource_action(resource_id, "POST", "activate", json=resource_data)

def disable(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
"""Switch queue to disabled state."""
return self._resource_action(resource_id, "POST", "disable", json=resource_data)


class AsyncQueuesService(
AsyncManagedResourceMixin[Queue],
AsyncCollectionMixin[Queue],
AsyncService[Queue],
QueuesServiceConfig,
):
"""Async Helpdesk Queues service."""

async def activate(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
"""Switch queue to active state."""
return await self._resource_action(resource_id, "POST", "activate", json=resource_data)

async def disable(self, resource_id: str, resource_data: ResourceData | None = None) -> Queue:
"""Switch queue to disabled state."""
return await self._resource_action(resource_id, "POST", "disable", json=resource_data)
33 changes: 33 additions & 0 deletions tests/e2e/helpdesk/queues/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest

from tests.e2e.helper import (
async_create_fixture_resource_and_delete,
create_fixture_resource_and_delete,
)


@pytest.fixture
def queue_data(short_uuid):
return {
"name": f"E2E Queue {short_uuid}",
"description": "E2E Created Helpdesk Queue",
}


@pytest.fixture
def invalid_queue_id():
return "HQU-0000-0000"


@pytest.fixture
def created_queue(mpt_ops, queue_data):
with create_fixture_resource_and_delete(mpt_ops.helpdesk.queues, queue_data) as queue:
yield queue


@pytest.fixture
async def async_created_queue(async_mpt_ops, queue_data):
async with async_create_fixture_resource_and_delete(
async_mpt_ops.helpdesk.queues, queue_data
) as queue:
yield queue
60 changes: 60 additions & 0 deletions tests/e2e/helpdesk/queues/test_async_queues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pytest

from mpt_api_client.exceptions import MPTAPIError

pytestmark = [pytest.mark.flaky]


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_get_queue(async_mpt_ops, async_created_queue):
result = await async_mpt_ops.helpdesk.queues.get(async_created_queue.id)

assert result.id == async_created_queue.id


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_list_queues(async_mpt_ops):
result = await async_mpt_ops.helpdesk.queues.fetch_page(limit=1)

assert len(result) > 0


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_create_queue(async_created_queue):
result = async_created_queue

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_update_queue(async_mpt_ops, async_created_queue, short_uuid):
update_data = {"description": f"e2e update {short_uuid}"}

result = await async_mpt_ops.helpdesk.queues.update(async_created_queue.id, update_data)

assert result.id == async_created_queue.id
assert result.to_dict().get("description") == update_data["description"]


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_activate_queue(async_mpt_ops, async_created_queue):
result = await async_mpt_ops.helpdesk.queues.activate(async_created_queue.id)

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_disable_queue(async_mpt_ops, async_created_queue):
result = await async_mpt_ops.helpdesk.queues.disable(async_created_queue.id)

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
async def test_delete_queue(async_mpt_ops, async_created_queue):
await async_mpt_ops.helpdesk.queues.delete(async_created_queue.id) # act


async def test_not_found(async_mpt_ops, invalid_queue_id):
with pytest.raises(MPTAPIError):
await async_mpt_ops.helpdesk.queues.get(invalid_queue_id)
60 changes: 60 additions & 0 deletions tests/e2e/helpdesk/queues/test_sync_queues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pytest

from mpt_api_client.exceptions import MPTAPIError

pytestmark = [pytest.mark.flaky]


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_get_queue(mpt_ops, created_queue):
result = mpt_ops.helpdesk.queues.get(created_queue.id)

assert result.id == created_queue.id


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_list_queues(mpt_ops):
result = mpt_ops.helpdesk.queues.fetch_page(limit=1)

assert len(result) > 0


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_create_queue(created_queue):
result = created_queue

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_update_queue(mpt_ops, created_queue, short_uuid):
update_data = {"description": f"e2e update {short_uuid}"}

result = mpt_ops.helpdesk.queues.update(created_queue.id, update_data)

assert result.id == created_queue.id
assert result.to_dict().get("description") == update_data["description"]


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_activate_queue(mpt_ops, created_queue):
result = mpt_ops.helpdesk.queues.activate(created_queue.id)

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_disable_queue(mpt_ops, created_queue):
result = mpt_ops.helpdesk.queues.disable(created_queue.id)

assert result is not None


@pytest.mark.skip(reason="Unskip after MPT-19124 completed")
def test_delete_queue(mpt_ops, created_queue):
mpt_ops.helpdesk.queues.delete(created_queue.id) # act


def test_not_found(mpt_ops, invalid_queue_id):
with pytest.raises(MPTAPIError):
mpt_ops.helpdesk.queues.get(invalid_queue_id)
3 changes: 3 additions & 0 deletions tests/unit/resources/helpdesk/test_helpdesk.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from mpt_api_client.resources.helpdesk import AsyncHelpdesk, Helpdesk
from mpt_api_client.resources.helpdesk.cases import AsyncCasesService, CasesService
from mpt_api_client.resources.helpdesk.chats import AsyncChatsService, ChatsService
from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, QueuesService


def test_helpdesk_init(http_client):
Expand All @@ -24,6 +25,7 @@ def test_async_helpdesk_init(async_http_client):
[
("chats", ChatsService),
("cases", CasesService),
("queues", QueuesService),
],
)
def test_helpdesk_properties(http_client, attr_name, expected):
Expand All @@ -39,6 +41,7 @@ def test_helpdesk_properties(http_client, attr_name, expected):
[
("chats", AsyncChatsService),
("cases", AsyncCasesService),
("queues", AsyncQueuesService),
],
)
def test_async_helpdesk_properties(async_http_client, attr_name, expected):
Expand Down
87 changes: 87 additions & 0 deletions tests/unit/resources/helpdesk/test_queues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import httpx
import pytest
import respx

from mpt_api_client.resources.helpdesk.queues import AsyncQueuesService, Queue, QueuesService


def _request_content(action: str) -> bytes:
if action == "activate":
return b'{"id":"HQU-1234-5678","status":"Active"}'
return b'{"id":"HQU-1234-5678","status":"Disabled"}'


@pytest.fixture
def queues_service(http_client):
return QueuesService(http_client=http_client)


@pytest.fixture
def async_queues_service(async_http_client):
return AsyncQueuesService(http_client=async_http_client)


@pytest.mark.parametrize(
"method",
["get", "create", "update", "delete", "fetch_page", "iterate", "activate", "disable"],
)
def test_methods_present(queues_service, method):
result = hasattr(queues_service, method)

assert result is True


@pytest.mark.parametrize(
"method",
["get", "create", "update", "delete", "fetch_page", "iterate", "activate", "disable"],
)
def test_async_methods_present(async_queues_service, method):
result = hasattr(async_queues_service, method)

assert result is True


@pytest.mark.parametrize("action", ["activate", "disable"])
def test_custom_resource_actions(queues_service, action):
response_expected_data = {"id": "HQU-1234-5678", "status": "Updated"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/helpdesk/queues/HQU-1234-5678/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
headers={"content-type": "application/json"},
json=response_expected_data,
)
)

result = getattr(queues_service, action)("HQU-1234-5678")

assert mock_route.call_count == 1
request = mock_route.calls[0].request
assert request.content == b""
assert result.to_dict() == response_expected_data
assert isinstance(result, Queue)


@pytest.mark.parametrize("action", ["activate", "disable"])
async def test_async_custom_resource_actions(async_queues_service, action):
response_expected_data = {"id": "HQU-1234-5678", "status": "Updated"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/helpdesk/queues/HQU-1234-5678/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
headers={"content-type": "application/json"},
json=response_expected_data,
)
)

result = await getattr(async_queues_service, action)("HQU-1234-5678")

assert mock_route.call_count == 1
request = mock_route.calls[0].request
assert request.content == b""
assert result.to_dict() == response_expected_data
assert isinstance(result, Queue)
Loading