Skip to content

Commit df8c5a0

Browse files
committed
feat: Add comprehensive unit tests for AsyncHttpClient and enhance API method tests to include resource handling.
1 parent ad4b590 commit df8c5a0

3 files changed

Lines changed: 353 additions & 1 deletion

File tree

amazon_creatorsapi/aio/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
try:
44
import httpx # noqa: F401
5-
except ImportError as exc:
5+
except ImportError as exc: # pragma: no cover
66
msg = (
77
"httpx is required for async support. "
88
"Install with: pip install python-amazon-paapi[async]"

tests/amazon_creatorsapi/aio/api_test.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
TooManyRequestsError,
1515
)
1616
from creatorsapi_python_sdk.models.condition import Condition
17+
from creatorsapi_python_sdk.models.get_browse_nodes_resource import (
18+
GetBrowseNodesResource,
19+
)
20+
from creatorsapi_python_sdk.models.get_items_resource import GetItemsResource
21+
from creatorsapi_python_sdk.models.get_variations_resource import GetVariationsResource
22+
from creatorsapi_python_sdk.models.search_items_resource import SearchItemsResource
1723
from creatorsapi_python_sdk.models.sort_by import SortBy
1824

1925

@@ -120,6 +126,22 @@ async def test_context_manager_creates_and_closes_client(
120126

121127
mock_client.__aexit__.assert_called_once()
122128

129+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
130+
async def test_context_manager_exit_without_client(
131+
self,
132+
mock_token_manager: MagicMock,
133+
) -> None:
134+
"""Test __aexit__ works explicitly when no client initialized."""
135+
api = AsyncAmazonCreatorsApi(
136+
credential_id="test_id",
137+
credential_secret="test_secret",
138+
version="2.2",
139+
tag="test-tag",
140+
country="ES",
141+
)
142+
# Should not raise
143+
await api.__aexit__(None, None, None)
144+
123145

124146
class TestAsyncAmazonCreatorsApiGetItems(unittest.IsolatedAsyncioTestCase):
125147
"""Tests for get_items() method."""
@@ -166,6 +188,45 @@ async def test_get_items_success(
166188

167189
self.assertEqual(len(items), 1)
168190

191+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
192+
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
193+
async def test_get_items_with_resources(
194+
self,
195+
mock_http_client_class: MagicMock,
196+
mock_token_manager_class: MagicMock,
197+
) -> None:
198+
"""Test get_items with explicit resources."""
199+
mock_response = MagicMock()
200+
mock_response.status_code = 200
201+
mock_response.json.return_value = {
202+
"itemsResult": {"items": [{"ASIN": "B0DLFMFBJW"}]}
203+
}
204+
205+
mock_client = AsyncMock()
206+
mock_client.post.return_value = mock_response
207+
mock_client.__aenter__.return_value = mock_client
208+
mock_http_client_class.return_value = mock_client
209+
210+
mock_token_manager = AsyncMock()
211+
mock_token_manager.get_token.return_value = "test_token"
212+
mock_token_manager_class.return_value = mock_token_manager
213+
214+
async with AsyncAmazonCreatorsApi(
215+
credential_id="test_id",
216+
credential_secret="test_secret",
217+
version="2.2",
218+
tag="test-tag",
219+
country="ES",
220+
) as api:
221+
items = await api.get_items(
222+
["B0DLFMFBJW"], resources=[GetItemsResource.ITEM_INFO_DOT_TITLE]
223+
)
224+
225+
self.assertEqual(len(items), 1)
226+
# Verify resources were passed
227+
call_args = mock_client.post.call_args
228+
self.assertIn("'resources': ['itemInfo.title']", str(call_args))
229+
169230
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
170231
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
171232
async def test_get_items_not_found(
@@ -280,6 +341,72 @@ async def test_search_items_success(
280341

281342
self.assertIsNotNone(result)
282343

344+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
345+
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
346+
async def test_search_items_with_resources(
347+
self,
348+
mock_http_client_class: MagicMock,
349+
mock_token_manager_class: MagicMock,
350+
) -> None:
351+
"""Test search_items with explicit resources."""
352+
mock_response = MagicMock()
353+
mock_response.status_code = 200
354+
mock_response.json.return_value = {
355+
"searchResult": {"items": [{"ASIN": "B0DLFMFBJY"}]}
356+
}
357+
mock_client = AsyncMock()
358+
mock_client.post.return_value = mock_response
359+
mock_client.__aenter__.return_value = mock_client
360+
mock_http_client_class.return_value = mock_client
361+
mock_token_manager = AsyncMock()
362+
mock_token_manager.get_token.return_value = "test_token"
363+
mock_token_manager_class.return_value = mock_token_manager
364+
365+
async with AsyncAmazonCreatorsApi(
366+
credential_id="test_id",
367+
credential_secret="test_secret",
368+
version="2.2",
369+
tag="test-tag",
370+
country="ES",
371+
) as api:
372+
await api.search_items(
373+
keywords="test", resources=[SearchItemsResource.ITEM_INFO_DOT_TITLE]
374+
)
375+
376+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
377+
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
378+
async def test_search_items_without_keywords(
379+
self,
380+
mock_http_client_class: MagicMock,
381+
mock_token_manager_class: MagicMock,
382+
) -> None:
383+
"""Test search_items without keywords (using other params)."""
384+
mock_response = MagicMock()
385+
mock_response.status_code = 200
386+
mock_response.json.return_value = {
387+
"searchResult": {"items": [{"ASIN": "B0DLFMFBJY"}]}
388+
}
389+
mock_client = AsyncMock()
390+
mock_client.post.return_value = mock_response
391+
mock_client.__aenter__.return_value = mock_client
392+
mock_http_client_class.return_value = mock_client
393+
mock_token_manager = AsyncMock()
394+
mock_token_manager.get_token.return_value = "test_token"
395+
mock_token_manager_class.return_value = mock_token_manager
396+
397+
async with AsyncAmazonCreatorsApi(
398+
credential_id="test_id",
399+
credential_secret="test_secret",
400+
version="2.2",
401+
tag="test-tag",
402+
country="ES",
403+
) as api:
404+
await api.search_items(browse_node_id="123456")
405+
406+
call_args = mock_client.post.call_args
407+
self.assertNotIn("keywords", str(call_args))
408+
self.assertIn("browseNodeId", str(call_args))
409+
283410

284411
class TestAsyncAmazonCreatorsApiErrorHandling(unittest.IsolatedAsyncioTestCase):
285412
"""Tests for error handling."""
@@ -467,6 +594,38 @@ async def test_get_variations_success(
467594

468595
self.assertIsNotNone(result)
469596

597+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
598+
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
599+
async def test_get_variations_with_resources(
600+
self,
601+
mock_http_client_class: MagicMock,
602+
mock_token_manager_class: MagicMock,
603+
) -> None:
604+
"""Test get_variations with explicit resources."""
605+
mock_response = MagicMock()
606+
mock_response.status_code = 200
607+
mock_response.json.return_value = {
608+
"variationsResult": {"items": [{"ASIN": "B0DLFMFBJV"}]}
609+
}
610+
mock_client = AsyncMock()
611+
mock_client.post.return_value = mock_response
612+
mock_client.__aenter__.return_value = mock_client
613+
mock_http_client_class.return_value = mock_client
614+
mock_token_manager = AsyncMock()
615+
mock_token_manager.get_token.return_value = "test_token"
616+
mock_token_manager_class.return_value = mock_token_manager
617+
618+
async with AsyncAmazonCreatorsApi(
619+
credential_id="test_id",
620+
credential_secret="test_secret",
621+
version="2.2",
622+
tag="test-tag",
623+
country="ES",
624+
) as api:
625+
await api.get_variations(
626+
"B0DLFMFBJV", resources=[GetVariationsResource.ITEM_INFO_DOT_TITLE]
627+
)
628+
470629
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
471630
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
472631
async def test_get_variations_with_params(
@@ -585,6 +744,40 @@ async def test_get_browse_nodes_success(
585744

586745
self.assertEqual(len(result), 1)
587746

747+
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
748+
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
749+
async def test_get_browse_nodes_with_resources(
750+
self,
751+
mock_http_client_class: MagicMock,
752+
mock_token_manager_class: MagicMock,
753+
) -> None:
754+
"""Test get_browse_nodes with explicit resources."""
755+
mock_response = MagicMock()
756+
mock_response.status_code = 200
757+
mock_response.json.return_value = {
758+
"browseNodesResult": {
759+
"browseNodes": [{"Id": "123456", "DisplayName": "Electronics"}]
760+
}
761+
}
762+
mock_client = AsyncMock()
763+
mock_client.post.return_value = mock_response
764+
mock_client.__aenter__.return_value = mock_client
765+
mock_http_client_class.return_value = mock_client
766+
mock_token_manager = AsyncMock()
767+
mock_token_manager.get_token.return_value = "test_token"
768+
mock_token_manager_class.return_value = mock_token_manager
769+
770+
async with AsyncAmazonCreatorsApi(
771+
credential_id="test_id",
772+
credential_secret="test_secret",
773+
version="2.2",
774+
tag="test-tag",
775+
country="ES",
776+
) as api:
777+
await api.get_browse_nodes(
778+
["123456"], resources=[GetBrowseNodesResource.BROWSE_NODES_DOT_ANCESTOR]
779+
)
780+
588781
@patch("amazon_creatorsapi.aio.api.AsyncOAuth2TokenManager")
589782
@patch("amazon_creatorsapi.aio.api.AsyncHttpClient")
590783
async def test_get_browse_nodes_with_languages(

0 commit comments

Comments
 (0)