Skip to content

Commit f5d63dc

Browse files
author
Robert Segal
committed
Add additional mixin tests for activatable resource
1 parent 3524b0b commit f5d63dc

File tree

3 files changed

+205
-25
lines changed

3 files changed

+205
-25
lines changed

mpt_api_client/resources/catalog/mixins.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from mpt_api_client.models import ResourceData
22

33

4+
# TODO: Consider moving publishable and activatable mixins to http/mixins
45
class PublishableMixin[Model]:
56
"""Publishable mixin adds the ability to review, publish and unpublish."""
67

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ per-file-ignores =
4141
tests/http/test_service.py: WPS204 WPS202
4242
tests/http/test_mixins.py: WPS204 WPS202
4343
tests/resources/catalog/test_products.py: WPS202 WPS210
44+
tests/resources/catalog/test_mixins.py: WPS118 WPS202 WPS204
4445

4546
tests/*:
4647
# Allow magic strings.

tests/resources/catalog/test_mixins.py

Lines changed: 203 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,69 @@
22
import pytest
33
import respx
44

5-
from mpt_api_client.resources.catalog.products import AsyncProductsService, Product, ProductsService
5+
from mpt_api_client.http.async_service import AsyncService
6+
from mpt_api_client.http.service import Service
7+
from mpt_api_client.resources.catalog.mixins import (
8+
ActivatableMixin,
9+
AsyncActivatableMixin,
10+
AsyncPublishableMixin,
11+
PublishableMixin,
12+
)
13+
from tests.conftest import DummyModel
14+
15+
16+
class DummyPublishableService( # noqa: WPS215
17+
PublishableMixin[DummyModel],
18+
Service[DummyModel],
19+
):
20+
_endpoint = "/public/v1/dummy/publishable/"
21+
_model_class = DummyModel
22+
_collection_key = "data"
23+
24+
25+
class DummyAsyncPublishableService( # noqa: WPS215
26+
AsyncPublishableMixin[DummyModel],
27+
AsyncService[DummyModel],
28+
):
29+
_endpoint = "/public/v1/dummy/publishable/"
30+
_model_class = DummyModel
31+
_collection_key = "data"
32+
33+
34+
class DummyActivatableService( # noqa: WPS215
35+
ActivatableMixin[DummyModel],
36+
Service[DummyModel],
37+
):
38+
_endpoint = "/public/v1/dummy/activatable/"
39+
_model_class = DummyModel
40+
41+
42+
class DummyAsyncActivatableService( # noqa: WPS215
43+
AsyncActivatableMixin[DummyModel],
44+
AsyncService[DummyModel],
45+
):
46+
_endpoint = "/public/v1/dummy/activatable/"
47+
_model_class = DummyModel
48+
49+
50+
@pytest.fixture
51+
def publishable_service(http_client):
52+
return DummyPublishableService(http_client=http_client)
653

754

855
@pytest.fixture
9-
def product_service(http_client):
10-
return ProductsService(http_client=http_client)
56+
def async_publishable_service(async_http_client):
57+
return DummyAsyncPublishableService(http_client=async_http_client)
1158

1259

1360
@pytest.fixture
14-
def async_product_service(async_http_client):
15-
return AsyncProductsService(http_client=async_http_client)
61+
def activatable_service(http_client):
62+
return DummyActivatableService(http_client=http_client)
63+
64+
65+
@pytest.fixture
66+
def async_activatable_service(async_http_client):
67+
return DummyAsyncActivatableService(http_client=async_http_client)
1668

1769

1870
@pytest.mark.parametrize(
@@ -23,27 +75,27 @@ def async_product_service(async_http_client):
2375
("unpublish", {"id": "PRD-123", "status": "update"}),
2476
],
2577
)
26-
def test_custom_resource_actions(product_service, action, input_status):
78+
def test_custom_resource_actions(publishable_service, action, input_status):
2779
request_expected_content = b'{"id":"PRD-123","status":"update"}'
2880
response_expected_data = {"id": "PRD-123", "status": "new_status"}
2981
with respx.mock:
3082
mock_route = respx.post(
31-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
83+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
3284
).mock(
3385
return_value=httpx.Response(
34-
status_code=200,
86+
status_code=httpx.codes.OK,
3587
headers={"content-type": "application/json"},
3688
json=response_expected_data,
3789
)
3890
)
39-
order = getattr(product_service, action)("PRD-123", input_status)
91+
order = getattr(publishable_service, action)("PRD-123", input_status)
4092

4193
assert mock_route.call_count == 1
4294
request = mock_route.calls[0].request
4395

4496
assert request.content == request_expected_content
4597
assert order.to_dict() == response_expected_data
46-
assert isinstance(order, Product)
98+
assert isinstance(order, DummyModel)
4799

48100

49101
@pytest.mark.parametrize(
@@ -54,27 +106,27 @@ def test_custom_resource_actions(product_service, action, input_status):
54106
("unpublish", None),
55107
],
56108
)
57-
def test_custom_resource_actions_no_data(product_service, action, input_status):
109+
def test_custom_resource_actions_no_data(publishable_service, action, input_status):
58110
request_expected_content = b""
59111
response_expected_data = {"id": "PRD-123", "status": "new_status"}
60112
with respx.mock:
61113
mock_route = respx.post(
62-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
114+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
63115
).mock(
64116
return_value=httpx.Response(
65-
status_code=200,
117+
status_code=httpx.codes.OK,
66118
headers={"content-type": "application/json"},
67119
json=response_expected_data,
68120
)
69121
)
70122

71-
order = getattr(product_service, action)("PRD-123")
123+
order = getattr(publishable_service, action)("PRD-123")
72124

73125
assert mock_route.call_count == 1
74126
request = mock_route.calls[0].request
75127
assert request.content == request_expected_content
76128
assert order.to_dict() == response_expected_data
77-
assert isinstance(order, Product)
129+
assert isinstance(order, DummyModel)
78130

79131

80132
@pytest.mark.parametrize(
@@ -85,27 +137,27 @@ def test_custom_resource_actions_no_data(product_service, action, input_status):
85137
("unpublish", {"id": "PRD-123", "status": "update"}),
86138
],
87139
)
88-
async def test_async_custom_resource_actions(async_product_service, action, input_status):
140+
async def test_async_custom_resource_actions(async_publishable_service, action, input_status):
89141
request_expected_content = b'{"id":"PRD-123","status":"update"}'
90142
response_expected_data = {"id": "PRD-123", "status": "new_status"}
91143
with respx.mock:
92144
mock_route = respx.post(
93-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
145+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
94146
).mock(
95147
return_value=httpx.Response(
96-
status_code=200,
148+
status_code=httpx.codes.OK,
97149
headers={"content-type": "application/json"},
98150
json=response_expected_data,
99151
)
100152
)
101-
order = await getattr(async_product_service, action)("PRD-123", input_status)
153+
order = await getattr(async_publishable_service, action)("PRD-123", input_status)
102154

103155
assert mock_route.call_count == 1
104156
request = mock_route.calls[0].request
105157

106158
assert request.content == request_expected_content
107159
assert order.to_dict() == response_expected_data
108-
assert isinstance(order, Product)
160+
assert isinstance(order, DummyModel)
109161

110162

111163
@pytest.mark.parametrize(
@@ -116,24 +168,150 @@ async def test_async_custom_resource_actions(async_product_service, action, inpu
116168
("unpublish", None),
117169
],
118170
)
119-
async def test_async_custom_resource_actions_no_data(async_product_service, action, input_status):
171+
async def test_async_custom_resource_actions_no_data(
172+
async_publishable_service, action, input_status
173+
):
120174
request_expected_content = b""
121175
response_expected_data = {"id": "PRD-123", "status": "new_status"}
122176
with respx.mock:
123177
mock_route = respx.post(
124-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
178+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
125179
).mock(
126180
return_value=httpx.Response(
127-
status_code=200,
181+
status_code=httpx.codes.OK,
128182
headers={"content-type": "application/json"},
129183
json=response_expected_data,
130184
)
131185
)
132186

133-
order = await getattr(async_product_service, action)("PRD-123")
187+
order = await getattr(async_publishable_service, action)("PRD-123")
134188

135189
assert mock_route.call_count == 1
136190
request = mock_route.calls[0].request
137191
assert request.content == request_expected_content
138192
assert order.to_dict() == response_expected_data
139-
assert isinstance(order, Product)
193+
assert isinstance(order, DummyModel)
194+
195+
196+
@pytest.mark.parametrize(
197+
("action", "input_status"),
198+
[
199+
("activate", {"id": "OBJ-0000-0001", "status": "update"}),
200+
("deactivate", {"id": "OBJ-0000-0001", "status": "update"}),
201+
],
202+
)
203+
def test_custom_resource_activatable_actions(activatable_service, action, input_status):
204+
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
205+
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
206+
with respx.mock:
207+
mock_route = respx.post(
208+
f"https://api.example.com/public/v1/dummy/activatable/OBJ-0000-0001/{action}"
209+
).mock(
210+
return_value=httpx.Response(
211+
status_code=httpx.codes.OK,
212+
headers={"content-type": "application/json"},
213+
json=response_expected_data,
214+
)
215+
)
216+
attachment = getattr(activatable_service, action)("OBJ-0000-0001", input_status)
217+
218+
assert mock_route.call_count == 1
219+
request = mock_route.calls[0].request
220+
221+
assert request.content == request_expected_content
222+
assert attachment.to_dict() == response_expected_data
223+
assert isinstance(attachment, DummyModel)
224+
225+
226+
@pytest.mark.parametrize(
227+
("action", "input_status"),
228+
[
229+
("activate", None),
230+
("deactivate", None),
231+
],
232+
)
233+
def test_custom_resource_activatable_actions_no_data(activatable_service, action, input_status):
234+
request_expected_content = b""
235+
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
236+
with respx.mock:
237+
mock_route = respx.post(
238+
f"https://api.example.com/public/v1/dummy/activatable/OBJ-0000-0001/{action}"
239+
).mock(
240+
return_value=httpx.Response(
241+
status_code=httpx.codes.OK,
242+
headers={"content-type": "application/json"},
243+
json=response_expected_data,
244+
)
245+
)
246+
attachment = getattr(activatable_service, action)("OBJ-0000-0001", input_status)
247+
248+
assert mock_route.call_count == 1
249+
request = mock_route.calls[0].request
250+
251+
assert request.content == request_expected_content
252+
assert attachment.to_dict() == response_expected_data
253+
assert isinstance(attachment, DummyModel)
254+
255+
256+
@pytest.mark.parametrize(
257+
("action", "input_status"),
258+
[
259+
("activate", {"id": "OBJ-0000-0001", "status": "update"}),
260+
("deactivate", {"id": "OBJ-0000-0001", "status": "update"}),
261+
],
262+
)
263+
async def test_async_custom_resource_activatable_actions(
264+
async_activatable_service, action, input_status
265+
):
266+
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
267+
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
268+
with respx.mock:
269+
mock_route = respx.post(
270+
f"https://api.example.com/public/v1/dummy/activatable/OBJ-0000-0001/{action}"
271+
).mock(
272+
return_value=httpx.Response(
273+
status_code=httpx.codes.OK,
274+
headers={"content-type": "application/json"},
275+
json=response_expected_data,
276+
)
277+
)
278+
attachment = await getattr(async_activatable_service, action)("OBJ-0000-0001", input_status)
279+
280+
assert mock_route.call_count == 1
281+
request = mock_route.calls[0].request
282+
283+
assert request.content == request_expected_content
284+
assert attachment.to_dict() == response_expected_data
285+
assert isinstance(attachment, DummyModel)
286+
287+
288+
@pytest.mark.parametrize(
289+
("action", "input_status"),
290+
[
291+
("activate", None),
292+
("deactivate", None),
293+
],
294+
)
295+
async def test_async_custom_resource_activatable_actions_no_data(
296+
async_activatable_service, action, input_status
297+
):
298+
request_expected_content = b""
299+
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
300+
with respx.mock:
301+
mock_route = respx.post(
302+
f"https://api.example.com/public/v1/dummy/activatable/OBJ-0000-0001/{action}"
303+
).mock(
304+
return_value=httpx.Response(
305+
status_code=httpx.codes.OK,
306+
headers={"content-type": "application/json"},
307+
json=response_expected_data,
308+
)
309+
)
310+
attachment = await getattr(async_activatable_service, action)("OBJ-0000-0001", input_status)
311+
312+
assert mock_route.call_count == 1
313+
request = mock_route.calls[0].request
314+
315+
assert request.content == request_expected_content
316+
assert attachment.to_dict() == response_expected_data
317+
assert isinstance(attachment, DummyModel)

0 commit comments

Comments
 (0)