Skip to content

Commit 1d05f5c

Browse files
author
Robert Segal
committed
Added Accounts account by id users endpoints e2e tests
1 parent 3399c94 commit 1d05f5c

File tree

10 files changed

+683
-6
lines changed

10 files changed

+683
-6
lines changed

e2e_config.test.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"accounts.module.id": "MOD-1756",
1010
"accounts.module.name": "Access Management",
1111
"accounts.seller.id": "SEL-7310-3075",
12+
"accounts.user.id": "USR-9673-3314",
1213
"accounts.user_group.id": "UGR-6822-0561",
1314
"catalog.product.item.id": "ITM-7255-3950-0751",
1415
"catalog.product.document.id": "PDC-7255-3950-0001",

mpt_api_client/http/mixins.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,3 +622,13 @@ class AsyncManagedResourceMixin[Model](
622622
AsyncCreateMixin[Model], AsyncModifiableResourceMixin[Model]
623623
):
624624
"""Managed resource mixin allows to read, create, update and delete a resource resources."""
625+
626+
627+
class CreatableResourceMixin[Model](CreateMixin[Model], GetMixin[Model], DeleteMixin):
628+
"""Managed resource mixin to read, create, and delete a resource resources."""
629+
630+
631+
class AsyncCreatableResourceMixin[Model](
632+
AsyncCreateMixin[Model], AsyncGetMixin[Model], AsyncDeleteMixin
633+
):
634+
"""Managed resource mixin to read, create, and delete a resource resources."""

mpt_api_client/resources/accounts/accounts_user_groups.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from mpt_api_client.http import AsyncService, Service
22
from mpt_api_client.http.mixins import (
33
AsyncCollectionMixin,
4-
AsyncManagedResourceMixin,
4+
AsyncCreatableResourceMixin,
55
CollectionMixin,
6-
ManagedResourceMixin,
6+
CreatableResourceMixin,
77
)
88
from mpt_api_client.models import Model
9+
from mpt_api_client.models.model import ResourceData
910

1011

1112
class AccountsUserGroup(Model):
@@ -21,18 +22,44 @@ class AccountsUserGroupsServiceConfig:
2122

2223

2324
class AccountsUserGroupsService(
24-
ManagedResourceMixin[AccountsUserGroup],
25+
CreatableResourceMixin[AccountsUserGroup],
2526
CollectionMixin[AccountsUserGroup],
2627
Service[AccountsUserGroup],
2728
AccountsUserGroupsServiceConfig,
2829
):
2930
"""Account User Groups Service."""
3031

32+
def update(self, resource_data: ResourceData) -> AccountsUserGroup:
33+
"""Update Account User Group.
34+
35+
Args:
36+
resource_data (ResourceData): Resource data to update.
37+
38+
Returns:
39+
AccountsUserGroup: Updated Account User Group.
40+
"""
41+
response = self.http_client.request("put", self.path, json=resource_data)
42+
43+
return self._model_class.from_response(response)
44+
3145

3246
class AsyncAccountsUserGroupsService(
33-
AsyncManagedResourceMixin[AccountsUserGroup],
47+
AsyncCreatableResourceMixin[AccountsUserGroup],
3448
AsyncCollectionMixin[AccountsUserGroup],
3549
AsyncService[AccountsUserGroup],
3650
AccountsUserGroupsServiceConfig,
3751
):
3852
"""Asynchronous Account User Groups Service."""
53+
54+
async def update(self, resource_data: ResourceData) -> AccountsUserGroup:
55+
"""Update Account User Group.
56+
57+
Args:
58+
resource_data (ResourceData): Resource data to update.
59+
60+
Returns:
61+
AccountsUserGroup: Updated Account User Group.
62+
"""
63+
response = await self.http_client.request("put", self.path, json=resource_data)
64+
65+
return self._model_class.from_response(response)

