Skip to content

Commit 7951831

Browse files
Add async parity coverage for extract schema mapping guards
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 7912839 commit 7951831

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

tests/test_tools_extract.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
207227
def 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+
222260
def 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+
249317
def 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+
278378
def 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+
306437
def test_extract_tool_runnable_serializes_empty_object_data():
307438
client = _SyncClient(response_data={})
308439

0 commit comments

Comments
 (0)