Skip to content

Commit 7748860

Browse files
authored
MPT-14934 add E2E tests for notifications batches (#169)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Streamlined file upload capability for batch notifications via improved service configuration. * **Tests** * Added comprehensive end-to-end test coverage for batch operations including creation, retrieval, filtering, and file uploads. * Enhanced category notification tests with improved fixture-based validation. <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 f96cd68 + 0a8eb2e commit 7748860

File tree

9 files changed

+126
-209
lines changed

9 files changed

+126
-209
lines changed

e2e_config.test.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
"commerce.subscription.agreement.id": "AGR-2473-3299-1721",
4747
"commerce.subscription.id": "SUB-3678-1831-2188",
4848
"commerce.subscription.product.item.id": "ITM-1767-7355-0001",
49+
"notifications.batch.id": "MST-3638-2460-4825",
50+
"notifications.category.id": "NTC-6157-0397",
4951
"notifications.subscriber.id": "NTS-0829-7123-7123",
5052
"notifications.message.id": "MSG-0000-6215-1019-0139"
5153
}

mpt_api_client/resources/notifications/batches.py

Lines changed: 7 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
from httpx._types import FileTypes
2-
31
from mpt_api_client.http import AsyncService, Service
4-
from mpt_api_client.http.client import json_to_file_payload
52
from mpt_api_client.http.mixins import (
63
AsyncCollectionMixin,
4+
AsyncCreateFileMixin,
75
AsyncGetMixin,
86
CollectionMixin,
7+
CreateFileMixin,
98
GetMixin,
109
)
11-
from mpt_api_client.models import FileModel, Model, ResourceData
10+
from mpt_api_client.models import FileModel, Model
1211

1312

1413
class Batch(Model):
@@ -21,44 +20,19 @@ class BatchesServiceConfig:
2120
_endpoint = "/public/v1/notifications/batches"
2221
_model_class = Batch
2322
_collection_key = "data"
23+
_upload_file_key = "attachment"
24+
_upload_data_key = "batch"
2425

2526

2627
class BatchesService(
28+
CreateFileMixin[Batch],
2729
GetMixin[Batch],
2830
CollectionMixin[Batch],
2931
Service[Batch],
3032
BatchesServiceConfig,
3133
):
3234
"""Notifications Batches service."""
3335

