1
1
from __future__ import annotations
2
2
3
+ import json
4
+ import time
3
5
from typing import TYPE_CHECKING
4
6
5
7
import pytest
8
+ from werkzeug import Response
6
9
7
10
from apify_client ._errors import ApifyApiError
8
11
from apify_client ._http_client import HTTPClient , HTTPClientAsync
9
12
10
13
if TYPE_CHECKING :
14
+ from collections .abc import Iterator
15
+
11
16
from pytest_httpserver import HTTPServer
17
+ from werkzeug import Request
12
18
13
19
_TEST_PATH = '/errors'
14
20
_EXPECTED_MESSAGE = 'some_message'
17
23
'invalidItems' : {'0' : ["should have required property 'name'" ], '1' : ["should have required property 'name'" ]}
18
24
}
19
25
26
+ RAW_ERROR = (
27
+ b'{\n '
28
+ b' "error": {\n '
29
+ b' "type": "insufficient-permissions",\n '
30
+ b' "message": "Insufficient permissions for the Actor run. Make sure you\' '
31
+ b're passing a correct API token and that it has the required permissions."\n '
32
+ b' }\n '
33
+ b'}'
34
+ )
35
+
20
36
21
37
@pytest .fixture
22
38
def test_endpoint (httpserver : HTTPServer ) -> str :
@@ -26,6 +42,22 @@ def test_endpoint(httpserver: HTTPServer) -> str:
26
42
return str (httpserver .url_for (_TEST_PATH ))
27
43
28
44
45
+ def streaming_handler (_request : Request ) -> Response :
46
+ """Handler for streaming log requests."""
47
+
48
+ def generate_response () -> Iterator [bytes ]:
49
+ for i in range (len (RAW_ERROR )):
50
+ yield RAW_ERROR [i : i + 1 ]
51
+ time .sleep (0.01 )
52
+
53
+ return Response (
54
+ response = (RAW_ERROR [i : i + 1 ] for i in range (len (RAW_ERROR ))),
55
+ status = 403 ,
56
+ mimetype = 'application/octet-stream' ,
57
+ headers = {'Content-Length' : str (len (RAW_ERROR ))},
58
+ )
59
+
60
+
29
61
def test_client_apify_api_error_with_data (test_endpoint : str ) -> None :
30
62
"""Test that client correctly throws ApifyApiError with error data from response."""
31
63
client = HTTPClient ()
@@ -48,3 +80,35 @@ async def test_async_client_apify_api_error_with_data(test_endpoint: str) -> Non
48
80
assert e .value .message == _EXPECTED_MESSAGE
49
81
assert e .value .type == _EXPECTED_TYPE
50
82
assert e .value .data == _EXPECTED_DATA
83
+
84
+
85
+ def test_client_apify_api_error_streamed (httpserver : HTTPServer ) -> None :
86
+ """Test that client correctly throws ApifyApiError when the response has stream."""
87
+
88
+ error = json .loads (RAW_ERROR .decode ())
89
+
90
+ client = HTTPClient ()
91
+
92
+ httpserver .expect_request ('/stream_error' ).respond_with_handler (streaming_handler )
93
+
94
+ with pytest .raises (ApifyApiError ) as e :
95
+ client .call (method = 'GET' , url = httpserver .url_for ('/stream_error' ), stream = True , parse_response = False )
96
+
97
+ assert e .value .message == error ['error' ]['message' ]
98
+ assert e .value .type == error ['error' ]['type' ]
99
+
100
+
101
+ async def test_async_client_apify_api_error_streamed (httpserver : HTTPServer ) -> None :
102
+ """Test that async client correctly throws ApifyApiError when the response has stream."""
103
+
104
+ error = json .loads (RAW_ERROR .decode ())
105
+
106
+ client = HTTPClientAsync ()
107
+
108
+ httpserver .expect_request ('/stream_error' ).respond_with_handler (streaming_handler )
109
+
110
+ with pytest .raises (ApifyApiError ) as e :
111
+ await client .call (method = 'GET' , url = httpserver .url_for ('/stream_error' ), stream = True , parse_response = False )
112
+
113
+ assert e .value .message == error ['error' ]['message' ]
114
+ assert e .value .type == error ['error' ]['type' ]
0 commit comments