Skip to content

Commit bddc175

Browse files
committed
feat: add helpdesk chat participants api with unit and e2e tests
1 parent c59571f commit bddc175

File tree

9 files changed

+349
-82
lines changed

9 files changed

+349
-82
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import (
3+
AsyncCollectionMixin,
4+
AsyncCreateMixin,
5+
AsyncDeleteMixin,
6+
AsyncUpdateMixin,
7+
CollectionMixin,
8+
CreateMixin,
9+
DeleteMixin,
10+
UpdateMixin,
11+
)
12+
from mpt_api_client.models import Model
13+
14+
15+
class ChatParticipant(Model):
16+
"""Helpdesk Chat Participant resource."""
17+
18+
19+
class ChatParticipantsServiceConfig:
20+
"""Helpdesk Chat Participants service configuration."""
21+
22+
_endpoint = "/public/v1/helpdesk/chats/{chat_id}/participants"
23+
_model_class = ChatParticipant
24+
_collection_key = "data"
25+
26+
27+
class ChatParticipantsService(
28+
CreateMixin[ChatParticipant],
29+
UpdateMixin[ChatParticipant],
30+
DeleteMixin,
31+
CollectionMixin[ChatParticipant],
32+
Service[ChatParticipant],
33+
ChatParticipantsServiceConfig,
34+
):
35+
"""Helpdesk Chat Participants service."""
36+
37+
38+
class AsyncChatParticipantsService(
39+
AsyncCreateMixin[ChatParticipant],
40+
AsyncUpdateMixin[ChatParticipant],
41+
AsyncDeleteMixin,
42+
AsyncCollectionMixin[ChatParticipant],
43+
AsyncService[ChatParticipant],
44+
ChatParticipantsServiceConfig,
45+
):
46+
"""Async Helpdesk Chat Participants service."""

mpt_api_client/resources/helpdesk/chats.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
AsyncChatMessagesService,
2323
ChatMessagesService,
2424
)
25+
from mpt_api_client.resources.helpdesk.chat_participants import (
26+
AsyncChatParticipantsService,
27+
ChatParticipantsService,
28+
)
2529

2630

2731
class Chat(Model):
@@ -62,6 +66,12 @@ def links(self, chat_id: str) -> ChatLinksService:
6266
"""Return chat links service."""
6367
return ChatLinksService(http_client=self.http_client, endpoint_params={"chat_id": chat_id})
6468

69+
def participants(self, chat_id: str) -> ChatParticipantsService:
70+
"""Return chat participants service."""
71+
return ChatParticipantsService(
72+
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
73+
)
74+
6575