34-
def create(
35-
self,
36-
resource_data: ResourceData | None = None,
37-
files: dict[str, FileTypes] | None = None, # noqa: WPS221
38-
data_key: str = "_attachment_data",
39-
) -> Model:
40-
"""Create batch with attachments.
41-
42-
Args:
43-
resource_data: batch data.
44-
files: Files data.
45-
data_key: Key to use for the JSON data in the multipart form.
46-
47-
Returns:
48-
Created resource.
49-
"""
50-
files = files or {}
51-
52-
if resource_data:
53-
files[data_key] = (
54-
None,
55-
json_to_file_payload(resource_data),
56-
"application/json",
57-
)
58-
59-
response = self.http_client.request("post", self.path, files=files)
60-
return self._model_class.from_response(response)
61-
6236
def get_batch_attachment(self, batch_id: str, attachment_id: str) -> FileModel:
6337
"""Get batch attachment.
6438
@@ -77,41 +51,14 @@ def get_batch_attachment(self, batch_id: str, attachment_id: str) -> FileModel:
7751

7852

7953
class AsyncBatchesService(
54+
AsyncCreateFileMixin[Batch],
8055
AsyncGetMixin[Batch],
8156
AsyncCollectionMixin[Batch],
8257
AsyncService[Batch],
8358
BatchesServiceConfig,
8459
):
8560
"""Async Notifications Batches service."""
8661

87-
async def create(
88-
self,
89-
resource_data: ResourceData | None = None,
90-
files: dict[str, FileTypes] | None = None, # noqa: WPS221
91-
data_key: str = "_attachment_data",
92-
) -> Model:
93-
"""Create batch with attachments.
94-
95-
Args:
96-
resource_data: batch data.
97-
files: Files data.
98-
data_key: Key to use for the JSON data in the multipart form.
99-
100-
Returns:
101-
Created resource.
102-
"""
103-
files = files or {}
104-
105-
if resource_data:
106-
files[data_key] = (
107-
None,
108-
json_to_file_payload(resource_data),
109-
"application/json",
110-
)
111-
112-
response = await self.http_client.request("post", self.path, files=files)
113-
return self._model_class.from_response(response)
114-
11562
async def get_batch_attachment(self, batch_id: str, attachment_id: str) -> FileModel:
11663
"""Get batch attachment.
11764
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def batch_service(mpt_ops):
6+
return mpt_ops.notifications.batches
7+
8+
9+
@pytest.fixture
10+
def async_batch_service(async_mpt_ops):
11+
return async_mpt_ops.notifications.batches
12+
13+
14+
@pytest.fixture
15+
def batch_id(e2e_config):
16+
return e2e_config["notifications.batch.id"]
17+
18+
19+
@pytest.fixture
20+
def batch_data(category_id, short_uuid):
21+
return {
22+
"category": {"id": category_id},
23+
"subject": f"E2E - please delete - {short_uuid}",
24+
"body": "Hello world",
25+
"contacts": [{"email": f"{short_uuid}@example.com"}],
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
3+
from mpt_api_client.rql.query_builder import RQLQuery
4+
5+
6+
@pytest.mark.skip(reason="Batches can not be deleted")
7+
async def test_create_batch(async_batch_service, batch_data):
8+
result = await async_batch_service.create(batch_data)
9+
10+
assert result is not None
11+
12+
13+
async def test_get_batch(async_batch_service, batch_id):
14+
result = await async_batch_service.get(batch_id)
15+
16+
assert result.id == batch_id
17+
18+
19+
async def test_iterate_and_filter(async_batch_service, batch_id):
20+
batches = [batch async for batch in async_batch_service.filter(RQLQuery(id=batch_id)).iterate()]
21+
22+
assert len(batches) == 1
23+
assert batches[0].id == batch_id
24+
25+
26+
@pytest.mark.skip(reason="Batches can not be deleted")
27+
async def test_create_batch_with_file(async_batch_service, batch_data, logo_fd):
28+
result = await async_batch_service.create(batch_data, file=logo_fd)
29+
30+
assert result is not None
31+
32+
33+
@pytest.mark.skip(reason="Batches attachments not implemented")
34+
async def test_download_attachment():
35+
# TODO - Implement get and download E2E tests for attachments
36+
raise NotImplementedError
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
3+
from mpt_api_client import RQLQuery
4+
5+
6+
@pytest.mark.skip(reason="Batches can not be deleted")
7+
def test_create_batch(batch_service, batch_data):
8+
result = batch_service.create(batch_data)
9+
10+
assert result is not None
11+
12+
13+
def test_get_batch(batch_service, batch_id):
14+
result = batch_service.get(batch_id)
15+
16+
assert result.id == batch_id
17+
18+
19+
def test_iterate_and_filter(batch_service, batch_id):
20+
result = list(batch_service.filter(RQLQuery(id=batch_id)).iterate())
21+
22+
assert len(result) == 1
23+
assert result[0].id == batch_id
24+
25+
26+
@pytest.mark.skip(reason="Batches can not be deleted")
27+
def test_create_batch_with_file(batch_service, batch_data, logo_fd):
28+
result = batch_service.create(batch_data, file=logo_fd)
29+
30+
assert result is not None
31+
32+
33+
@pytest.mark.skip(reason="Batches attachments not implemented") # noqa: AAA01
34+
def test_download_attachment():
35+
# TODO - Implement get and download E2E tests for attachment
36+
raise NotImplementedError

tests/e2e/notifications/categories/test_async_categories.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,19 @@ async def async_created_category(async_mpt_ops, category_data):
1717
print(f"TEARDOWN - Unable to delete category {category.id}: {error.title}") # noqa: WPS421
1818

1919

20-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785") # noqa: AAA01
21-
def test_create_category(async_created_category, category_data):
20+
def test_create_category(async_created_category, category_data): # noqa: AAA01
2221
assert async_created_category.name == category_data["name"]
2322
assert async_created_category.description == category_data["description"]
2423

2524

26-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
27-
async def test_get_category(async_mpt_vendor, async_created_category):
25+
async def test_get_category(async_mpt_vendor, category_id):
2826
service = async_mpt_vendor.notifications.categories
2927

30-
result = await service.get(async_created_category.id)
28+
result = await service.get(category_id)
3129

32-
assert result.id == async_created_category.id
33-
assert result.name == async_created_category.name
30+
assert result.id == category_id
3431

3532

36-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
3733
async def test_update_category(async_mpt_ops, async_created_category):
3834
service = async_mpt_ops.notifications.categories
3935
update_data = {
@@ -47,26 +43,13 @@ async def test_update_category(async_mpt_ops, async_created_category):
4743
assert result.description == "Async updated description"
4844

4945

50-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
51-
async def test_list_categories(async_mpt_vendor, async_created_category):
46+
async def test_filter_categories(async_mpt_vendor, category_id):
5247
service = async_mpt_vendor.notifications.categories
5348

54-
result = [category async for category in service.iterate()]
55-
56-
assert any(category.id == async_created_category.id for category in result)
57-
58-
59-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
60-
async def test_filter_categories(async_mpt_vendor, async_created_category):
61-
service = async_mpt_vendor.notifications.categories
62-
63-
result = [
64-
category
65-
async for category in service.filter(RQLQuery(id=async_created_category.id)).iterate()
66-
]
49+
result = [category async for category in service.filter(RQLQuery(id=category_id)).iterate()]
6750

6851
assert len(result) == 1
69-
assert result[0].id == async_created_category.id
52+
assert result[0].id == category_id
7053

7154

7255
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
@@ -98,15 +81,11 @@ async def test_category_not_found(async_mpt_vendor, invalid_category_id):
9881
await service.get(invalid_category_id)
9982

10083

101-
@pytest.mark.skip(reason="async_created_category kills performance due to MPT-13785")
10284
async def test_delete_category(async_mpt_ops, async_created_category):
10385
service = async_mpt_ops.notifications.categories
10486

10587
await service.delete(async_created_category.id)
10688

107-
with pytest.raises(MPTAPIError):
108-
await service.get(async_created_category.id)
109-
11089

11190
async def test_delete_category_not_found(async_mpt_ops, invalid_category_id):
11291
service = async_mpt_ops.notifications.categories

tests/e2e/notifications/categories/test_sync_categories.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,18 @@ def created_category(mpt_ops, category_data):
1717
print(f"TEARDOWN - Unable to delete category {category.id}: {error.title}") # noqa: WPS421
1818

1919

20-
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
2120
def test_create_category(created_category, category_data):
2221
assert created_category.name == category_data["name"] # act
2322

2423
assert created_category.description == category_data["description"]
2524

2625

27-
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
28-
def test_get_category(mpt_client, created_category):
26+
def test_get_category(mpt_client, category_id):
2927
service = mpt_client.notifications.categories
3028

31-
result = service.get(created_category.id)
29+
result = service.get(category_id)
3230

33-
assert result.id == created_category.id
34-
assert result.name == created_category.name
31+
assert result.id == category_id
3532

3633

3734
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
@@ -48,23 +45,13 @@ def test_update_category(mpt_ops, created_category):
4845
assert result.description == "Updated description"
4946

5047

51-
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
52-
def test_list_categories(mpt_client, created_category):
48+
def test_filter_categories(mpt_client, category_id):
5349
service = mpt_client.notifications.categories
5450

55-
result = list(service.iterate())
56-
57-
assert any(category.id == created_category.id for category in result)
58-
59-
60-
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
61-
def test_filter_categories(mpt_client, created_category):
62-
service = mpt_client.notifications.categories
63-
64-
result = list(service.filter(RQLQuery(id=created_category.id)).iterate())
51+
result = list(service.filter(RQLQuery(id=category_id)).iterate())
6552

6653
assert len(result) == 1
67-
assert result[0].id == created_category.id
54+
assert result[0].id == category_id
6855

6956

7057
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
@@ -96,15 +83,11 @@ def test_category_not_found(mpt_client, invalid_category_id):
9683
service.get(invalid_category_id)
9784

9885

99-
@pytest.mark.skip(reason="created_category kills performance due to MPT-13785")
10086
def test_delete_category(mpt_ops, created_category):
10187
service = mpt_ops.notifications.categories
10288

10389
service.delete(created_category.id) # act
10490

105-
with pytest.raises(MPTAPIError):
106-
service.get(created_category.id)
107-
10891

10992
def test_delete_category_not_found(mpt_ops, invalid_category_id):
11093
service = mpt_ops.notifications.categories
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def category_id(e2e_config):
6+
return e2e_config["notifications.category.id"]

0 commit comments

Comments
 (0)