diff --git a/spec/tests/test-hyperscript-behavioral.sx b/spec/tests/test-hyperscript-behavioral.sx index cb309769..23324d3b 100644 --- a/spec/tests/test-hyperscript-behavioral.sx +++ b/spec/tests/test-hyperscript-behavioral.sx @@ -9627,6 +9627,7 @@ (hs-activate! _el-d1) (dom-dispatch (dom-query-by-id "d1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "40") + (dom-dispatch (dom-query-by-id "b1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "42") )) (deftest "properly processes hyperscript at start of" @@ -9638,6 +9639,7 @@ (hs-activate! _el-d1) (dom-dispatch (dom-query-by-id "d1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "40") + (dom-dispatch (dom-query-by-id "b1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "42") )) (deftest "properly processes hyperscript in before" @@ -9661,6 +9663,7 @@ (hs-activate! _el-d1) (dom-dispatch (dom-query-by-id "d1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "40") + (dom-dispatch (dom-query-by-id "b1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "42") )) (deftest "properly processes hyperscript in new content in a symbol write" @@ -9671,6 +9674,7 @@ (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "40") + (dom-dispatch (dom-query-by-id "b1") "click" nil) (assert= (dom-text-content (dom-query-by-id "b1")) "42") )) (deftest "put null into attribute removes it" diff --git a/tests/playwright/generate-sx-tests.py b/tests/playwright/generate-sx-tests.py index eabc99ca..fcf0fe47 100644 --- a/tests/playwright/generate-sx-tests.py +++ b/tests/playwright/generate-sx-tests.py @@ -889,14 +889,19 @@ def parse_dev_body(body, elements, var_names): continue # evaluate(() => { window.X = Y; ... }) — block window setup. + # Only `continue` if at least one window-setup was parsed, otherwise + # fall through to other patterns that may match this `evaluate(...)`. m = re.match(r'evaluate\(\s*\(\)\s*=>\s*\{(.+)\}\s*\)\s*$', stmt_na, re.DOTALL) if m: - for name, sx_val in _window_setup_ops(m.group(1)): - if seen_html: - ops.append(f'(host-set! (host-global "window") "{name}" {sx_val})') - else: - pre_setups.append((name, sx_val)) - continue + setups_here = list(_window_setup_ops(m.group(1))) + if setups_here: + for name, sx_val in setups_here: + if seen_html: + ops.append(f'(host-set! (host-global "window") "{name}" {sx_val})') + else: + pre_setups.append((name, sx_val)) + continue + # fall through # evaluate(() => document.querySelector(SEL).innerHTML = VAL) — DOM reset. m = re.match( @@ -954,6 +959,22 @@ def parse_dev_body(body, elements, var_names): ops.append(f'(dom-dispatch {target} "{m.group(4)}" nil)') continue + # evaluate(() => { const e = new Event(NAME, {...}); document.querySelector(SEL).dispatchEvent(e); }) + # Common upstream pattern for dispatching a non-bubbling click. + m = re.match( + r"evaluate\(\s*\(\)\s*=>\s*\{\s*" + r"const\s+(\w+)\s*=\s*new\s+(?:Custom)?Event\(\s*(['\"])([^'\"]+)\2" + r"(?:\s*,\s*\{[^}]*\})?\s*\)\s*;\s*" + r"document\.querySelector\(\s*(['\"])([^'\"]+)\4\s*\)" + r"\.dispatchEvent\(\s*\1\s*\)\s*;?\s*\}\s*\)\s*$", + stmt_na, re.DOTALL, + ) + if m and seen_html: + sel = re.sub(r'^#work-area\s+', '', m.group(5)) + target = selector_to_sx(sel, elements, var_names) + ops.append(f'(dom-dispatch {target} "{m.group(3)}" nil)') + continue + # evaluate(() => document.getElementById(ID).METHOD()) — generic # method dispatch (showModal, close, click, focus, blur, reset…). m = re.match(