Skip to content

Commit 9521013

Browse files
authored
[MPT-14909] Added e2e tests for commerce order subscription (#165)
Added e2e tests for commerce order subscription https://softwareone.atlassian.net/browse/MPT-14909 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added comprehensive end-to-end tests (sync + async) for order subscriptions covering CRUD, list/paginate, filter/select, not-found scenarios, and resilient teardown. * Added fixtures and a deterministic factory with frozen timestamp to produce repeatable subscription test data. * **Chores** * Test configuration updated with a new subscription line identifier used by e2e suites. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents 0699809 + a47325a commit 9521013

File tree

5 files changed

+244
-0
lines changed

5 files changed

+244
-0
lines changed

e2e_config.test.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"catalog.unit.id": "UNT-1229",
2727
"commerce.agreement.attachment.id": "ATT-9850-2169-6098-0001",
2828
"commerce.agreement.id": "AGR-9850-2169-6098",
29+
"commerce.agreement.subscription.line.id": "ALI-9850-2169-6098-0001",
2930
"commerce.assets.agreement.id": "AGR-2473-3299-1721",
3031
"commerce.assets.id": "AST-0625-6526-6154",
3132
"commerce.assets.order.id": "ORD-7707-7765-8445",

tests/e2e/commerce/conftest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,18 @@ def asset_item_id(e2e_config):
4949
@pytest.fixture
5050
def asset_agreement_id(e2e_config):
5151
return e2e_config["commerce.assets.agreement.id"]
52+
53+
54+
@pytest.fixture
55+
def subscription_id(e2e_config):
56+
return e2e_config["commerce.subscription.id"]
57+
58+
59+
@pytest.fixture
60+
def agreement_subscription_line_id(e2e_config):
61+
return e2e_config["commerce.agreement.subscription.line.id"]
62+
63+
64+
@pytest.fixture
65+
def invalid_subscription_id():
66+
return "SUB-0000-0000-0000"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
from freezegun import freeze_time
3+
4+
5+
@pytest.fixture
6+
def order_subscription_factory(agreement_subscription_line_id):
7+
@freeze_time("2025-11-14T09:00:00.000Z")
8+
def factory(
9+
name: str = "E2E Created Order Subscription",
10+
external_vendor_id: str = "ext-vendor-id",
11+
):
12+
return {
13+
"name": name,
14+
"startDate": "2025-11-03T09:00:00.000Z",
15+
"commitmentDate": "2026-11-02T09:00:00.000Z",
16+
"autoRenew": True,
17+
"externalIds": {"vendor": external_vendor_id},
18+
"template": None,
19+
"lines": [{"id": agreement_subscription_line_id}],
20+
"parameters": {"fulfillment": []},
21+
}
22+
23+
return factory
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from contextlib import asynccontextmanager
2+
3+
import pytest
4+
5+
from mpt_api_client.exceptions import MPTAPIError
6+
from mpt_api_client.rql.query_builder import RQLQuery
7+
8+
pytestmark = [pytest.mark.flaky]
9+
10+
11+
@asynccontextmanager
12+
async def async_create_fixture_resource_and_delete(resource_manager, resource_data):
13+
resource = await resource_manager.create(resource_data)
14+
15+
yield resource
16+
17+
try:
18+
await resource_manager.delete(resource.id)
19+
except MPTAPIError as error:
20+
print(f"TEARDOWN - Unable to delete subscription: {getattr(error, 'title', str(error))}") # noqa: WPS421
21+
22+
23+
@pytest.fixture
24+
async def created_order_subscription(async_mpt_vendor, order_subscription_factory, order_id):
25+
# Must use this fixture for all tests to prevent api failures
26+
subscription_data = order_subscription_factory()
27+
orders = async_mpt_vendor.commerce.orders
28+
subscriptions = orders.subscriptions(order_id)
29+
async with async_create_fixture_resource_and_delete(
30+
subscriptions, subscription_data
31+
) as subscription:
32+
yield subscription
33+
34+
35+
async def test_get_order_subscription_by_id(async_mpt_vendor, created_order_subscription, order_id):
36+
subscription_id = created_order_subscription.id
37+
subscriptions = async_mpt_vendor.commerce.orders.subscriptions(order_id)
38+
39+
result = await subscriptions.get(subscription_id)
40+
41+
assert result is not None
42+
43+
44+
async def test_list_order_subscriptions(async_mpt_vendor, created_order_subscription, order_id):
45+
limit = 10
46+
orders = async_mpt_vendor.commerce.orders
47+
subscriptions = orders.subscriptions(order_id)
48+
49+
result = await subscriptions.fetch_page(limit=limit)
50+
51+
assert result is not None
52+
53+
54+
async def test_get_order_subscription_by_id_not_found(
55+
async_mpt_vendor, created_order_subscription, order_id, invalid_subscription_id
56+
):
57+
orders = async_mpt_vendor.commerce.orders
58+
subscriptions = orders.subscriptions(order_id)
59+
60+
with pytest.raises(MPTAPIError, match="404 Not Found"):
61+
await subscriptions.get(invalid_subscription_id)
62+
63+
64+
async def test_filter_order_subscriptions(async_mpt_vendor, created_order_subscription, order_id):
65+
select_fields = ["-externalIds"]
66+
subscription_id = created_order_subscription.id
67+
subscriptions = async_mpt_vendor.commerce.orders.subscriptions(order_id)
68+
filtered_subscriptions = (
69+
subscriptions.filter(RQLQuery(id=subscription_id))
70+
.filter(RQLQuery(name="E2E Created Order Subscription"))
71+
.select(*select_fields)
72+
)
73+
74+
result = [subscription async for subscription in filtered_subscriptions.iterate()]
75+
76+
assert len(result) == 1
77+
78+
79+
def test_create_order_subscription(created_order_subscription):
80+
result = created_order_subscription
81+
82+
assert result is not None
83+
84+
85+
async def test_update_order_subscription(async_mpt_vendor, created_order_subscription, order_id):
86+
subscription_id = created_order_subscription.id
87+
updated_subscription_data = {
88+
"name": "E2E Updated Order Subscription",
89+
}
90+
orders = async_mpt_vendor.commerce.orders
91+
subscriptions = orders.subscriptions(order_id)
92+
93+
result = await subscriptions.update(subscription_id, updated_subscription_data)
94+
95+
assert result is not None
96+
97+
98+
async def test_delete_order_subscription(async_mpt_vendor, created_order_subscription, order_id):
99+
subscription_id = created_order_subscription.id
100+
orders = async_mpt_vendor.commerce.orders
101+
102+
subscriptions = orders.subscriptions(order_id)
103+
await subscriptions.delete(subscription_id)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from contextlib import contextmanager
2+
3+
import pytest
4+
5+
from mpt_api_client.exceptions import MPTAPIError
6+
from mpt_api_client.rql.query_builder import RQLQuery
7+
8+
pytestmark = [pytest.mark.flaky]
9+
10+
11+
@contextmanager
12+
def create_fixture_resource_and_delete(resource_manager, resource_data):
13+
resource = resource_manager.create(resource_data)
14+
15+
yield resource
16+
17+
try:
18+
resource_manager.delete(resource.id)
19+
except MPTAPIError as error:
20+
print(f"TEARDOWN - Unable to delete subscription: {getattr(error, 'title', str(error))}") # noqa: WPS421
21+
22+
23+
@pytest.fixture
24+
def created_order_subscription(mpt_vendor, order_subscription_factory, order_id):
25+
# Must use this fixture for all tests to prevent api failures
26+
subscription_data = order_subscription_factory()
27+
orders = mpt_vendor.commerce.orders
28+
subscriptions = orders.subscriptions(order_id)
29+
with create_fixture_resource_and_delete(subscriptions, subscription_data) as subscription:
30+
yield subscription
31+
32+
33+
def test_get_order_subscription_by_id(mpt_vendor, created_order_subscription, order_id):
34+
subscription_id = created_order_subscription.id
35+
subscriptions = mpt_vendor.commerce.orders.subscriptions(order_id)
36+
37+
result = subscriptions.get(subscription_id)
38+
39+
assert result is not None
40+
41+
42+
def test_list_order_subscriptions(mpt_vendor, created_order_subscription, order_id):
43+
limit = 10
44+
orders = mpt_vendor.commerce.orders
45+
subscriptions = orders.subscriptions(order_id)
46+
47+
result = subscriptions.fetch_page(limit=limit)
48+
49+
assert result is not None
50+
51+
52+
def test_get_order_subscription_by_id_not_found(
53+
mpt_vendor, created_order_subscription, order_id, invalid_subscription_id
54+
):
55+
orders = mpt_vendor.commerce.orders
56+
subscriptions = orders.subscriptions(order_id)
57+
58+
with pytest.raises(MPTAPIError, match="404 Not Found"):
59+
subscriptions.get(invalid_subscription_id)
60+
61+
62+
def test_filter_order_subscriptions(mpt_vendor, created_order_subscription, order_id):
63+
select_fields = ["-externalIds"]
64+
subscription_id = created_order_subscription.id
65+
subscriptions = mpt_vendor.commerce.orders.subscriptions(order_id)
66+
filtered_subscriptions = (
67+
subscriptions.filter(RQLQuery(id=subscription_id))
68+
.filter(RQLQuery(name="E2E Created Order Subscription"))
69+
.select(*select_fields)
70+
)
71+
72+
result = list(filtered_subscriptions.iterate())
73+
74+
assert len(result) == 1
75+
76+
77+
def test_create_order_subscription(created_order_subscription):
78+
result = created_order_subscription
79+
80+
assert result is not None
81+
82+
83+
def test_update_order_subscription(mpt_vendor, created_order_subscription, order_id):
84+
subscription_id = created_order_subscription.id
85+
updated_subscription_data = {
86+
"name": "E2E Updated Order Subscription",
87+
}
88+
orders = mpt_vendor.commerce.orders
89+
subscriptions = orders.subscriptions(order_id)
90+
91+
result = subscriptions.update(subscription_id, updated_subscription_data)
92+
93+
assert result is not None
94+
95+
96+
def test_delete_order_subscription(mpt_vendor, created_order_subscription, order_id):
97+
subscription_id = created_order_subscription.id
98+
orders = mpt_vendor.commerce.orders
99+
100+
result = orders.subscriptions(order_id)
101+
102+
result.delete(subscription_id)

0 commit comments

Comments
 (0)