HS take command: class/attr with+giving, attr removal from scope, giving keyword
- tokenizer: add 'giving' as keyword so parse-take-cmd can detect it.
- parser.sx parse-take-cmd: loop over 'with <class>' / 'giving <class>' /
'from <sel>' / 'for <tgt>' clauses in any order for both the class and
attribute cases. Emits uniform (take! kind name from-sel for-tgt
attr-val with-val) 7-slot AST.
- compiler emit-take: pass with-cls for the class case through to runtime.
- runtime hs-take!: with a class 'with' replacement, toggle both classes
across scope + target. For attribute take, always strip the attr from
the scope 'others' (setting to with-val if given, otherwise removing).
- generator pw-body: translate evaluate(() => document.querySelector(s).
click()) and .dispatchEvent(new Event('name', …)) into dom-dispatch ops
so bubbling-click assertions in 'parent takes…' tests work.
- generator toHaveClass: strip JS regex word-boundaries (\\b) from the
expected class name.
- shared/static/wasm/sx/dom.sx: dom-child-list / dom-child-nodes mirror
the dom-query-all SX-list passthrough — childNodes arrives pre-SXified.
Net: take 6→15 (100%), remove 16→17, fetch 11→15.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -680,10 +680,14 @@ def pw_assertion_to_sx(target, negated, assert_type, args_str):
|
||||
elif assert_type == 'toHaveClass':
|
||||
cls = args[0] if args else ''
|
||||
if not cls:
|
||||
# Handle regex like /outer-clicked/
|
||||
# Handle regex like /outer-clicked/ or /\bselected\b/
|
||||
m = re.match(r'/(.+?)/', args_str)
|
||||
if m:
|
||||
cls = m.group(1)
|
||||
# Strip JS regex anchors/word-boundaries — the class name itself is
|
||||
# a bare ident, not a regex pattern.
|
||||
cls = re.sub(r'\\b', '', cls)
|
||||
cls = cls.strip('^$')
|
||||
if negated:
|
||||
return f'(assert (not (dom-has-class? {target} "{cls}")))'
|
||||
return f'(assert (dom-has-class? {target} "{cls}"))'
|
||||
@@ -897,6 +901,32 @@ def parse_dev_body(body, elements, var_names):
|
||||
ops.append(f'(dom-set-inner-html {target} "{val}")')
|
||||
continue
|
||||
|
||||
# evaluate(() => document.querySelector(SEL).click()) — dispatch click
|
||||
# on the matched element (bubbles so ancestors see it too).
|
||||
m = re.match(
|
||||
r"evaluate\(\s*\(\)\s*=>\s*document\.querySelector\(\s*(['\"])([^'\"]+)\1\s*\)"
|
||||
r"\.click\(\)\s*\)\s*$",
|
||||
stmt_na, re.DOTALL,
|
||||
)
|
||||
if m and seen_html:
|
||||
sel = re.sub(r'^#work-area\s+', '', m.group(2))
|
||||
target = selector_to_sx(sel, elements, var_names)
|
||||
ops.append(f'(dom-dispatch {target} "click" nil)')
|
||||
continue
|
||||
|
||||
# evaluate(() => document.querySelector(SEL).dispatchEvent(new Event/CustomEvent(NAME…)))
|
||||
m = re.match(
|
||||
r"evaluate\(\s*\(\)\s*=>\s*document\.querySelector\(\s*(['\"])([^'\"]+)\1\s*\)"
|
||||
r"\.dispatchEvent\(\s*new\s+(?:Custom)?Event\(\s*(['\"])([^'\"]+)\3"
|
||||
r"(?:\s*,\s*[^)]*)?\s*\)\s*\)\s*\)\s*$",
|
||||
stmt_na, re.DOTALL,
|
||||
)
|
||||
if m and seen_html:
|
||||
sel = re.sub(r'^#work-area\s+', '', m.group(2))
|
||||
target = selector_to_sx(sel, elements, var_names)
|
||||
ops.append(f'(dom-dispatch {target} "{m.group(4)}" nil)')
|
||||
continue
|
||||
|
||||
if not seen_html:
|
||||
continue
|
||||
if add_action(stmt_na):
|
||||
|
||||
Reference in New Issue
Block a user