setup.cfg

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# All configuration for plugins
2+
# and other utils is defined here and in `pyproject.toml`
3+
4+
# === Linter configuration ===
5+
6+
# NOTE: You can use https://pypi.org/project/Flake8-pyproject/
7+
# to move all your `flake8` configuration to `pyproject.toml`
8+
9+
[flake8]
10+
# Base flake8 configuration:
11+
# https://flake8.pycqa.org/en/latest/user/configuration.html
12+
format = wemake
13+
show-source = true
14+
statistics = false
15+
doctests = true
16+
17+
# Self settings:
18+
max-imports = 17
19+
20+
# Excluding some directories:
21+
extend-exclude =
22+
.venv
23+
24+
# We only run `wemake-python-styleguide` with `flake8`:
25+
select = WPS, E999
26+
27+
extend-ignore =
28+
# Found string constant over-use
29+
WPS226
30+
# Allow logic in WPS412
31+
WPS412
32+
33+
34+
per-file-ignores =
35+
mpt_api_client/mpt_client.py: WPS214 WPS235
36+
mpt_api_client/http/mixins.py: WPS202 WPS204 WPS235
37+
mpt_api_client/resources/*: WPS215
38+
mpt_api_client/models/model.py: WPS215 WPS110
39+
mpt_api_client/resources/accounts/*.py: WPS202 WPS215 WPS214 WPS235
40+
mpt_api_client/resources/billing/*.py: WPS202 WPS204 WPS214 WPS215
41+
mpt_api_client/resources/catalog/*.py: WPS110 WPS214 WPS215 WPS235
42+
mpt_api_client/resources/catalog/mixins.py: WPS110 WPS202 WPS214 WPS215 WPS235
43+
mpt_api_client/resources/catalog/products.py: WPS204 WPS214 WPS215 WPS235
44+
mpt_api_client/rql/query_builder.py: WPS110 WPS115 WPS210 WPS214
45+
tests/unit/http/test_async_service.py: WPS204 WPS202
46+
tests/unit/http/test_service.py: WPS204 WPS202
47+
tests/unit/http/test_mixins.py: WPS204 WPS202 WPS210 WPS235 WPS402
48+
tests/unit/resources/catalog/test_products.py: WPS202 WPS210
49+
tests/unit/resources/accounts/*.py: WPS204 WPS202 WPS210
50+
tests/unit/resources/*/test_mixins.py: WPS118 WPS202 WPS204 WPS235
51+
tests/unit/test_mpt_client.py: WPS235
52+
tests/e2e/accounts/*.py: WPS430 WPS202
53+
tests/e2e/accounts/accounts_users/*.py: WPS204 WPS202
54+
tests/e2e/catalog/*.py: WPS202 WPS421
55+
tests/e2e/catalog/items/*.py: WPS110 WPS202
56+
57+
tests/*:
58+
# Allow magic strings.
59+
WPS432
60+
# Found too many modules members.
61+
WPS202
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def invalid_user_id():
6+
return "USR-0000-0000"
7+
8+
9+
@pytest.fixture
10+
def account_user_factory(account_id, user_group_id, uuid_str):
11+
def _account_user( # noqa: WPS430
12+
email: str | None = None, # Must be unique in Marketplace
13+
first_name: str = "E2E Created",
14+
last_name: str = "Account User",
15+
):
16+
if not email:
17+
email = f"e2e_{uuid_str}@dummy.com"
18+
19+
return {
20+
"user": {
21+
"firstName": first_name,
22+
"lastName": last_name,
23+
"email": email,
24+
},
25+
"account": {
26+
"id": account_id,
27+
},
28+
"groups": [
29+
{"id": user_group_id},
30+
],
31+
"invitation": {
32+
"status": "Invited",
33+
},
34+
}
35+
36+
return _account_user
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
from mpt_api_client.rql.query_builder import RQLQuery
5+
6+
pytestmark = [pytest.mark.flaky]
7+
8+
9+
@pytest.fixture
10+
async def created_account_user(async_mpt_vendor, account_user_factory, account_id):
11+
"""Fixture to create and teardown an account user."""
12+
ret_account_user = None
13+
14+
async def _created_account_user( # noqa: WPS430
15+
first_name: str = "E2E Created",
16+
last_name: str = "Account User",
17+
):
18+
"""Create an account user with the given first and last name."""
19+
nonlocal ret_account_user # noqa: WPS420
20+
account_user_data = account_user_factory(
21+
first_name=first_name,
22+
last_name=last_name,
23+
)
24+
ret_account_user = await async_mpt_vendor.accounts.accounts.users(
25+
account_id=account_id
26+
).create(account_user_data)
27+
return ret_account_user
28+
29+
yield _created_account_user
30+
31+
if ret_account_user:
32+
try:
33+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id).delete(
34+
ret_account_user.id
35+
)
36+
except MPTAPIError:
37+
print( # noqa: WPS421
38+
f"TEARDOWN - Unable to delete account user {ret_account_user.id}",
39+
)
40+
41+
42+
@pytest.fixture
43+
async def created_user_group(async_mpt_ops, user_group_factory):
44+
"""Fixture to create and teardown a user group."""
45+
new_user_group_request_data = user_group_factory()
46+
created_user_group = await async_mpt_ops.accounts.user_groups.create(
47+
new_user_group_request_data
48+
)
49+
50+
yield created_user_group
51+
52+
try:
53+
await async_mpt_ops.accounts.user_groups.delete(created_user_group.id)
54+
except MPTAPIError as error:
55+
print(f"TEARDOWN - Unable to delete user group: {error.title}") # noqa: WPS421
56+
57+
58+
@pytest.fixture
59+
async def created_account_user_group(
60+
async_mpt_vendor, created_account_user, created_user_group, account_id
61+
):
62+
"""Fixture to create and teardown an account user group."""
63+
created_account_user_data = await created_account_user()
64+
user_group_data = created_user_group
65+
create_user_group_data = {"id": user_group_data.id}
66+
created_account_user_group = (
67+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id)
68+
.groups(user_id=created_account_user_data.id)
69+
.create(create_user_group_data)
70+
)
71+
yield created_account_user_group
72+
73+
try:
74+
await (
75+
async_mpt_vendor.accounts.accounts.users(account_id=account_id)
76+
.groups(user_id=created_account_user_data.id)
77+
.delete(user_group_data.id)
78+
)
79+
except MPTAPIError as error:
80+
print(f"TEARDOWN - Unable to delete account user group: {error.title}") # noqa: WPS421
81+
82+
83+
async def test_get_account_user_by_id(async_mpt_vendor, user_id, account_id):
84+
"""Test retrieving an account user by ID."""
85+
account_user = await async_mpt_vendor.accounts.accounts.users(account_id=account_id).get(
86+
user_id
87+
)
88+
assert account_user is not None
89+
90+
91+
async def test_list_account_users(async_mpt_vendor, account_id):
92+
"""Test listing account users."""
93+
limit = 10
94+
95+
account_users = await async_mpt_vendor.accounts.accounts.users(
96+
account_id=account_id
97+
).fetch_page(limit=limit)
98+
99+
assert len(account_users) > 0
100+
101+
102+
async def test_get_account_user_by_id_not_found(async_mpt_vendor, invalid_user_id, account_id):
103+
"""Test retrieving an account user by invalid ID."""
104+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
105+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id).get(invalid_user_id)
106+
107+
108+
async def test_filter_account_users(async_mpt_vendor, user_id, account_id):
109+
"""Test filtering account users."""
110+
select_fields = ["-name"]
111+
112+
filtered_account_users = (
113+
async_mpt_vendor.accounts.accounts.users(account_id=account_id)
114+
.filter(RQLQuery(id=user_id))
115+
.select(*select_fields)
116+
)
117+
118+
account_users = [user async for user in filtered_account_users.iterate()]
119+
120+
assert len(account_users) == 1
121+
122+
123+
async def test_create_account_user(created_account_user):
124+
"""Test creating an account user."""
125+
account_user_data = await created_account_user()
126+
assert account_user_data is not None
127+
128+
129+
async def test_delete_account_user(async_mpt_vendor, created_account_user, account_id):
130+
"""Test deleting an account user."""
131+
account_user_data = await created_account_user()
132+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id).delete(
133+
account_user_data.id
134+
)
135+
136+
137+
async def test_update_account_user(
138+
async_mpt_vendor,
139+
account_user_factory,
140+
created_account_user,
141+
account_id,
142+
):
143+
"""Test updating an account user."""
144+
account_user_data = await created_account_user()
145+
updated_account_user_data = account_user_factory(
146+
first_name="E2E Updated",
147+
last_name="Account User",
148+
)
149+
updated_account_user = await async_mpt_vendor.accounts.accounts.users(
150+
account_id=account_id
151+
).update(
152+
account_user_data.id,
153+
updated_account_user_data,
154+
)
155+
assert updated_account_user is not None
156+
157+
158+
async def test_account_user_resend_invite(
159+
async_mpt_vendor,
160+
created_account_user,
161+
account_id,
162+
):
163+
"""Test resending an invite to an account user."""
164+
account_user_data = await created_account_user()
165+
resend_invite = await async_mpt_vendor.accounts.accounts.users(
166+
account_id=account_id
167+
).resend_invite(account_user_data.id)
168+
assert resend_invite is not None
169+
170+
171+
async def test_account_user_group_post(created_account_user_group):
172+
"""Test creating an account user group."""
173+
created_account_user_group_data = created_account_user_group
174+
assert created_account_user_group_data is not None
175+
176+
177+
async def test_account_user_group_update(
178+
async_mpt_vendor,
179+
created_account_user,
180+
created_user_group,
181+
account_id,
182+
):
183+
"""Test updating an account user group."""
184+
created_account_user_data = await created_account_user()
185+
update_user_group_data = [{"id": created_user_group.id}]
186+
updated_account_user_group = (
187+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id)
188+
.groups(user_id=created_account_user_data.id)
189+
.update(update_user_group_data)
190+
)
191+
assert updated_account_user_group is not None
192+
193+
194+
async def test_account_user_group_delete(
195+
async_mpt_vendor,
196+
created_account_user,
197+
created_user_group,
198+
account_id,
199+
):
200+
"""Test deleting an account user group."""
201+
created_account_user_data = await created_account_user()
202+
create_user_group_data = {"id": created_user_group.id}
203+
(
204+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id)
205+
.groups(user_id=created_account_user_data.id)
206+
.create(create_user_group_data)
207+
)
208+
(
209+
await async_mpt_vendor.accounts.accounts.users(account_id=account_id)
210+
.groups(user_id=created_account_user_data.id)
211+
.delete(created_user_group.id)
212+
)

0 commit comments

Comments
 (0)