6676
class AsyncChatsService(
6777
AsyncCreateMixin[Chat],
@@ -90,3 +100,9 @@ def links(self, chat_id: str) -> AsyncChatLinksService:
90100
return AsyncChatLinksService(
91101
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
92102
)
103+
104+
def participants(self, chat_id: str) -> AsyncChatParticipantsService:
105+
"""Return async chat participants service."""
106+
return AsyncChatParticipantsService(
107+
http_client=self.http_client, endpoint_params={"chat_id": chat_id}
108+
)

pyproject.toml

Lines changed: 83 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,51 @@ description = "SoftwareOne Marketplace API Client for Python"
55
authors = [{ name = "SoftwareOne AG" }]
66
requires-python = ">=3.12,<4"
77
readme = "docs/PROJECT_DESCRIPTION.md"
8-
license = {text = "Apache-2.0 license"}
8+
license = { text = "Apache-2.0 license" }
99
keywords = [
10-
"openapi",
11-
"client",
12-
"softwareone",
13-
"marketplace",
10+
"openapi",
11+
"client",
12+
"softwareone",
13+
"marketplace",
1414
]
1515
classifiers = [
16-
"Development Status :: 5 - Production/Stable",
17-
"Environment :: Console",
18-
"Operating System :: POSIX :: Linux",
19-
"Programming Language :: Python :: 3.12",
20-
"Topic :: Utilities",
16+
"Development Status :: 5 - Production/Stable",
17+
"Environment :: Console",
18+
"Operating System :: POSIX :: Linux",
19+
"Programming Language :: Python :: 3.12",
20+
"Topic :: Utilities",
2121
]
2222
dependencies = [
23-
"httpx==0.28.*",
23+
"httpx==0.28.*",
2424
]
2525

2626
[dependency-groups]
2727
dev = [
28-
"dependency-injector==4.48.*",
29-
"flake8==7.3.*", # force flake8 version to have same formatting everywhere, also update in pre-commit config
30-
"flake8-aaa==0.17.*", # also update pre-commit config
31-
"flake8-pyproject==1.2.*", # also update pre-commit config
32-
"freezegun==1.5.*",
33-
"ipdb==0.13.*",
34-
"ipython==9.*",
35-
"mypy==1.19.*",
36-
"pre-commit==4.5.*",
37-
"pyfakefs==6.1.*",
38-
"pytest==9.0.*",
39-
"pytest-asyncio==1.3.*",
40-
"pytest-cov==7.0.*",
41-
"pytest-deadfixtures==3.1.*",
42-
"pytest-mock==3.15.*",
43-
"pytest-randomly==4.0.*",
44-
"pytest-reportportal==5.6.*",
45-
"pytest-rerunfailures==16.1.*",
46-
"pytest-xdist==3.8.*",
47-
"responses==0.26.*",
48-
"respx==0.22.*",
49-
"ruff==0.15.*", # force ruff version to have same formatting everywhere
50-
"typing-extensions==4.15.*",
51-
"wemake-python-styleguide==1.6.*",
52-
"types-python-dateutil==2.9.*",
28+
"dependency-injector==4.48.*",
29+
"flake8==7.3.*", # force flake8 version to have same formatting everywhere, also update in pre-commit config
30+
"flake8-aaa==0.17.*", # also update pre-commit config
31+
"flake8-pyproject==1.2.*", # also update pre-commit config
32+
"freezegun==1.5.*",
33+
"ipdb==0.13.*",
34+
"ipython==9.*",
35+
"mypy==1.19.*",
36+
"pre-commit==4.5.*",
37+
"pyfakefs==6.1.*",
38+
"pytest==9.0.*",
39+
"pytest-asyncio==1.3.*",
40+
"pytest-cov==7.0.*",
41+
"pytest-deadfixtures==3.1.*",
42+
"pytest-mock==3.15.*",
43+
"pytest-randomly==4.0.*",
44+
"pytest-reportportal==5.6.*",
45+
"pytest-rerunfailures==16.1.*",
46+
"pytest-xdist==3.8.*",
47+
"responses==0.26.*",
48+
"respx==0.22.*",
49+
"ruff==0.15.*", # force ruff version to have same formatting everywhere
50+
"typing-extensions==4.15.*",
51+
"wemake-python-styleguide==1.6.*",
52+
"types-python-dateutil==2.9.*",
5353
]
5454

5555
[tool.hatch.build.targets.sdist]
@@ -70,8 +70,8 @@ log_cli = false
7070
asyncio_mode = "auto"
7171
asyncio_default_fixture_loop_scope = "function"
7272
filterwarnings = [
73-
"ignore:Support for class-based `config` is deprecated:DeprecationWarning",
74-
"ignore:pkg_resources is deprecated as an API:DeprecationWarning",
73+
"ignore:Support for class-based `config` is deprecated:DeprecationWarning",
74+
"ignore:pkg_resources is deprecated as an API:DeprecationWarning",
7575
]
7676
rp_project = "mpt-api-python-client"
7777
markers = [
@@ -85,11 +85,11 @@ source = ["mpt_api_client"]
8585

8686
[tool.coverage.report]
8787
exclude_also = [
88-
"if __name__ == \"__main__\":",
89-
"raise NotImplementedError",
88+
"if __name__ == \"__main__\":",
89+
"raise NotImplementedError",
9090
]
9191
omit = [
92-
"*/__init__.py"
92+
"*/__init__.py"
9393
]
9494

9595
[tool.flake8]
@@ -122,6 +122,7 @@ per-file-ignores = [
122122
"mpt_api_client/resources/catalog/*.py: WPS110 WPS214 WPS215 WPS235",
123123
"mpt_api_client/resources/catalog/products.py: WPS204 WPS214 WPS215 WPS235",
124124
"mpt_api_client/resources/commerce/*.py: WPS235 WPS215",
125+
"mpt_api_client/resources/helpdesk/*.py: WPS204 WPS215",
125126
"mpt_api_client/rql/query_builder.py: WPS110 WPS115 WPS210 WPS214",
126127
"tests/e2e/accounts/*.py: WPS430 WPS202",
127128
"tests/e2e/billing/*.py: WPS202 WPS421 WPS118",
@@ -157,48 +158,48 @@ docstring-code-format = false
157158

158159
[tool.ruff.lint]
159160
select = [
160-
"A", # flake8-builtins
161-
"B", # flake8-bugbear
162-
"C4", # flake8-comprehensions
163-
"C90", # maccabe
164-
"COM", # flake8-commas
165-
"D", # pydocstyle
166-
"DTZ", # flake8-datetimez
167-
"E", # pycodestyle
168-
"ERA", # flake8-eradicate
169-
"EXE", # flake8-executable
170-
"F", # pyflakes
171-
"FBT", # flake8-boolean-trap
172-
"FLY", # pyflint
161+
"A", # flake8-builtins
162+
"B", # flake8-bugbear
163+
"C4", # flake8-comprehensions
164+
"C90", # maccabe
165+
"COM", # flake8-commas
166+
"D", # pydocstyle
167+
"DTZ", # flake8-datetimez
168+
"E", # pycodestyle
169+
"ERA", # flake8-eradicate
170+
"EXE", # flake8-executable
171+
"F", # pyflakes
172+
"FBT", # flake8-boolean-trap
173+
"FLY", # pyflint
173174
"FURB", # refurb
174-
"G", # flake8-logging-format
175-
"I", # isort
176-
"ICN", # flake8-import-conventions
177-
"ISC", # flake8-implicit-str-concat
178-
"LOG", # flake8-logging
179-
"N", # pep8-naming
175+
"G", # flake8-logging-format
176+
"I", # isort
177+
"ICN", # flake8-import-conventions
178+
"ISC", # flake8-implicit-str-concat
179+
"LOG", # flake8-logging
180+
"N", # pep8-naming
180181
"PERF", # perflint
181-
"PIE", # flake8-pie
182-
"PL", # pylint
183-
"PT", # flake8-pytest-style
184-
"PTH", # flake8-use-pathlib
185-
"Q", # flake8-quotes
186-
"RET", # flake8-return
187-
"RSE", # flake8-raise
188-
"RUF", # ruff
189-
"S", # flake8-bandit
190-
"SIM", # flake8-simpify
191-
"SLF", # flake8-self
182+
"PIE", # flake8-pie
183+
"PL", # pylint
184+
"PT", # flake8-pytest-style
185+
"PTH", # flake8-use-pathlib
186+
"Q", # flake8-quotes
187+
"RET", # flake8-return
188+
"RSE", # flake8-raise
189+
"RUF", # ruff
190+
"S", # flake8-bandit
191+
"SIM", # flake8-simpify
192+
"SLF", # flake8-self
192193
"SLOT", # flake8-slots
193194
"T100", # flake8-debugger
194-
"TRY", # tryceratops
195-
"UP", # pyupgrade
196-
"W", # pycodestyle
197-
"YTT", # flake8-2020
195+
"TRY", # tryceratops
196+
"UP", # pyupgrade
197+
"W", # pycodestyle
198+
"YTT", # flake8-2020
198199
]
199200
ignore = [
200-
"A005", # allow to shadow stdlib and builtin module names
201-
"B904", # Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
201+
"A005", # allow to shadow stdlib and builtin module names
202+
"B904", # Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
202203
"COM812", # trailing comma, conflicts with `ruff format`
203204
# Different doc rules that we don't really care about:
204205
"D100",
@@ -211,15 +212,15 @@ ignore = [
211212
"D401",
212213
"D404",
213214
"D405",
214-
"ISC001", # implicit string concat conflicts with `ruff format`
215-
"ISC003", # prefer explicit string concat over implicit concat
216-
"PLR09", # we have our own complexity rules
215+
"ISC001", # implicit string concat conflicts with `ruff format`
216+
"ISC003", # prefer explicit string concat over implicit concat
217+
"PLR09", # we have our own complexity rules
217218
"PLR2004", # do not report magic numbers
218219
"PLR6301", # do not require classmethod / staticmethod when self not used
219220
"PT011", # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception
220-
"TRY003", # long exception messages from `tryceratops`
221+
"TRY003", # long exception messages from `tryceratops`
221222
]
222-
external = [ "AAA", "WPS" ]
223+
external = ["AAA", "WPS"]
223224

224225
# Plugin configs:
225226
[tool.ruff.lint.flake8-import-conventions]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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_participants_service(mpt_ops, chat_id):
11+
return mpt_ops.helpdesk.chats.participants(chat_id)
12+
13+
14+
@pytest.fixture
15+
def async_chat_participants_service(async_mpt_ops, chat_id):
16+
return async_mpt_ops.helpdesk.chats.participants(chat_id)
17+
18+
19+
@pytest.fixture
20+
def chat_participant_data(account_id, user_id):
21+
return {
22+
"identity": {"id": user_id},
23+
"account": {"id": account_id},
24+
}
25+
26+
27+
@pytest.fixture
28+
def created_chat_participant(chat_participants_service, chat_participant_data):
29+
with create_fixture_resource_and_delete(
30+
chat_participants_service, chat_participant_data
31+
) as chat_participant:
32+
yield chat_participant
33+
34+
35+
@pytest.fixture
36+
async def async_created_chat_participant(async_chat_participants_service, chat_participant_data):
37+
async with async_create_fixture_resource_and_delete(
38+
async_chat_participants_service, chat_participant_data
39+
) as chat_participant:
40+
yield chat_participant
41+
42+
43+
@pytest.fixture
44+
def invalid_chat_participant_id():
45+
return "CHP-0000-0000-0000"

0 commit comments

Comments
 (0)