Skip to content

Commit 4fa2c08

Browse files
author
Robert Segal
committed
Added sellers E2E tests
1 parent 262d20c commit 4fa2c08

File tree

7 files changed

+333
-1
lines changed

7 files changed

+333
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,6 @@ cython_debug/
170170

171171
# VS Code dev container
172172
.devcontainer/
173+
174+
# E2E report
175+
e2e-report.xml

e2e_config.test.json

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

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ per-file-ignores =
4747
tests/unit/resources/*/test_mixins.py: WPS118 WPS202 WPS204 WPS235
4848
tests/unit/resources/accounts/test_users.py: WPS204 WPS202 WPS210
4949
tests/unit/test_mpt_client.py: WPS235
50+
tests/e2e/accounts/*.py: WPS430 WPS420 WPS421
5051

5152
tests/*:
5253
# Allow magic strings.

tests/e2e/accounts/conftest.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import datetime as dt
2+
import pathlib
3+
4+
import pytest
5+
6+
7+
@pytest.fixture(scope="session")
8+
def timestamp():
9+
return int(dt.datetime.now(tz=dt.UTC).strftime("%Y%m%d%H%M%S"))
10+
11+
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+
33+
@pytest.fixture
34+
def currencies():
35+
return ["USD", "EUR"]
36+
37+
38+
@pytest.fixture
39+
def seller(currencies):
40+
def _seller(
41+
external_id: str, # Must be unique in Marketplace
42+
name="E2E Test Seller",
43+
currencies=currencies,
44+
):
45+
return {
46+
"name": name,
47+
"address": {
48+
"addressLine1": "123 Main St",
49+
"city": "Anytown",
50+
"state": "CA",
51+
"postCode": "12345",
52+
"country": "US",
53+
},
54+
"currencies": currencies,
55+
"externalId": external_id,
56+
}
57+
58+
return _seller
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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+
# TODO: Handle create and teardown more gracefully with fixture that doesn't cause teardown issues
10+
@pytest.fixture
11+
async def async_created_seller(async_mpt_ops, seller):
12+
ret_seller = None
13+
14+
async def _async_created_seller(
15+
external_id: str,
16+
name: str = "E2E Test Seller",
17+
):
18+
nonlocal ret_seller
19+
seller_data = seller(external_id=external_id, name=name)
20+
ret_seller = await async_mpt_ops.accounts.sellers.create(seller_data)
21+
return ret_seller
22+
23+
yield _async_created_seller
24+
25+
if ret_seller:
26+
try:
27+
await async_mpt_ops.accounts.sellers.delete(ret_seller.id)
28+
except MPTAPIError as error:
29+
print(f"TEARDOWN - Unable to delete seller {ret_seller.id}: {error}")
30+
31+
32+
async def test_get_seller_by_id(async_mpt_ops, seller_id):
33+
seller = await async_mpt_ops.accounts.sellers.get(seller_id)
34+
assert seller is not None
35+
36+
37+
async def test_list_sellers(async_mpt_ops):
38+
sellers = await async_mpt_ops.accounts.sellers.fetch_page(limit=10)
39+
assert len(sellers) > 0
40+
41+
42+
async def test_get_seller_by_id_not_found(async_mpt_ops, invalid_seller_id):
43+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
44+
await async_mpt_ops.accounts.sellers.get(invalid_seller_id)
45+
46+
47+
async def test_filter_sellers(async_mpt_ops, seller_id):
48+
select_fields = ["-address"]
49+
50+
async_filtered_sellers = (
51+
async_mpt_ops.accounts.sellers.filter(RQLQuery(id=seller_id))
52+
.filter(RQLQuery(name="E2E Seeded Seller"))
53+
.select(*select_fields)
54+
)
55+
56+
sellers = [filtered_seller async for filtered_seller in async_filtered_sellers.iterate()]
57+
58+
assert len(sellers) == 1
59+
60+
61+
async def test_create_seller(async_created_seller, timestamp):
62+
seller_data = await async_created_seller(external_id=f"Async Create E2E Seller - {timestamp}")
63+
assert seller_data is not None
64+
65+
66+
async def test_delete_seller(async_mpt_ops, async_created_seller, timestamp):
67+
seller_data = await async_created_seller(external_id=f"Async Delete E2E Seller - {timestamp}")
68+
await async_mpt_ops.accounts.sellers.delete(seller_data.id)
69+
70+
71+
async def test_delete_seller_not_found(async_mpt_ops, invalid_seller_id):
72+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
73+
await async_mpt_ops.accounts.sellers.delete(invalid_seller_id)
74+
75+
76+
async def test_update_seller(async_mpt_ops, seller, async_created_seller, timestamp):
77+
seller_data = await async_created_seller(external_id=f"Async Update E2E Seller - {timestamp}")
78+
update_data = seller(
79+
external_id=f"Async Update E2E Seller - {timestamp}",
80+
name=f"Updated Update E2E Seller - {timestamp}",
81+
)
82+
updated_seller = await async_mpt_ops.accounts.sellers.update(seller_data.id, update_data)
83+
assert updated_seller is not None
84+
85+
86+
async def test_update_seller_mpt_error(async_mpt_ops, seller, timestamp, invalid_seller_id):
87+
update_data = seller(
88+
external_id=f"Async Update E2E Seller Not Found - {timestamp}",
89+
name=f"Updated Update E2E Seller Not Found - {timestamp}",
90+
)
91+
with pytest.raises(MPTAPIError):
92+
await async_mpt_ops.accounts.sellers.update(invalid_seller_id, update_data)
93+
94+
95+
async def test_activate_seller(async_mpt_ops, async_created_seller, timestamp):
96+
seller_data = await async_created_seller(external_id=f"Async Activate E2E Seller - {timestamp}")
97+
await async_mpt_ops.accounts.sellers.deactivate(seller_data.id)
98+
activated_seller = await async_mpt_ops.accounts.sellers.activate(seller_data.id)
99+
100+
assert activated_seller is not None
101+
102+
103+
async def test_activate_seller_mpt_error(async_mpt_ops, invalid_seller_id):
104+
with pytest.raises(MPTAPIError):
105+
await async_mpt_ops.accounts.sellers.activate(invalid_seller_id)
106+
107+
108+
async def test_deactivate_seller(async_mpt_ops, async_created_seller, timestamp):
109+
seller_data = await async_created_seller(
110+
external_id=f"Async Deactivate E2E Seller - {timestamp}"
111+
)
112+
deactivated_seller = await async_mpt_ops.accounts.sellers.deactivate(seller_data.id)
113+
114+
assert deactivated_seller is not None
115+
116+
117+
async def test_deactivate_seller_mpt_error(async_mpt_ops, invalid_seller_id):
118+
with pytest.raises(MPTAPIError):
119+
await async_mpt_ops.accounts.sellers.deactivate(invalid_seller_id)
120+
121+
122+
async def test_disable_seller(async_mpt_ops, async_created_seller, timestamp):
123+
seller_data = await async_created_seller(external_id=f"Async Disable E2E Seller - {timestamp}")
124+
disabled_seller = await async_mpt_ops.accounts.sellers.disable(seller_data.id)
125+
126+
assert disabled_seller is not None
127+
128+
129+
async def test_disable_seller_mpt_error(async_mpt_ops, invalid_seller_id):
130+
with pytest.raises(MPTAPIError):
131+
await async_mpt_ops.accounts.sellers.disable(invalid_seller_id)
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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+
def created_seller(mpt_ops, seller):
11+
ret_seller = None
12+
13+
def _created_seller(
14+
external_id: str,
15+
name: str = "E2E Test Seller",
16+
):
17+
nonlocal ret_seller
18+
seller_data = seller(external_id=external_id, name=name)
19+
ret_seller = mpt_ops.accounts.sellers.create(seller_data)
20+
return ret_seller
21+
22+
yield _created_seller
23+
24+
if ret_seller:
25+
try:
26+
mpt_ops.accounts.sellers.delete(ret_seller.id)
27+
except MPTAPIError as error:
28+
print(f"TEARDOWN - Unable to delete seller {ret_seller.id}: {error}")
29+
30+
31+
def test_get_seller_by_id(mpt_ops, seller_id):
32+
seller = mpt_ops.accounts.sellers.get(seller_id)
33+
assert seller is not None
34+
35+
36+
def test_list_sellers(mpt_ops):
37+
sellers = mpt_ops.accounts.sellers.fetch_page(limit=10)
38+
assert len(sellers) > 0
39+
40+
41+
def test_get_seller_by_id_not_found(mpt_ops, invalid_seller_id):
42+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
43+
mpt_ops.accounts.sellers.get(invalid_seller_id)
44+
45+
46+
def test_filter_sellers(mpt_ops, seller_id):
47+
select_fields = ["-address"]
48+
49+
filtered_sellers = (
50+
mpt_ops.accounts.sellers.filter(RQLQuery(id=seller_id))
51+
.filter(RQLQuery(name="E2E Seeded Seller"))
52+
.select(*select_fields)
53+
)
54+
55+
sellers = list(filtered_sellers.iterate())
56+
57+
assert len(sellers) == 1
58+
59+
60+
def test_create_seller(created_seller, timestamp):
61+
seller_data = created_seller(external_id=f"Create E2E Seller - {timestamp}")
62+
assert seller_data is not None
63+
64+
65+
def test_delete_seller(mpt_ops, created_seller, timestamp):
66+
seller_data = created_seller(external_id=f"Delete E2E Seller - {timestamp}")
67+
mpt_ops.accounts.sellers.delete(seller_data.id)
68+
69+
70+
def test_delete_seller_not_found(mpt_ops, invalid_seller_id):
71+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
72+
mpt_ops.accounts.sellers.delete(invalid_seller_id)
73+
74+
75+
def test_update_seller(mpt_ops, seller, created_seller, timestamp):
76+
seller_data = created_seller(external_id=f"Update E2E Seller - {timestamp}")
77+
update_data = seller(
78+
external_id=f"Update E2E Seller - {timestamp}",
79+
name=f"Updated Update E2E Seller - {timestamp}",
80+
)
81+
updated_seller = mpt_ops.accounts.sellers.update(seller_data.id, update_data)
82+
assert updated_seller is not None
83+
84+
85+
def test_update_seller_mpt_error(mpt_ops, seller, timestamp, invalid_seller_id):
86+
update_data = seller(
87+
external_id=f"Async Update E2E Seller Not Found - {timestamp}",
88+
name=f"Updated Update E2E Seller Not Found - {timestamp}",
89+
)
90+
with pytest.raises(MPTAPIError):
91+
mpt_ops.accounts.sellers.update(invalid_seller_id, update_data)
92+
93+
94+
def test_activate_seller(mpt_ops, created_seller, timestamp):
95+
seller_data = created_seller(external_id=f"Activate E2E Seller - {timestamp}")
96+
mpt_ops.accounts.sellers.deactivate(seller_data.id)
97+
activated_seller = mpt_ops.accounts.sellers.activate(seller_data.id)
98+
99+
assert activated_seller is not None
100+
101+
102+
def test_activate_seller_mpt_error(mpt_ops, invalid_seller_id):
103+
with pytest.raises(MPTAPIError):
104+
mpt_ops.accounts.sellers.activate(invalid_seller_id)
105+
106+
107+
def test_deactivate_seller(mpt_ops, created_seller, timestamp):
108+
seller_data = created_seller(external_id=f"Deactivate E2E Seller - {timestamp}")
109+
deactivated_seller = mpt_ops.accounts.sellers.deactivate(seller_data.id)
110+
111+
assert deactivated_seller is not None
112+
113+
114+
def test_deactivate_seller_mpt_error(mpt_ops, invalid_seller_id):
115+
with pytest.raises(MPTAPIError):
116+
mpt_ops.accounts.sellers.deactivate(invalid_seller_id)
117+
118+
119+
def test_disable_seller(mpt_ops, created_seller, timestamp):
120+
seller_data = created_seller(external_id=f"Disable E2E Seller - {timestamp}")
121+
disabled_seller = mpt_ops.accounts.sellers.disable(seller_data.id)
122+
123+
assert disabled_seller is not None
124+
125+
126+
def test_disable_seller_mpt_error(mpt_ops, invalid_seller_id):
127+
with pytest.raises(MPTAPIError):
128+
mpt_ops.accounts.sellers.disable(invalid_seller_id)

tests/e2e/conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,13 @@ def e2e_config(project_root_path):
7878
@pytest.fixture
7979
def product_id(e2e_config):
8080
return e2e_config["catalog.product.id"]
81+
82+
83+
@pytest.fixture
84+
def invalid_seller_id():
85+
return "SEL-0000-0000"
86+
87+
88+
@pytest.fixture
89+
def seller_id(e2e_config):
90+
return e2e_config["accounts.seller.id"]

0 commit comments

Comments
 (0)