Skip to content

Commit b3db7cd

Browse files
committed
fix: propagate JavaScript evaluation errors
1 parent 5ca7099 commit b3db7cd

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

helpers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ def wait_for_selector(selector, timeout=10.0, visible=False, interval=0.2):
226226
"""
227227
return bool(wait_for_js(expression, timeout=timeout, interval=interval))
228228

229+
def _js_exception_text(r):
230+
d = r.get("exceptionDetails") or {}
231+
e = d.get("exception") or {}
232+
return "\n".join(str(x) for x in (d.get("text"), e.get("description"), e.get("value")) if x)
233+
229234
def js(expression, target_id=None):
230235
"""Run JS in the attached tab (default) or inside an iframe target (via iframe_target()).
231236
@@ -236,6 +241,8 @@ def js(expression, target_id=None):
236241
if "return " in expression:
237242
expression = f"(function(){{{expression}}})()"
238243
r = cdp("Runtime.evaluate", session_id=sid, expression=expression, returnByValue=True, awaitPromise=True)
244+
if "exceptionDetails" in r:
245+
raise RuntimeError(f"JavaScript evaluation failed: {_js_exception_text(r) or 'unknown error'}")
239246
return r.get("result", {}).get("value")
240247

241248
def page_outline(limit=80):

test_js.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pytest
12
from unittest.mock import patch
23
import helpers
34

@@ -28,6 +29,20 @@ def test_return_statement_gets_wrapped():
2829
assert _evaluated_expression(captured) == "(function(){const x = 1; return x})()"
2930

3031

32+
def test_js_raises_on_runtime_exception():
33+
def fake_cdp(method, **kwargs):
34+
return {
35+
"exceptionDetails": {
36+
"text": "Uncaught ReferenceError",
37+
"exception": {"description": "ReferenceError: missing is not defined"},
38+
}
39+
}
40+
41+
with patch("helpers.cdp", side_effect=fake_cdp):
42+
with pytest.raises(RuntimeError, match="missing is not defined"):
43+
helpers.js("missing.value")
44+
45+
3146
def test_wait_for_js_returns_first_truthy_value():
3247
with patch("helpers.js", side_effect=[False, None, {"ready": True}]), \
3348
patch("helpers.time.sleep") as sleep:
@@ -36,6 +51,15 @@ def test_wait_for_js_returns_first_truthy_value():
3651
assert sleep.call_count == 2
3752

3853

54+
def test_wait_for_js_propagates_js_errors():
55+
with patch("helpers.js", side_effect=RuntimeError("JavaScript evaluation failed")), \
56+
patch("helpers.time.sleep") as sleep:
57+
with pytest.raises(RuntimeError, match="JavaScript evaluation failed"):
58+
helpers.wait_for_js("missing.value", timeout=1, interval=0.01)
59+
60+
sleep.assert_not_called()
61+
62+
3963
def test_wait_for_selector_uses_visible_predicate():
4064
with patch("helpers.wait_for_js", return_value=True) as wait:
4165
assert helpers.wait_for_selector("button[aria-label='Save']", timeout=3, visible=True)

0 commit comments

Comments
 (0)