Skip to content

Commit b36c487

Browse files
author
Robert Segal
committed
Seeded and created e2e tests for commerce agreements
1 parent 8f72e0c commit b36c487

13 files changed

Lines changed: 339 additions & 21 deletions

File tree

e2e_config.test.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
"accounts.seller.id": "SEL-7310-3075",
1212
"accounts.user.id": "USR-9673-3314",
1313
"accounts.user_group.id": "UGR-6822-0561",
14+
"commerce.agreement.id": "AGR-9850-2169-6098",
15+
"commerce.product.id": "PRD-1767-7355",
16+
"commerce.product.item.id": "ITM-1767-7355-0001",
17+
"commerce.product.listing.id": "LST-5489-0806",
18+
"commerce.product.template.id": "TPL-1767-7355-0003",
19+
"commerce.authorization.id": "AUT-0031-2873",
20+
"commerce.client.id": "ACC-1086-6867",
1421
"catalog.product.item.id": "ITM-7255-3950-0751",
1522
"catalog.product.document.id": "PDC-7255-3950-0001",
1623
"catalog.product.id": "PRD-7255-3950",

mpt_api_client/resources/commerce/agreements.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ def template(self, agreement_id: str) -> str:
4444
response = self._resource_do_request(agreement_id, action="template")
4545
return response.text
4646

47+
def render(self, agreement_id: str) -> str:
48+
"""Renders the template for the given Agreement id.
49+
50+
Args:
51+
agreement_id: Agreement ID.
52+
53+
Returns:
54+
Rendered Agreement.
55+
"""
56+
response = self._resource_do_request(agreement_id, action="render")
57+
return response.text
58+
4759
def attachments(self, agreement_id: str) -> AgreementsAttachmentService:
4860
"""Get the attachments service for the given Agreement id.
4961
@@ -79,6 +91,18 @@ async def template(self, agreement_id: str) -> str:
7991
response = await self._resource_do_request(agreement_id, action="template")
8092
return response.text
8193

94+
async def render(self, agreement_id: str) -> str:
95+
"""Renders the template for the given Agreement id.
96+
97+
Args:
98+
agreement_id: Agreement ID.
99+
100+
Returns:
101+
Rendered Agreement.
102+
"""
103+
response = await self._resource_do_request(agreement_id, action="render")
104+
return response.text
105+
82106
def attachments(self, agreement_id: str) -> AsyncAgreementsAttachmentService:
83107
"""Get the attachments service for the given Agreement id.
84108

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ dev = [
4848
"ruff==0.12.11", # force ruff version to have same formatting everywhere
4949
"typing-extensions==4.13.*",
5050
"wemake-python-styleguide==1.3.*",
51+
"types-python-dateutil",
5152
]
5253

