@@ -378,6 +378,20 @@ def test_screenshot_tool_decodes_utf8_bytes_field():
378378 assert output == "image-data"
379379
380380
381+ def test_screenshot_tool_wraps_invalid_utf8_bytes_field ():
382+ client = _SyncScrapeClient (
383+ _Response (data = SimpleNamespace (screenshot = b"\xff \xfe \xfd " ))
384+ )
385+
386+ with pytest .raises (
387+ HyperbrowserError ,
388+ match = "screenshot tool response field 'screenshot' must be a UTF-8 string" ,
389+ ) as exc_info :
390+ WebsiteScreenshotTool .runnable (client , {"url" : "https://example.com" })
391+
392+ assert exc_info .value .original_error is not None
393+
394+
381395def test_crawl_tool_rejects_non_list_response_data ():
382396 client = _SyncCrawlClient (_Response (data = {"invalid" : "payload" }))
383397
@@ -538,6 +552,18 @@ def test_browser_use_tool_decodes_utf8_bytes_final_result():
538552 assert output == "done"
539553
540554
555+ def test_browser_use_tool_wraps_invalid_utf8_bytes_final_result ():
556+ client = _SyncBrowserUseClient (_Response (data = SimpleNamespace (final_result = b"\xff " )))
557+
558+ with pytest .raises (
559+ HyperbrowserError ,
560+ match = "browser-use tool response field 'final_result' must be a UTF-8 string" ,
561+ ) as exc_info :
562+ BrowserUseTool .runnable (client , {"task" : "search docs" })
563+
564+ assert exc_info .value .original_error is not None
565+
566+
541567def test_browser_use_tool_supports_mapping_response_data ():
542568 client = _SyncBrowserUseClient (_Response (data = {"final_result" : "mapping output" }))
543569
@@ -617,6 +643,36 @@ async def run() -> None:
617643 asyncio .run (run ())
618644
619645
646+ def test_async_screenshot_tool_decodes_utf8_bytes_field ():
647+ async def run () -> None :
648+ client = _AsyncScrapeClient (_Response (data = SimpleNamespace (screenshot = b"async-shot" )))
649+ output = await WebsiteScreenshotTool .async_runnable (
650+ client ,
651+ {"url" : "https://example.com" },
652+ )
653+ assert output == "async-shot"
654+
655+ asyncio .run (run ())
656+
657+
658+ def test_async_browser_use_tool_wraps_invalid_utf8_bytes_final_result ():
659+ async def run () -> None :
660+ client = _AsyncBrowserUseClient (
661+ _Response (data = SimpleNamespace (final_result = b"\xff " ))
662+ )
663+ with pytest .raises (
664+ HyperbrowserError ,
665+ match = (
666+ "browser-use tool response field "
667+ "'final_result' must be a UTF-8 string"
668+ ),
669+ ) as exc_info :
670+ await BrowserUseTool .async_runnable (client , {"task" : "search docs" })
671+ assert exc_info .value .original_error is not None
672+
673+ asyncio .run (run ())
674+
675+
620676def test_async_scrape_tool_supports_mapping_response_data ():
621677 async def run () -> None :
622678 client = _AsyncScrapeClient (_Response (data = {"markdown" : "async mapping" }))
0 commit comments