Skip to content

Commit a296919

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

File tree

3 files changed

+207
-25
lines changed

3 files changed

+207
-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: 205 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,71 @@
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+
_collection_key = "data"
41+
42+
43+
class DummyAsyncActivatableService( # noqa: WPS215
44+
AsyncActivatableMixin[DummyModel],
45+
AsyncService[DummyModel],
46+
):
47+
_endpoint = "/public/v1/dummy/activatable/"
48+
_model_class = DummyModel
49+
_collection_key = "data"
50+
51+
52+
@pytest.fixture
53+
def publishable_service(http_client):
54+
return DummyPublishableService(http_client=http_client)
655

756

857
@pytest.fixture
9-
def product_service(http_client):
10-
return ProductsService(http_client=http_client)
58+
def async_publishable_service(async_http_client):
59+
return DummyAsyncPublishableService(http_client=async_http_client)
1160

1261

1362
@pytest.fixture
14-
def async_product_service(async_http_client):
15-
return AsyncProductsService(http_client=async_http_client)
63+
def activatable_service(http_client):
64+
return DummyActivatableService(http_client=http_client)
65+
66+
67+
@pytest.fixture
68+
def async_activatable_service(async_http_client):
69+
return DummyAsyncActivatableService(http_client=async_http_client)
1670

1771

1872
@pytest.mark.parametrize(
@@ -23,27 +77,27 @@ def async_product_service(async_http_client):
2377
("unpublish", {"id": "PRD-123", "status": "update"}),
2478
],
2579
)
26-
def test_custom_resource_actions(product_service, action, input_status):
80+
def test_custom_resource_actions(publishable_service, action, input_status):
2781
request_expected_content = b'{"id":"PRD-123","status":"update"}'
2882
response_expected_data = {"id": "PRD-123", "status": "new_status"}
2983
with respx.mock:
3084
mock_route = respx.post(
31-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
85+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
3286
).mock(
3387
return_value=httpx.Response(
34-
status_code=200,
88+
status_code=httpx.codes.OK,
3589
headers={"content-type": "application/json"},
3690
json=response_expected_data,
3791
)
3892
)
39-
order = getattr(product_service, action)("PRD-123", input_status)
93+
order = getattr(publishable_service, action)("PRD-123", input_status)
4094

4195
assert mock_route.call_count == 1
4296
request = mock_route.calls[0].request
4397

4498
assert request.content == request_expected_content
4599
assert order.to_dict() == response_expected_data
46-
assert isinstance(order, Product)
100+
assert isinstance(order, DummyModel)
47101

48102

49103
@pytest.mark.parametrize(
@@ -54,27 +108,27 @@ def test_custom_resource_actions(product_service, action, input_status):
54108
("unpublish", None),
55109
],
56110
)
57-
def test_custom_resource_actions_no_data(product_service, action, input_status):
111+
def test_custom_resource_actions_no_data(publishable_service, action, input_status):
58112
request_expected_content = b""
59113
response_expected_data = {"id": "PRD-123", "status": "new_status"}
60114
with respx.mock:
61115
mock_route = respx.post(
62-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
116+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
63117
).mock(
64118
return_value=httpx.Response(
65-
status_code=200,
119+
status_code=httpx.codes.OK,
66120
headers={"content-type": "application/json"},
67121
json=response_expected_data,
68122
)
69123
)
70124

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

73127
assert mock_route.call_count == 1
74128
request = mock_route.calls[0].request
75129
assert request.content == request_expected_content
76130
assert order.to_dict() == response_expected_data
77-
assert isinstance(order, Product)
131+
assert isinstance(order, DummyModel)
78132

79133

80134
@pytest.mark.parametrize(
@@ -85,27 +139,27 @@ def test_custom_resource_actions_no_data(product_service, action, input_status):
85139
("unpublish", {"id": "PRD-123", "status": "update"}),
86140
],
87141
)
88-
async def test_async_custom_resource_actions(async_product_service, action, input_status):
142+
async def test_async_custom_resource_actions(async_publishable_service, action, input_status):
89143
request_expected_content = b'{"id":"PRD-123","status":"update"}'
90144
response_expected_data = {"id": "PRD-123", "status": "new_status"}
91145
with respx.mock:
92146
mock_route = respx.post(
93-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
147+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
94148
).mock(
95149
return_value=httpx.Response(
96-
status_code=200,
150+
status_code=httpx.codes.OK,
97151
headers={"content-type": "application/json"},
98152
json=response_expected_data,
99153
)
100154
)
101-
order = await getattr(async_product_service, action)("PRD-123", input_status)
155+
order = await getattr(async_publishable_service, action)("PRD-123", input_status)
102156

103157
assert mock_route.call_count == 1
104158
request = mock_route.calls[0].request
105159

106160
assert request.content == request_expected_content
107161
assert order.to_dict() == response_expected_data
108-
assert isinstance(order, Product)
162+
assert isinstance(order, DummyModel)
109163

110164

111165
@pytest.mark.parametrize(
@@ -116,24 +170,150 @@ async def test_async_custom_resource_actions(async_product_service, action, inpu
116170
("unpublish", None),
117171
],
118172
)
119-
async def test_async_custom_resource_actions_no_data(async_product_service, action, input_status):
173+
async def test_async_custom_resource_actions_no_data(
174+
async_publishable_service, action, input_status
175+
):
120176
request_expected_content = b""
121177
response_expected_data = {"id": "PRD-123", "status": "new_status"}
122178
with respx.mock:
123179
mock_route = respx.post(
124-
f"https://api.example.com/public/v1/catalog/products/PRD-123/{action}"
180+
f"https://api.example.com/public/v1/dummy/publishable/PRD-123/{action}"
125181
).mock(
126182
return_value=httpx.Response(
127-
status_code=200,
183+
status_code=httpx.codes.OK,
128184
headers={"content-type": "application/json"},
129185
json=response_expected_data,
130186
)
131187
)
132188

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

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

0 commit comments

Comments
 (0)