5354
[tool.hatch.build.targets.sdist]
@@ -119,6 +120,7 @@ per-file-ignores = [
119120
"mpt_api_client/resources/catalog/mixins.py: WPS110 WPS202 WPS214 WPS215 WPS235",
120121
"mpt_api_client/resources/catalog/products.py: WPS204 WPS214 WPS215 WPS235",
121122
"mpt_api_client/rql/query_builder.py: WPS110 WPS115 WPS210 WPS214",
123+
"mpt_api_client/utils.py: WPS100 WPS453",
122124
"tests/unit/http/test_async_service.py: WPS204 WPS202",
123125
"tests/unit/http/test_service.py: WPS204 WPS202",
124126
"tests/unit/http/test_mixins.py: WPS204 WPS202 WPS210",

tests/e2e/accounts/conftest.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,6 @@ def currencies():
1818
return ["USD", "EUR"]
1919

2020

21-
@pytest.fixture
22-
def account_id(e2e_config):
23-
return e2e_config["accounts.account.id"]
24-
25-
26-
@pytest.fixture
27-
def seller_id(e2e_config):
28-
return e2e_config["accounts.seller.id"]
29-
30-
31-
@pytest.fixture
32-
def buyer_id(e2e_config):
33-
return e2e_config["accounts.buyer.id"]
34-
35-
3621
@pytest.fixture
3722
def user_group_id(e2e_config):
3823
return e2e_config["accounts.user_group.id"]

tests/e2e/accounts/licensees/conftest.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ def licensee_group_id(e2e_config):
1111
return e2e_config["accounts.licensee.group.id"]
1212

1313

14-
@pytest.fixture
15-
def licensee_id(e2e_config):
16-
return e2e_config["accounts.licensee.id"]
17-
18-
1914
@pytest.fixture
2015
def invalid_licensee_id():
2116
return "LCE-0000-0000-0000"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import datetime as dt
2+
3+
import pytest
4+
from dateutil.relativedelta import relativedelta
5+
from freezegun import freeze_time
6+
7+
8+
def get_iso_dt_str(dt_obj: dt.datetime) -> str:
9+
"""Convert datetime to ISO 8601 string with UTC normalization."""
10+
dt_obj = dt_obj.astimezone(dt.UTC)
11+
return dt_obj.isoformat(timespec="milliseconds").replace("+00:00", "Z")
12+
13+
14+
@pytest.fixture
15+
def invalid_agreement_id():
16+
return "AGR-0000-0000"
17+
18+
19+
@pytest.fixture
20+
def agreement_factory( # noqa: WPS211
21+
account_id,
22+
seller_id,
23+
buyer_id,
24+
licensee_id,
25+
commerce_product_id,
26+
authorization_id,
27+
):
28+
@freeze_time("2025-11-14T09:00:00.000Z")
29+
def _agreement_factory( # noqa: WPS430
30+
name: str = "E2E Created Agreement",
31+
client_external_id: str = "test-client-external-id",
32+
vendor_external_id: str = "test-vendor-external-id",
33+
):
34+
"""Factory to create agreement data."""
35+
start_date = dt.datetime.now(tz=dt.UTC)
36+
end_date = start_date + relativedelta(years=1)
37+
38+
return {
39+
"name": name,
40+
"status": "Active",
41+
"vendor": {"id": account_id},
42+
"authorization": {"id": authorization_id},
43+
"seller": {"id": seller_id},
44+
"buyer": {"id": buyer_id},
45+
"licensee": {"id": licensee_id},
46+
"product": {"id": commerce_product_id},
47+
"value": {
48+
"PPxY": 150,
49+
"PPxM": 12.5,
50+
"SPxY": 165,
51+
"SPxM": 13.75,
52+
"markup": 0.1,
53+
"margin": 0.11,
54+
"currency": "USD",
55+
},
56+
"startDate": get_iso_dt_str(start_date),
57+
"endDate": get_iso_dt_str(end_date),
58+
"externalIds": {
59+
"client": client_external_id,
60+
"vendor": vendor_external_id,
61+
},
62+
}
63+
64+
return _agreement_factory
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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_agreement(async_mpt_ops, agreement_factory):
11+
new_agreement_request_data = agreement_factory(
12+
name="E2E Created Agreement",
13+
)
14+
15+
return await async_mpt_ops.commerce.agreements.create(new_agreement_request_data)
16+
17+
18+
async def test_get_agreement_by_id(async_mpt_ops, agreement_id):
19+
result = await async_mpt_ops.commerce.agreements.get(agreement_id)
20+
21+
assert result is not None
22+
23+
24+
async def test_list_agreements(async_mpt_ops):
25+
limit = 10
26+
27+
result = await async_mpt_ops.commerce.agreements.fetch_page(limit=limit)
28+
29+
assert len(result) > 0
30+
31+
32+
async def test_get_agreement_by_id_not_found(async_mpt_ops, invalid_agreement_id):
33+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
34+
await async_mpt_ops.commerce.agreements.get(invalid_agreement_id) # act
35+
36+
37+
async def test_filter_agreements(async_mpt_ops, agreement_id):
38+
select_fields = ["-value"]
39+
filtered_agreements = (
40+
async_mpt_ops.commerce.agreements.filter(RQLQuery(id=agreement_id))
41+
.filter(RQLQuery(name="E2E Seeded For Commerce for Test Api Client Client"))
42+
.select(*select_fields)
43+
)
44+
45+
result = [filtered_agreement async for filtered_agreement in filtered_agreements.iterate()]
46+
47+
assert len(result) == 1
48+
49+
50+
def test_create_agreement(created_agreement):
51+
result = created_agreement
52+
53+
assert result is not None
54+
55+
56+
async def test_update_agreement(async_mpt_ops, created_agreement, agreement_factory):
57+
updated_name = "E2E Updated Agreement Name"
58+
updated_agreement_data = agreement_factory(name=updated_name)
59+
60+
result = await async_mpt_ops.commerce.agreements.update(
61+
created_agreement.id, updated_agreement_data
62+
)
63+
64+
assert result is not None
65+
66+
67+
async def test_get_agreement_render(async_mpt_ops, agreement_id):
68+
result = await async_mpt_ops.commerce.agreements.render(agreement_id)
69+
70+
assert result is not None
71+
72+
73+
async def test_get_agreement_template(async_mpt_ops, agreement_id):
74+
result = await async_mpt_ops.commerce.agreements.template(agreement_id)
75+
76+
assert result is not None
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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_agreement(mpt_ops, agreement_factory):
11+
new_agreement_request_data = agreement_factory(
12+
name="E2E Created Agreement",
13+
)
14+
15+
return mpt_ops.commerce.agreements.create(new_agreement_request_data)
16+
17+
18+
def test_get_agreement_by_id(mpt_ops, agreement_id):
19+
result = mpt_ops.commerce.agreements.get(agreement_id)
20+
21+
assert result is not None
22+
23+
24+
def test_list_agreements(mpt_ops):
25+
limit = 10
26+
27+
result = mpt_ops.commerce.agreements.fetch_page(limit=limit)
28+
29+
assert len(result) > 0
30+
31+
32+
def test_get_agreement_by_id_not_found(mpt_ops, invalid_agreement_id):
33+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
34+
mpt_ops.commerce.agreements.get(invalid_agreement_id) # act
35+
36+
37+
def test_filter_agreements(mpt_ops, agreement_id):
38+
select_fields = ["-value"]
39+
filtered_agreements = (
40+
mpt_ops.commerce.agreements.filter(RQLQuery(id=agreement_id))
41+
.filter(RQLQuery(name="E2E Seeded For Commerce for Test Api Client Client"))
42+
.select(*select_fields)
43+
)
44+
45+
result = list(filtered_agreements.iterate())
46+
47+
assert len(result) == 1
48+
49+
50+
def test_create_agreement(created_agreement):
51+
result = created_agreement
52+
53+
assert result is not None
54+
55+
56+
def test_update_agreement(mpt_ops, created_agreement, agreement_factory):
57+
updated_name = "E2E Updated Agreement Name"
58+
updated_agreement_data = agreement_factory(name=updated_name)
59+
60+
result = mpt_ops.commerce.agreements.update(created_agreement.id, updated_agreement_data)
61+
62+
assert result is not None
63+
64+
65+
def test_get_agreement_render(mpt_ops, agreement_id):
66+
result = mpt_ops.commerce.agreements.render(agreement_id)
67+
68+
assert result is not None
69+
70+
71+
def test_get_agreement_template(mpt_ops, agreement_id):
72+
result = mpt_ops.commerce.agreements.template(agreement_id)
73+
74+
assert result is not None

tests/e2e/commerce/conftest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def agreement_id(e2e_config):
6+
return e2e_config["commerce.agreement.id"]
7+
8+
9+
@pytest.fixture
10+
def commerce_product_id(e2e_config):
11+
return e2e_config["commerce.product.id"]

tests/e2e/conftest.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,28 @@ def logo_fd():
116116
@pytest.fixture
117117
def user_id(e2e_config):
118118
return e2e_config["accounts.user.id"]
119+
120+
121+
@pytest.fixture
122+
def account_id(e2e_config):
123+
return e2e_config["accounts.account.id"]
124+
125+
126+
@pytest.fixture
127+
def seller_id(e2e_config):
128+
return e2e_config["accounts.seller.id"]
129+
130+
131+
@pytest.fixture
132+
def buyer_id(e2e_config):
133+
return e2e_config["accounts.buyer.id"]
134+
135+
136+
@pytest.fixture
137+
def licensee_id(e2e_config):
138+
return e2e_config["accounts.licensee.id"]
139+
140+
141+
@pytest.fixture
142+
def authorization_id(e2e_config):
143+
return e2e_config["commerce.authorization.id"]

0 commit comments

Comments
 (0)