Skip to content

Commit 7adea35

Browse files
committed
MPT-14767 E2E seeding proof of concept
- Added seeding proof of concept - Fix create product request
1 parent 419d0d5 commit 7adea35

12 files changed

Lines changed: 185 additions & 9 deletions

File tree

mpt_api_client/http/client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def __init__(
4949
base_headers = {
5050
"User-Agent": "swo-marketplace-client/1.0",
5151
"Authorization": f"Bearer {api_token}",
52-
"content-type": "application/json",
5352
}
5453
self.httpx_client = Client(
5554
base_url=base_url,

mpt_api_client/http/mixins.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ def create(
8686
_json_to_file_payload(resource_data),
8787
"application/json",
8888
)
89-
9089
response = self.http_client.request("post", self.path, files=files) # type: ignore[attr-defined]
9190

9291
return self._model_class.from_response(response) # type: ignore[attr-defined, no-any-return]

mpt_api_client/resources/catalog/products.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import json
2+
13
from mpt_api_client.http import AsyncService, Service
24
from mpt_api_client.http.mixins import (
35
AsyncCollectionMixin,
4-
AsyncManagedResourceMixin,
6+
AsyncModifiableResourceMixin,
57
CollectionMixin,
6-
ManagedResourceMixin,
8+
ModifiableResourceMixin,
79
)
10+
from mpt_api_client.http.types import FileTypes
811
from mpt_api_client.models import Model, ResourceData
912
from mpt_api_client.resources.catalog.mixins import (
1013
AsyncPublishableMixin,
@@ -54,13 +57,38 @@ class ProductsServiceConfig:
5457

5558
class ProductsService(
5659
PublishableMixin[Product],
57-
ManagedResourceMixin[Product],
60+
ModifiableResourceMixin[Product],
5861
CollectionMixin[Product],
5962
Service[Product],
6063
ProductsServiceConfig,
6164
):
6265
"""Products service."""
6366

67+
def create(
68+
self,
69+
resource_data: ResourceData,
70+
icon: FileTypes,
71+
) -> Model:
72+
"""Create product with icon.
73+
74+
Args:
75+
resource_data: Product data.
76+
icon: Icon image in jpg, png, GIF, etc.
77+
78+
Returns:
79+
Created resource.
80+
"""
81+
files: dict[str, FileTypes] = {}
82+
files["product"] = (
83+
None,
84+
json.dumps(resource_data),
85+
"application/json",
86+
)
87+
files["icon"] = icon
88+
response = self.http_client.request("post", self.path, files=files)
89+
90+
return self._model_class.from_response(response)
91+
6492
def item_groups(self, product_id: str) -> ItemGroupsService:
6593
"""Return item_groups service."""
6694
return ItemGroupsService(
@@ -108,13 +136,37 @@ def update_settings(self, product_id: str, settings: ResourceData) -> Product:
108136

109137
class AsyncProductsService(
110138
AsyncPublishableMixin[Product],
111-
AsyncManagedResourceMixin[Product],
139+
AsyncModifiableResourceMixin[Product],
112140
AsyncCollectionMixin[Product],
113141
AsyncService[Product],
114142
ProductsServiceConfig,
115143
):
116144
"""Products service."""
117145

146+
async def create(
147+
self,
148+
resource_data: ResourceData,
149+
icon: FileTypes,
150+
) -> Model:
151+
"""Create product with icon.
152+
153+
Args:
154+
resource_data: Product data.
155+
icon: Icon image in jpg, png, GIF, etc.
156+
157+
Returns:
158+
Created resource.
159+
"""
160+
files: dict[str, FileTypes] = {}
161+
files["product"] = (
162+
None,
163+
json.dumps(resource_data),
164+
"application/json",
165+
)
166+
files["icon"] = icon
167+
response = await self.http_client.request("post", self.path, files=files)
168+
return self._model_class.from_response(response)
169+
118170
def item_groups(self, product_id: str) -> AsyncItemGroupsService:
119171
"""Return item_groups service."""
120172
return AsyncItemGroupsService(

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ per-file-ignores =
4848
tests/unit/resources/accounts/test_users.py: WPS204 WPS202 WPS210
4949
tests/unit/test_mpt_client.py: WPS235
5050

51-
tests/unit/*:
51+
tests/*:
5252
# Allow magic strings.
5353
WPS432
5454
# Found too many modules members.

tests/seed/__init__.py

Whitespace-only changes.
84 KB
Loading

tests/seed/catalog/__init__.py

Whitespace-only changes.

tests/seed/catalog/test_product.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import datetime as dt
2+
import json
3+
import pathlib
4+
import uuid
5+
6+
import httpx
7+
import pytest
8+
9+
10+
@pytest.fixture
11+
def icon_path():
12+
return pathlib.Path(__file__).parent / "FIL-9920-4780-9379.png"
13+
14+
15+
@pytest.fixture
16+
def product_id(mpt_vendor, mpt_operations, icon_path):
17+
product_data = {
18+
"name": "Microsoft 365 online services for commercial",
19+
"shortDescription": "Microsoft 365 and Office 365 [...]",
20+
"longDescription": "Microsoft 365 and Office 365 [...long]",
21+
"website": "https://www.microsoft.com",
22+
}
23+
24+
with pathlib.Path.open(icon_path, "rb") as icon_file:
25+
new_product = mpt_vendor.catalog.products.create(
26+
product_data,
27+
icon=icon_file,
28+
)
29+
assert new_product.meta.response.status_code == httpx.Response.raise_for_status()
30+
31+
return new_product.id
32+
33+
34+
@pytest.fixture
35+
def product_data(product_id):
36+
return {
37+
"product_id": product_id,
38+
}
39+
40+
41+
@pytest.fixture
42+
def product_json_path():
43+
date = dt.datetime.now(tz=dt.UTC).strftime("%Y-%m-%d")
44+
test_run_id = str(uuid.uuid4())[:8]
45+
return pathlib.Path(__file__).parent / f"../../../test-data-{date}-{test_run_id}.json"
46+
47+
48+
def test_save(product_json_path, product_data, logger):
49+
catalog_data_json = json.dumps(product_data, indent=2)
50+
pathlib.Path(product_json_path).write_text(catalog_data_json, encoding="utf-8")
51+
logger.info("Saved commerce data to `%s`", product_json_path)
52+
logger.debug(catalog_data_json)

tests/seed/conftest.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
3+
import pytest
4+
5+
from mpt_api_client import MPTClient
6+
7+
8+
@pytest.fixture
9+
def operations_token():
10+
return os.getenv("MPT_API_TOKEN_OPERATIONS")
11+
12+
13+
@pytest.fixture
14+
def base_url():
15+
return os.getenv("MPT_API_BASE_URL")
16+
17+
18+
@pytest.fixture
19+
def vendor_token():
20+
return os.getenv("MPT_API_TOKEN_VENDOR")
21+
22+
23+
@pytest.fixture
24+
def mpt_vendor(vendor_token, base_url):
25+
return MPTClient.from_config(api_token=vendor_token, base_url=base_url)
26+
27+
28+
@pytest.fixture
29+
def mpt_operations(operations_token, base_url):
30+
return MPTClient.from_config(api_token=operations_token, base_url=base_url)

tests/unit/http/test_client.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ def test_http_initialization(mocker):
1919
headers={
2020
"User-Agent": "swo-marketplace-client/1.0",
2121
"Authorization": "Bearer test-token",
22-
"content-type": "application/json",
2322
},
2423
timeout=5.0,
2524
transport=mocker.ANY,
@@ -38,7 +37,6 @@ def test_env_initialization(monkeypatch, mocker):
3837
headers={
3938
"User-Agent": "swo-marketplace-client/1.0",
4039
"Authorization": f"Bearer {API_TOKEN}",
41-
"content-type": "application/json",
4240
},
4341
timeout=5.0,
4442
transport=mocker.ANY,

0 commit comments

Comments
 (0)