1
1
import json
2
- from collections .abc import Generator
2
+ from collections .abc import AsyncIterator , Generator , Iterator
3
3
4
4
import httpx
5
5
import pytest
15
15
'invalidItems' : {'0' : ["should have required property 'name'" ], '1' : ["should have required property 'name'" ]}
16
16
}
17
17
18
+ RAW_ERROR = (
19
+ b'{\n '
20
+ b' "error": {\n '
21
+ b' "type": "insufficient-permissions",\n '
22
+ b' "message": "Insufficient permissions for the Actor run. Make sure you\' '
23
+ b're passing a correct API token and that it has the required permissions."\n '
24
+ b' }\n '
25
+ b'}'
26
+ )
18
27
19
- @pytest .fixture (autouse = True )
28
+
29
+ @pytest .fixture
20
30
def mocked_response () -> Generator [respx .MockRouter ]:
21
31
response_content = json .dumps (
22
32
{'error' : {'message' : _EXPECTED_MESSAGE , 'type' : _EXPECTED_TYPE , 'data' : _EXPECTED_DATA }}
@@ -26,6 +36,7 @@ def mocked_response() -> Generator[respx.MockRouter]:
26
36
yield respx_mock
27
37
28
38
39
+ @pytest .mark .usefixtures ('mocked_response' )
29
40
def test_client_apify_api_error_with_data () -> None :
30
41
"""Test that client correctly throws ApifyApiError with error data from response."""
31
42
client = HTTPClient ()
@@ -38,6 +49,7 @@ def test_client_apify_api_error_with_data() -> None:
38
49
assert e .value .data == _EXPECTED_DATA
39
50
40
51
52
+ @pytest .mark .usefixtures ('mocked_response' )
41
53
async def test_async_client_apify_api_error_with_data () -> None :
42
54
"""Test that async client correctly throws ApifyApiError with error data from response."""
43
55
client = HTTPClientAsync ()
@@ -48,3 +60,53 @@ async def test_async_client_apify_api_error_with_data() -> None:
48
60
assert e .value .message == _EXPECTED_MESSAGE
49
61
assert e .value .type == _EXPECTED_TYPE
50
62
assert e .value .data == _EXPECTED_DATA
63
+
64
+
65
+ def test_client_apify_api_error_streamed () -> None :
66
+ """Test that client correctly throws ApifyApiError when the response has stream."""
67
+
68
+ error = json .loads (RAW_ERROR .decode ())
69
+
70
+ class ByteStream (httpx ._types .SyncByteStream ):
71
+ def __iter__ (self ) -> Iterator [bytes ]:
72
+ yield RAW_ERROR
73
+
74
+ def close (self ) -> None :
75
+ pass
76
+
77
+ stream_url = 'http://some-stream-url.com'
78
+
79
+ client = HTTPClient ()
80
+
81
+ with respx .mock () as respx_mock :
82
+ respx_mock .get (url = stream_url ).mock (return_value = httpx .Response (stream = ByteStream (), status_code = 403 ))
83
+ with pytest .raises (ApifyApiError ) as e :
84
+ client .call (method = 'GET' , url = stream_url , stream = True , parse_response = False )
85
+
86
+ assert e .value .message == error ['error' ]['message' ]
87
+ assert e .value .type == error ['error' ]['type' ]
88
+
89
+
90
+ async def test_async_client_apify_api_error_streamed () -> None :
91
+ """Test that async client correctly throws ApifyApiError when the response has stream."""
92
+
93
+ error = json .loads (RAW_ERROR .decode ())
94
+
95
+ class AsyncByteStream (httpx ._types .AsyncByteStream ):
96
+ async def __aiter__ (self ) -> AsyncIterator [bytes ]:
97
+ yield RAW_ERROR
98
+
99
+ async def aclose (self ) -> None :
100
+ pass
101
+
102
+ stream_url = 'http://some-stream-url.com'
103
+
104
+ client = HTTPClientAsync ()
105
+
106
+ with respx .mock () as respx_mock :
107
+ respx_mock .get (url = stream_url ).mock (return_value = httpx .Response (stream = AsyncByteStream (), status_code = 403 ))
108
+ with pytest .raises (ApifyApiError ) as e :
109
+ await client .call (method = 'GET' , url = stream_url , stream = True , parse_response = False )
110
+
111
+ assert e .value .message == error ['error' ]['message' ]
112
+ assert e .value .type == error ['error' ]['type' ]
0 commit comments