@@ -204,6 +204,26 @@ def test_extract_tool_runnable_normalizes_mapping_schema_values():
204204 assert client .extract .last_params .schema_ == {"type" : "object" , "properties" : {}}
205205
206206
207+ def test_extract_tool_async_runnable_normalizes_mapping_schema_values ():
208+ client = _AsyncClient ()
209+ schema_mapping = MappingProxyType ({"type" : "object" , "properties" : {}})
210+
211+ async def run ():
212+ return await WebsiteExtractTool .async_runnable (
213+ client ,
214+ {
215+ "urls" : ["https://example.com" ],
216+ "schema" : schema_mapping ,
217+ },
218+ )
219+
220+ asyncio .run (run ())
221+
222+ assert isinstance (client .extract .last_params , StartExtractJobParams )
223+ assert isinstance (client .extract .last_params .schema_ , dict )
224+ assert client .extract .last_params .schema_ == {"type" : "object" , "properties" : {}}
225+
226+
207227def test_extract_tool_runnable_rejects_non_string_schema_keys ():
208228 client = _SyncClient ()
209229
@@ -219,6 +239,24 @@ def test_extract_tool_runnable_rejects_non_string_schema_keys():
219239 )
220240
221241
242+ def test_extract_tool_async_runnable_rejects_non_string_schema_keys ():
243+ client = _AsyncClient ()
244+
245+ async def run ():
246+ await WebsiteExtractTool .async_runnable (
247+ client ,
248+ {
249+ "urls" : ["https://example.com" ],
250+ "schema" : {1 : "invalid-key" }, # type: ignore[dict-item]
251+ },
252+ )
253+
254+ with pytest .raises (
255+ HyperbrowserError , match = "Extract tool `schema` object keys must be strings"
256+ ):
257+ asyncio .run (run ())
258+
259+
222260def test_extract_tool_runnable_wraps_schema_key_read_failures ():
223261 class _BrokenSchemaMapping (Mapping [object , object ]):
224262 def __iter__ (self ):
@@ -246,6 +284,36 @@ def __getitem__(self, key: object) -> object:
246284 assert exc_info .value .original_error is not None
247285
248286
287+ def test_extract_tool_async_runnable_wraps_schema_key_read_failures ():
288+ class _BrokenSchemaMapping (Mapping [object , object ]):
289+ def __iter__ (self ):
290+ raise RuntimeError ("cannot iterate schema keys" )
291+
292+ def __len__ (self ) -> int :
293+ return 1
294+
295+ def __getitem__ (self , key : object ) -> object :
296+ return key
297+
298+ client = _AsyncClient ()
299+
300+ async def run ():
301+ await WebsiteExtractTool .async_runnable (
302+ client ,
303+ {
304+ "urls" : ["https://example.com" ],
305+ "schema" : _BrokenSchemaMapping (),
306+ },
307+ )
308+
309+ with pytest .raises (
310+ HyperbrowserError , match = "Failed to read extract tool `schema` object keys"
311+ ) as exc_info :
312+ asyncio .run (run ())
313+
314+ assert exc_info .value .original_error is not None
315+
316+
249317def test_extract_tool_runnable_wraps_schema_value_read_failures ():
250318 class _BrokenSchemaMapping (Mapping [str , object ]):
251319 def __iter__ (self ):
@@ -275,6 +343,38 @@ def __getitem__(self, key: str) -> object:
275343 assert exc_info .value .original_error is not None
276344
277345
346+ def test_extract_tool_async_runnable_wraps_schema_value_read_failures ():
347+ class _BrokenSchemaMapping (Mapping [str , object ]):
348+ def __iter__ (self ):
349+ yield "type"
350+
351+ def __len__ (self ) -> int :
352+ return 1
353+
354+ def __getitem__ (self , key : str ) -> object :
355+ _ = key
356+ raise RuntimeError ("cannot read schema value" )
357+
358+ client = _AsyncClient ()
359+
360+ async def run ():
361+ await WebsiteExtractTool .async_runnable (
362+ client ,
363+ {
364+ "urls" : ["https://example.com" ],
365+ "schema" : _BrokenSchemaMapping (),
366+ },
367+ )
368+
369+ with pytest .raises (
370+ HyperbrowserError ,
371+ match = "Failed to read extract tool `schema` value for key 'type'" ,
372+ ) as exc_info :
373+ asyncio .run (run ())
374+
375+ assert exc_info .value .original_error is not None
376+
377+
278378def test_extract_tool_runnable_preserves_hyperbrowser_schema_value_read_failures ():
279379 class _BrokenSchemaMapping (Mapping [str , object ]):
280380 def __iter__ (self ):
@@ -303,6 +403,37 @@ def __getitem__(self, key: str) -> object:
303403 assert exc_info .value .original_error is None
304404
305405
406+ def test_extract_tool_async_runnable_preserves_hyperbrowser_schema_value_read_failures ():
407+ class _BrokenSchemaMapping (Mapping [str , object ]):
408+ def __iter__ (self ):
409+ yield "type"
410+
411+ def __len__ (self ) -> int :
412+ return 1
413+
414+ def __getitem__ (self , key : str ) -> object :
415+ _ = key
416+ raise HyperbrowserError ("custom schema value failure" )
417+
418+ client = _AsyncClient ()
419+
420+ async def run ():
421+ await WebsiteExtractTool .async_runnable (
422+ client ,
423+ {
424+ "urls" : ["https://example.com" ],
425+ "schema" : _BrokenSchemaMapping (),
426+ },
427+ )
428+
429+ with pytest .raises (
430+ HyperbrowserError , match = "custom schema value failure"
431+ ) as exc_info :
432+ asyncio .run (run ())
433+
434+ assert exc_info .value .original_error is None
435+
436+
306437def test_extract_tool_runnable_serializes_empty_object_data ():
307438 client = _SyncClient (response_data = {})
308439
0 commit comments