11import os
2+ import sys
23from asyncio import iscoroutine
34from typing import Any , Dict
5+ from unittest import mock
46
57import pytest
68from _pytest .logging import LogCaptureFixture # NOQA
2325
2426
2527class TestAPI :
28+ @staticmethod
29+ async def produce_request_response (meta , custom_settings = None ):
30+ with MockServer () as server :
31+ async with make_handler (custom_settings , server .urljoin ("/" )) as handler :
32+ req = Request (
33+ "http://example.com" ,
34+ method = "POST" ,
35+ meta = meta ,
36+ )
37+ coro = handler ._download_request (req , None )
38+ assert iscoroutine (coro )
39+ assert not isinstance (coro , Deferred )
40+ resp = await coro # type: ignore
41+ return req , resp
42+
2643 @pytest .mark .parametrize (
2744 "meta" ,
2845 [
@@ -34,25 +51,14 @@ class TestAPI:
3451 )
3552 @pytest .mark .asyncio
3653 async def test_browser_html_request (self , meta : Dict [str , Dict [str , Any ]]):
37- with MockServer () as server :
38- async with make_handler ({}, server .urljoin ("/" )) as handler :
39- req = Request (
40- "http://example.com" ,
41- method = "POST" ,
42- meta = meta ,
43- )
44- coro = handler ._download_request (req , Spider ("test" ))
45- assert iscoroutine (coro )
46- assert not isinstance (coro , Deferred )
47- resp = await coro # type: ignore
48-
49- assert isinstance (resp , TextResponse )
50- assert resp .request is req
51- assert resp .url == req .url
52- assert resp .status == 200
53- assert "zyte-api" in resp .flags
54- assert resp .body == b"<html></html>"
55- assert resp .text == "<html></html>"
54+ req , resp = await self .produce_request_response (meta )
55+ assert isinstance (resp , TextResponse )
56+ assert resp .request is req
57+ assert resp .url == req .url
58+ assert resp .status == 200
59+ assert "zyte-api" in resp .flags
60+ assert resp .body == b"<html></html>"
61+ assert resp .text == "<html></html>"
5662
5763 @pytest .mark .parametrize (
5864 "meta" ,
@@ -71,24 +77,13 @@ async def test_browser_html_request(self, meta: Dict[str, Dict[str, Any]]):
7177 )
7278 @pytest .mark .asyncio
7379 async def test_http_response_body_request (self , meta : Dict [str , Dict [str , Any ]]):
74- with MockServer () as server :
75- async with make_handler ({}, server .urljoin ("/" )) as handler :
76- req = Request (
77- "http://example.com" ,
78- method = "POST" ,
79- meta = meta ,
80- )
81- coro = handler ._download_request (req , Spider ("test" ))
82- assert iscoroutine (coro )
83- assert not isinstance (coro , Deferred )
84- resp = await coro # type: ignore
85-
86- assert isinstance (resp , Response )
87- assert resp .request is req
88- assert resp .url == req .url
89- assert resp .status == 200
90- assert "zyte-api" in resp .flags
91- assert resp .body == b"<html></html>"
80+ req , resp = await self .produce_request_response (meta )
81+ assert isinstance (resp , Response )
82+ assert resp .request is req
83+ assert resp .url == req .url
84+ assert resp .status == 200
85+ assert "zyte-api" in resp .flags
86+ assert resp .body == b"<html></html>"
9287
9388 @pytest .mark .parametrize (
9489 "meta" ,
@@ -99,24 +94,64 @@ async def test_http_response_body_request(self, meta: Dict[str, Dict[str, Any]])
9994 )
10095 @pytest .mark .asyncio
10196 async def test_http_response_headers_request (self , meta : Dict [str , Dict [str , Any ]]):
102- with MockServer () as server :
103- async with make_handler ({}, server .urljoin ("/" )) as handler :
104- req = Request (
105- "http://example.com" ,
106- method = "POST" ,
107- meta = meta ,
108- )
109- coro = handler ._download_request (req , Spider ("test" ))
110- assert iscoroutine (coro )
111- assert not isinstance (coro , Deferred )
112- resp = await coro # type: ignore
97+ req , resp = await self .produce_request_response (meta )
98+ assert resp .request is req
99+ assert resp .url == req .url
100+ assert resp .status == 200
101+ assert "zyte-api" in resp .flags
102+ assert resp .body == b"<html></html>"
103+ assert resp .headers == {b"Test_Header" : [b"test_value" ]}
113104
114- assert resp .request is req
115- assert resp .url == req .url
116- assert resp .status == 200
117- assert "zyte-api" in resp .flags
118- assert resp .body == b"<html></html>"
119- assert resp .headers == {b"Test_Header" : [b"test_value" ]}
105+ @pytest .mark .skipif (
106+ sys .version_info < (3 , 8 ), reason = "Python3.7 has poor support for AsyncMocks"
107+ )
108+ @pytest .mark .parametrize (
109+ "meta,custom_settings,expected" ,
110+ [
111+ ({}, {}, {}),
112+ ({"zyte_api" : {}}, {}, {}),
113+ (
114+ {},
115+ {"ZYTE_API_DEFAULT_PARAMS" : {"browserHtml" : True , "geolocation" : "CA" }},
116+ {"browserHtml" : True , "geolocation" : "CA" },
117+ ),
118+ (
119+ {"zyte_api" : {}},
120+ {"ZYTE_API_DEFAULT_PARAMS" : {"browserHtml" : True , "geolocation" : "CA" }},
121+ {"browserHtml" : True , "geolocation" : "CA" },
122+ ),
123+ (
124+ {"zyte_api" : {"javascript" : True , "geolocation" : "US" }},
125+ {"ZYTE_API_DEFAULT_PARAMS" : {"browserHtml" : True , "geolocation" : "CA" }},
126+ {"browserHtml" : True , "geolocation" : "US" , "javascript" : True },
127+ ),
128+ ],
129+ )
130+ @mock .patch ("tests.AsyncClient" )
131+ @pytest .mark .asyncio
132+ async def test_empty_zyte_api_request_meta (
133+ self ,
134+ mock_client ,
135+ meta : Dict [str , Dict [str , Any ]],
136+ custom_settings : Dict [str , str ],
137+ expected : Dict [str , str ],
138+ ):
139+ try :
140+ # This would always error out since the mocked client doesn't
141+ # return the expected API response.
142+ await self .produce_request_response (meta , custom_settings = custom_settings )
143+ except Exception :
144+ pass
145+
146+ # What we're interested in is the Request call in the API
147+ request_call = [c for c in mock_client .mock_calls if "request_raw(" in str (c )]
148+ if not request_call :
149+ pytest .fail ("The client's request_raw() method was not called." )
150+
151+ args_used = request_call [0 ].args [0 ]
152+ args_used .pop ("url" )
153+
154+ assert args_used == expected
120155
121156 @pytest .mark .parametrize (
122157 "meta, api_relevant" ,
0 commit comments