|
7 | 7 | from tests.sample_data import sample_file
|
8 | 8 | from zendriver.cdp.fetch import RequestStage
|
9 | 9 | from zendriver.cdp.network import ResourceType
|
| 10 | +from zendriver.core.connection import ProtocolException |
10 | 11 |
|
11 | 12 |
|
12 | 13 | async def test_set_user_agent_sets_navigator_values(browser: zd.Browser) -> None:
|
@@ -295,53 +296,74 @@ async def test_evaluate_complex_object_no_error(browser: zd.Browser) -> None:
|
295 | 296 | tab = await browser.get(sample_file("complex_object.html"))
|
296 | 297 | await tab.wait_for_ready_state("complete")
|
297 | 298 |
|
298 |
| - result = await tab.evaluate("document.querySelector('body:not(.no-js)')") |
| 299 | + result = await tab.evaluate( |
| 300 | + "document.querySelector('body:not(.no-js)')", return_by_value=False |
| 301 | + ) |
299 | 302 | assert result is not None
|
300 | 303 |
|
301 | 304 | # This is similar to the original failing case but more likely to trigger the error
|
302 |
| - body_with_complex_refs = await tab.evaluate("document.body") |
| 305 | + body_with_complex_refs = await tab.evaluate("document.body", return_by_value=False) |
303 | 306 | assert body_with_complex_refs is not None
|
304 | 307 |
|
305 | 308 |
|
306 |
| -async def test_evaluate_return_by_value_modes(browser: zd.Browser) -> None: |
| 309 | +async def test_evaluate_return_by_value_complex_object(browser: zd.Browser) -> None: |
307 | 310 | tab = await browser.get(sample_file("complex_object.html"))
|
308 | 311 | await tab.wait_for_ready_state("complete")
|
309 | 312 |
|
310 | 313 | expression = "document.querySelector('body:not(.no-js)')"
|
311 | 314 |
|
312 |
| - result_by_value = await tab.evaluate(expression, return_by_value=True) |
313 |
| - assert result_by_value is not None |
| 315 | + # Fetching a complex object with return_by_value=True is unsupported because there is no |
| 316 | + # way to represent the object as a simple data structure. |
| 317 | + with pytest.raises(ProtocolException): |
| 318 | + _ = await tab.evaluate(expression, return_by_value=True) |
314 | 319 |
|
315 |
| - result_false = await tab.evaluate(expression, return_by_value=False) |
| 320 | + result_by_value_false = await tab.evaluate(expression, return_by_value=False) |
316 | 321 | assert (
|
317 |
| - result_false is not None |
| 322 | + result_by_value_false is not None |
318 | 323 | ) # Should return the deep serialized value, not a tuple
|
319 | 324 |
|
320 | 325 |
|
| 326 | +async def test_evaluate_return_by_value_simple_json(browser: zd.Browser) -> None: |
| 327 | + tab = await browser.get(sample_file("simple_json.html")) |
| 328 | + await tab.wait_for_ready_state("complete") |
| 329 | + |
| 330 | + expression = "JSON.parse(document.querySelector('#obj').textContent)" |
| 331 | + |
| 332 | + result_by_value_true = await tab.evaluate(expression, return_by_value=True) |
| 333 | + assert result_by_value_true == {"a": "x", "b": 3.14159} |
| 334 | + |
| 335 | + result_by_value_false = await tab.evaluate(expression, return_by_value=False) |
| 336 | + assert result_by_value_false == [ |
| 337 | + ["a", {"type": "string", "value": "x"}], |
| 338 | + ["b", {"type": "number", "value": 3.14159}], |
| 339 | + ] |
| 340 | + |
| 341 | + |
321 | 342 | async def test_evaluate_stress_test_complex_objects(browser: zd.Browser) -> None:
|
322 | 343 | tab = await browser.get(sample_file("complex_object.html"))
|
323 | 344 | await tab.wait_for_ready_state("complete")
|
324 | 345 |
|
325 | 346 | # Test various DOM queries that could trigger reference chain issues
|
326 |
| - # Each test case is a tuple of (expression, expected_type_or_validator) |
| 347 | + # Each test case is a tuple of (expression, return_by_value, expected_type_or_validator) |
327 | 348 | test_cases = [
|
328 |
| - ("document.querySelector('body:not(.no-js)')", lambda x: x is not None), |
329 |
| - ("document.documentElement", lambda x: x is not None), |
330 |
| - ("document.querySelector('*')", lambda x: x is not None), |
331 |
| - ("document.body.parentElement", lambda x: x is not None), |
332 |
| - ("document.getElementById('content')", lambda x: x is not None), |
| 349 | + ("document.querySelector('body:not(.no-js)')", False, lambda x: x is not None), |
| 350 | + ("document.documentElement", False, lambda x: x is not None), |
| 351 | + ("document.querySelector('*')", False, lambda x: x is not None), |
| 352 | + ("document.body.parentElement", False, lambda x: x is not None), |
| 353 | + ("document.getElementById('content')", False, lambda x: x is not None), |
333 | 354 | (
|
334 | 355 | "document.body.complexStructure ? 'has complex structure' : 'no structure'",
|
| 356 | + True, |
335 | 357 | str,
|
336 | 358 | ),
|
337 |
| - ("document.readyState", str), |
338 |
| - ("navigator.userAgent", str), |
339 |
| - ("window.location.href", str), |
340 |
| - ("document.title", str), |
| 359 | + ("document.readyState", True, str), |
| 360 | + ("navigator.userAgent", True, str), |
| 361 | + ("window.location.href", True, str), |
| 362 | + ("document.title", True, str), |
341 | 363 | ]
|
342 | 364 |
|
343 |
| - for expression, validator in test_cases: |
344 |
| - result = await tab.evaluate(expression) |
| 365 | + for expression, return_by_value, validator in test_cases: |
| 366 | + result = await tab.evaluate(expression, return_by_value=return_by_value) |
345 | 367 | # Verify the result is usable and matches expected type/validation
|
346 | 368 | if callable(validator):
|
347 | 369 | assert validator(
|
|
0 commit comments