Skip to content

Commit bfbab93

Browse files
author
Robert Segal
committed
Added Accounts accounts e2e CRUD endpoints tests
1 parent 65fb211 commit bfbab93

11 files changed

Lines changed: 481 additions & 34 deletions

File tree

e2e_config.test.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"catalog.product.id": "PRD-7255-3950",
3-
"accounts.seller.id": "SEL-7310-3075"
3+
"accounts.seller.id": "SEL-7310-3075",
4+
"accounts.account.id": "ACC-9042-0088"
45
}

mpt_api_client/resources/accounts/account.py

Lines changed: 127 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1+
from typing import override
2+
13
from mpt_api_client.http import AsyncService, Service
24
from mpt_api_client.http.mixins import (
35
AsyncCollectionMixin,
4-
AsyncCreateMixin,
6+
AsyncCreateWithIconMixin,
57
AsyncGetMixin,
6-
AsyncUpdateMixin,
8+
AsyncUpdateWithIconMixin,
79
CollectionMixin,
8-
CreateMixin,
10+
CreateWithIconMixin,
911
GetMixin,
10-
UpdateMixin,
12+
UpdateWithIconMixin,
1113
)
14+
from mpt_api_client.http.types import FileTypes
1215
from mpt_api_client.models import Model
16+
from mpt_api_client.models.model import ResourceData
1317
from mpt_api_client.resources.accounts.accounts_users import (
1418
AccountsUsersService,
1519
AsyncAccountsUsersService,
@@ -31,14 +35,14 @@ class Account(Model):
3135
class AccountsServiceConfig:
3236
"""Accounts service configuration."""
3337

34-
_endpoint = "/public/v1/accounts"
38+
_endpoint = "/public/v1/accounts/accounts"
3539
_model_class = Account
3640
_collection_key = "data"
3741

3842

3943
class AccountsService(
40-
CreateMixin[Account],
41-
UpdateMixin[Account],
44+
CreateWithIconMixin[Account],
45+
UpdateWithIconMixin[Account],
4246
ActivatableMixin[Account],
4347
EnablableMixin[Account],
4448
ValidateMixin[Account],
@@ -49,6 +53,63 @@ class AccountsService(
4953
):
5054
"""Accounts service."""
5155

56+
@override
57+
def create(
58+
self,
59+
resource_data: ResourceData,
60+
logo: FileTypes,
61+
data_key: str = "account",
62+
icon_key: str = "logo",
63+
) -> Account:
64+
"""
65+
Create a new account with logo.
66+
67+
Args:
68+
resource_data (ResourceData): Account data.
69+
logo: Logo image in jpg, png, GIF, etc.
70+
data_key: Key for the account data.
71+
icon_key: Key for the logo.
72+
73+
Returns:
74+
Account: The created account.
75+
"""
76+
return super().create(
77+
resource_data=resource_data,
78+
icon=logo,
79+
data_key=data_key,
80+
icon_key=icon_key,
81+
)
82+
83+
@override
84+
def update(
85+
self,
86+
resource_id: str,
87+
resource_data: ResourceData,
88+
logo: FileTypes,
89+
data_key: str = "account",
90+
icon_key: str = "logo",
91+
) -> Account:
92+
"""
93+
Update an existing account with logo.
94+
95+
Args:
96+
resource_id (str): The ID of the account to update.
97+
resource_data (ResourceData): Account data.
98+
logo: Logo image in jpg, png, GIF, etc.
99+
data_key: Key for the account data.
100+
icon_key: Key for the logo.
101+
102+
Returns:
103+
Account: The updated account.
104+
"""
105+
return super().update(
106+
resource_id=resource_id,
107+
resource_data=resource_data,
108+
icon=logo,
109+
data_key=data_key,
110+
icon_key=icon_key,
111+
)
112+
52113
def users(self, account_id: str) -> AccountsUsersService:
53114
"""Return account users service."""
54115
return AccountsUsersService(
@@ -57,8 +118,8 @@ def users(self, account_id: str) -> AccountsUsersService:
57118

58119

59120
class AsyncAccountsService(
60-
AsyncCreateMixin[Account],
61-
AsyncUpdateMixin[Account],
121+
AsyncCreateWithIconMixin[Account],
122+
AsyncUpdateWithIconMixin[Account],
62123
AsyncActivatableMixin[Account],
63124
AsyncEnablableMixin[Account],
64125
AsyncValidateMixin[Account],
@@ -69,6 +130,63 @@ class AsyncAccountsService(
69130
):
70131
"""Async Accounts service."""
71132

133+
@override
134+
async def create(
135+
self,
136+
resource_data: ResourceData,
137+
logo: FileTypes,
138+
data_key: str = "account",
139+
icon_key: str = "logo",
140+
) -> Account:
141+
"""
142+
Create a new account with logo.
143+
144+
Args:
145+
resource_data (ResourceData): Account data.
146+
logo: Logo image in jpg, png, GIF, etc.
147+
data_key: Key for the account data.
148+
icon_key: Key for the logo.
149+
150+
Returns:
151+
Account: The created account.
152+
"""
153+
return await super().create(
154+
resource_data=resource_data,
155+
icon=logo,
156+
data_key=data_key,
157+
icon_key=icon_key,
158+
)
159+
160+
@override
161+
async def update(
162+
self,
163+
resource_id: str,
164+
resource_data: ResourceData,
165+
logo: FileTypes,
166+
data_key: str = "account",
167+
icon_key: str = "logo",
168+
) -> Account:
169+
"""
170+
Update an existing account with logo.
171+
172+
Args:
173+
resource_id (str): The ID of the account to update.
174+
resource_data (ResourceData): Account data.
175+
logo: Logo image in jpg, png, GIF, etc.
176+
data_key: Key for the account data.
177+
icon_key: Key for the logo.
178+
179+
Returns:
180+
Account: The updated account.
181+
"""
182+
return await super().update(
183+
resource_id=resource_id,
184+
resource_data=resource_data,
185+
icon=logo,
186+
data_key=data_key,
187+
icon_key=icon_key,
188+
)
189+
72190
def users(self, account_id: str) -> AsyncAccountsUsersService:
73191
"""Return account users service."""
74192
return AsyncAccountsUsersService(

tests/e2e/accounts/conftest.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,6 @@ def timestamp():
99
return int(dt.datetime.now(tz=dt.UTC).strftime("%Y%m%d%H%M%S"))
1010

1111

12-
@pytest.fixture
13-
def account_data():
14-
return {
15-
"name": "Test Api Client Vendor",
16-
"address": {
17-
"addressLine1": "123 Test St",
18-
"city": "San Francisco",
19-
"state": "CA",
20-
"postCode": "12345",
21-
"country": "US",
22-
},
23-
"type": "Vendor",
24-
"status": "Active",
25-
}
26-
27-
28-
@pytest.fixture
29-
def account_icon():
30-
return pathlib.Path(__file__).parent / "logo.png"
31-
32-
3312
@pytest.fixture
3413
def currencies():
3514
return ["USD", "EUR"]
@@ -56,3 +35,30 @@ def _seller(
5635
}
5736

5837
return _seller
38+
39+
40+
@pytest.fixture
41+
def account():
42+
def _account(
43+
name: str = "Test Api Client Vendor",
44+
external_id: str = "",
45+
):
46+
return {
47+
"name": name,
48+
"address": {
49+
"addressLine1": "123 Test St",
50+
"city": "San Francisco",
51+
"state": "CA",
52+
"postCode": "12345",
53+
"country": "US",
54+
},
55+
"type": "Vendor",
56+
"status": "Active",
57+
}
58+
59+
return _account
60+
61+
62+
@pytest.fixture
63+
def account_icon():
64+
return pathlib.Path.open(pathlib.Path(__file__).parents[1] / "logo.png", "rb")
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import pytest
2+
3+
from mpt_api_client import AsyncMPTClient
4+
from mpt_api_client.exceptions import MPTAPIError
5+
from mpt_api_client.rql.query_builder import RQLQuery
6+
7+
pytestmark = [pytest.mark.flaky]
8+
9+
10+
@pytest.fixture
11+
async def async_created_account(logger, async_mpt_ops, account, account_icon):
12+
account_data = account()
13+
14+
res_account = await async_mpt_ops.accounts.accounts.create(account_data, logo=account_icon)
15+
16+
yield res_account
17+
18+
try:
19+
await async_mpt_ops.accounts.accounts.deactivate(res_account.id)
20+
except MPTAPIError as error:
21+
print("TEARDOWN - Unable to deactivate account: %s", error.title) # noqa: WPS421
22+
23+
24+
async def test_get_account_by_id_not_found(async_mpt_ops):
25+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
26+
await async_mpt_ops.accounts.accounts.get("INVALID-ID")
27+
28+
29+
async def test_get_account_by_id(async_mpt_ops, account_id):
30+
account = await async_mpt_ops.accounts.accounts.get(account_id)
31+
assert account is not None
32+
33+
34+
async def test_list_accounts(async_mpt_ops):
35+
limit = 10
36+
accounts_page = await async_mpt_ops.accounts.accounts.fetch_page(limit=limit)
37+
assert len(accounts_page) > 0
38+
39+
40+
def test_create_account(async_created_account):
41+
account = async_created_account
42+
assert account is not None
43+
44+
45+
async def test_update_account(async_mpt_ops, async_created_account, account, account_icon):
46+
updated_data = account(name="Updated Account Name")
47+
48+
updated_account = await async_mpt_ops.accounts.accounts.update(
49+
async_created_account.id, updated_data, logo=account_icon
50+
)
51+
52+
assert updated_account is not None
53+
54+
55+
async def test_update_account_invalid_data(
56+
async_mpt_ops, account, async_created_account, account_icon
57+
):
58+
updated_data = account(name="")
59+
60+
with pytest.raises(MPTAPIError, match=r"400 Bad Request"):
61+
await async_mpt_ops.accounts.accounts.update(
62+
async_created_account.id, updated_data, logo=account_icon
63+
)
64+
65+
66+
async def test_update_account_not_found(async_mpt_ops, account, invalid_account_id, account_icon):
67+
non_existent_account = account(name="Non Existent Account")
68+
69+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
70+
await async_mpt_ops.accounts.accounts.update(
71+
invalid_account_id, non_existent_account, logo=account_icon
72+
)
73+
74+
75+
async def test_account_enable(async_mpt_ops, account, async_created_account):
76+
await async_mpt_ops.accounts.accounts.disable(async_created_account.id)
77+
78+
account = await async_mpt_ops.accounts.accounts.enable(async_created_account.id)
79+
80+
assert account is not None
81+
82+
83+
async def test_account_enable_not_found(async_mpt_ops, invalid_account_id):
84+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
85+
await async_mpt_ops.accounts.accounts.enable(invalid_account_id)
86+
87+
88+
async def test_account_disable(async_mpt_ops, async_created_account):
89+
account = await async_mpt_ops.accounts.accounts.disable(async_created_account.id)
90+
91+
assert account is not None
92+
93+
94+
async def test_account_disable_not_found(async_mpt_ops, invalid_account_id):
95+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
96+
await async_mpt_ops.accounts.accounts.disable(invalid_account_id)
97+
98+
99+
async def test_account_rql_filter(async_mpt_ops, account_id):
100+
selected_fields = ["-address"]
101+
filtered_accounts = (
102+
async_mpt_ops.accounts.accounts.filter(RQLQuery(id=account_id))
103+
.filter(RQLQuery(name="Test Api Client Vendor"))
104+
.select(*selected_fields)
105+
)
106+
107+
accounts = [account async for account in filtered_accounts.iterate()]
108+
109+
assert len(accounts) > 0

tests/e2e/accounts/test_async_sellers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ async def _async_created_seller(
2626
try:
2727
await async_mpt_ops.accounts.sellers.delete(ret_seller.id)
2828
except MPTAPIError:
29-
logger.exception("TEARDOWN - Unable to delete seller %s", ret_seller.id)
29+
print("TEARDOWN - Unable to delete seller %s", ret_seller.id) # noqa: WPS421
3030

3131

3232
async def test_get_seller_by_id(async_mpt_ops, seller_id):

0 commit comments

Comments
 (0)