HS: fix empty/halt/morph/reset/dialog — 17 upstream tests pass

- parser `empty` no-target → (ref "me") (was bogus (sym "me"))
- parser `halt` modes distinguish: "all"/"bubbling"/"default" halt execution
  (raise hs-return), "the-event"/"the event's" only stop propagation/default.
  "'s" now matched as op token, not keyword.
- parser `get` cmd: dispatch + cmd-kw list + parse-get-cmd (parses expr with
  optional `as TYPE`). Required for `get result as JSON` in fetch chains.
- compiler empty-target for (local X): emit (set! X (hs-empty-like X)) so
  arrays/sets/maps clear the variable, not call DOM empty on the value.
- runtime hs-empty-like: container-of-same-type empty value.
- runtime hs-empty-target!: drop dead FORM branch that was short-circuiting
  to innerHTML=""; the querySelectorAll-over-inputs branch now runs.
- runtime hs-halt!: take ev param (was free `event` lookup); raise hs-return
  to stop execution unless mode is "the-event".
- runtime hs-reset!: type-aware — FORM → reset, INPUT/TEXTAREA → value/checked
  from defaults, SELECT → defaultSelected option.
- runtime hs-open!/hs-close!: toggle `open` attribute on details elements
  (not just the prop) so dom-has-attr? assertions work.
- runtime hs-coerce JSON: json-stringify dict/list (was str).
- test-runner mock: host-get on List + "length"/"size" (was only Dict);
  dom-set-attr tracks defaultChecked / defaultSelected / defaultValue;
  mock_query_all supports comma-separated selector groups.
- generator: emit boolean attrs (checked/selected/etc) even with null value;
  drop overcautious "skip HS with bare quotes or embedded HTML" guard so
  morph tests (source contains embedded <div>) emit properly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 15:36:01 +00:00
parent 5c66095b0f
commit 802ccd23e8
12 changed files with 1340 additions and 345 deletions

View File

@@ -23,7 +23,14 @@
(let ((sx (hs-to-sx (hs-compile src))))
(let ((handler (eval-expr-cek
(list (quote fn) (list (quote me)) (list (quote let) (list (list (quote it) nil) (list (quote event) nil)) sx)))))
(handler nil)))))
(guard
(_e
(true
(if
(and (list? _e) (= (first _e) "hs-return"))
(nth _e 1)
(raise _e))))
(handler nil))))))
;; Evaluate with a specific me value (for "I am between" etc.)
(define eval-hs-with-me
@@ -31,7 +38,14 @@
(let ((sx (hs-to-sx (hs-compile src))))
(let ((handler (eval-expr-cek
(list (quote fn) (list (quote me)) (list (quote let) (list (list (quote it) nil) (list (quote event) nil)) sx)))))
(handler me-val)))))
(guard
(_e
(true
(if
(and (list? _e) (= (first _e) "hs-return"))
(nth _e 1)
(raise _e))))
(handler me-val))))))
;; ── add (19 tests) ──
(defsuite "hs-upstream-add"
@@ -235,6 +249,7 @@
(dom-set-attr _el-d1 "id" "d1")
(dom-add-class _el-d1 "item")
(dom-set-attr _el-none "id" "none")
(dom-set-attr _el-none "hidden" "")
(dom-append (dom-body) _el-trigger)
(dom-append (dom-body) _el-d1)
(dom-append (dom-body) _el-none)
@@ -365,7 +380,7 @@
(dom-append _el-d1 _el-p)
(dom-append _el-div _el-p3)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-div "click" nil)
;; SKIP check: skip div.innerHTML.includes("foo").should.equal(true)
;; SKIP check: skip div.innerHTML.includes("bar").should.equal(true)
;; SKIP check: skip div.innerHTML.includes("doh").should.equal(true)
@@ -797,8 +812,8 @@
(dom-append (dom-body) _el-div)
(dom-append _el-div _el-d1)
(hs-activate! _el-div)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "foo")
(dom-dispatch _el-div "click" nil)
(assert= (dom-inner-html _el-div) "foo")
))
(deftest "can set complex indirect properties rhs"
(hs-cleanup!)
@@ -808,8 +823,8 @@
(dom-append (dom-body) _el-div)
(dom-append _el-div _el-d1)
(hs-activate! _el-div)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "foo")
(dom-dispatch _el-div "click" nil)
(assert= (dom-inner-html _el-div) "foo")
))
(deftest "can set chained indirect properties"
(hs-cleanup!)
@@ -819,8 +834,8 @@
(dom-append (dom-body) _el-div)
(dom-append _el-div _el-d1)
(hs-activate! _el-div)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "foo")
(dom-dispatch _el-div "click" nil)
(assert= (dom-inner-html _el-div) "foo")
))
(deftest "can set styles"
(hs-cleanup!)
@@ -1358,8 +1373,8 @@
(dom-append (dom-body) _el-div)
(hs-activate! _el-div)
(dom-dispatch _el-div "click" nil)
(dom-dispatch _el-div "click" nil)
(assert= (dom-inner-html _el-div) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "properly processes hyperscript in new content in a element target"
(hs-cleanup!)
@@ -1369,8 +1384,8 @@
(dom-append (dom-body) _el-d1)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "properly processes hyperscript in before"
(hs-cleanup!)
@@ -1380,8 +1395,8 @@
(dom-append (dom-body) _el-d1)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "properly processes hyperscript at start of"
(hs-cleanup!)
@@ -1391,8 +1406,8 @@
(dom-append (dom-body) _el-d1)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "properly processes hyperscript at end of"
(hs-cleanup!)
@@ -1402,8 +1417,8 @@
(dom-append (dom-body) _el-d1)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "properly processes hyperscript after"
(hs-cleanup!)
@@ -1413,8 +1428,8 @@
(dom-append (dom-body) _el-d1)
(hs-activate! _el-d1)
(dom-dispatch _el-d1 "click" nil)
(dom-dispatch _el-d1 "click" nil)
(assert= (dom-inner-html _el-d1) "42")
(dom-dispatch (dom-query "button") "click" nil)
(assert= (dom-inner-html (dom-query "button")) "42")
))
(deftest "is null tolerant"
(hs-cleanup!)
@@ -2324,7 +2339,7 @@
(dom-append _el-div _el-d3)
(hs-activate! _el-div)
(dom-dispatch _el-d2 "click" nil)
(assert (not (dom-has-class? _el-d1 "foo")))
(assert (not (dom-has-class? _el-div "foo")))
(assert (dom-has-class? _el-d2 "foo"))
(assert (not (dom-has-class? _el-d3 "foo")))
))
@@ -2441,7 +2456,7 @@
(dom-append _el-div _el-d3)
(hs-activate! _el-div)
(dom-dispatch _el-d2 "click" nil)
(assert= (dom-get-attr _el-d1 "data-foo") "bar")
(assert= (dom-get-attr _el-div "data-foo") "bar")
(assert= (dom-get-attr _el-d2 "data-foo") "")
;; SKIP check: skip assert.isNull(d2.getAttribute("data-foo")
;; SKIP check: skip assert.isNull(d3.getAttribute("data-foo")
@@ -3300,7 +3315,7 @@
(dom-append (dom-body) _el-div)
(hs-activate! _el-div)
(dom-dispatch _el-div "click" nil)
(assert (dom-has-class? _el-div "topping"))
(assert (dom-has-class? (dom-query "span") "topping"))
))
(deftest "can append a value to a set"
(hs-cleanup!)
@@ -4227,6 +4242,7 @@
(hs-cleanup!)
(let ((_el-d (dom-create-element "details")) (_el-summary (dom-create-element "summary")) (_el-p (dom-create-element "p")) (_el-button (dom-create-element "button")))
(dom-set-attr _el-d "id" "d")
(dom-set-attr _el-d "open" "")
(dom-set-inner-html _el-summary "More")
(dom-set-inner-html _el-p "Content")
(dom-set-attr _el-button "_" "on click close #d")
@@ -4386,6 +4402,7 @@
(let ((_el-cb1 (dom-create-element "input")) (_el-button (dom-create-element "button")))
(dom-set-attr _el-cb1 "id" "cb1")
(dom-set-attr _el-cb1 "type" "checkbox")
(dom-set-attr _el-cb1 "checked" "")
(dom-set-attr _el-button "_" "on click empty #cb1")
(dom-set-inner-html _el-button "Empty")
(dom-append (dom-body) _el-cb1)
@@ -4401,6 +4418,7 @@
(dom-set-attr _el-option "value" "a")
(dom-set-inner-html _el-option "A")
(dom-set-attr _el-option2 "value" "b")
(dom-set-attr _el-option2 "selected" "")
(dom-set-inner-html _el-option2 "B")
(dom-set-attr _el-button "_" "on click empty #sel1")
(dom-set-inner-html _el-button "Empty")
@@ -4422,6 +4440,7 @@
(dom-set-inner-html _el-ta2 "text")
(dom-set-attr _el-cb2 "id" "cb2")
(dom-set-attr _el-cb2 "type" "checkbox")
(dom-set-attr _el-cb2 "checked" "")
(dom-set-attr _el-button "_" "on click empty #f1")
(dom-set-inner-html _el-button "Empty")
(dom-append (dom-body) _el-f1)
@@ -4649,10 +4668,11 @@
(let ((_el-target (dom-create-element "div")) (_el-button (dom-create-element "button")))
(dom-set-attr _el-target "id" "target")
(dom-set-inner-html _el-target "old")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click morph #target to \"<div id=target>new</div>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-target)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
(assert= (dom-text-content (dom-query-by-id "target")) "new")
))
@@ -4662,10 +4682,11 @@
(dom-set-attr _el-target "id" "target")
(dom-set-inner-html _el-target "old")
(dom-set-attr _el-go "id" "go")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-go "_" "on click morph #target to \"<div id=target>new</div>\"")
(dom-set-inner-html _el-go "go")
(dom-append (dom-body) _el-target)
(dom-append (dom-body) _el-go)
(hs-activate! _el-go)
(dom-dispatch (dom-query-by-id "go") "click" nil)
(assert= (dom-text-content (dom-query-by-id "target")) "new")
))
@@ -4675,10 +4696,11 @@
(dom-set-attr _el-target "id" "target")
(dom-add-class _el-target "old")
(dom-set-inner-html _el-target "content")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click morph #target to \"<div id=target class=new>content</div>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-target)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
(assert (dom-has-class? (dom-query-by-id "target") "new"))
))
@@ -4736,12 +4758,13 @@
(dom-set-attr _el-child "id" "child")
(dom-set-attr _el-child "_" "on click put \"alive\" into me")
(dom-set-inner-html _el-child "child")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click morph #target to \"<div id=target><p>replaced</p></div>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-target)
(dom-append _el-target _el-child)
(dom-append (dom-body) _el-button)
(hs-activate! _el-child)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
))
(deftest "morph reorders children by id"
@@ -4752,12 +4775,13 @@
(dom-set-inner-html _el-a "A")
(dom-set-attr _el-b "id" "b")
(dom-set-inner-html _el-b "B")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click morph #target to \"<div id=target><div id=b>B2</div><div id=a>A2</div></div>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-target)
(dom-append _el-target _el-a)
(dom-append _el-target _el-b)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
))
(deftest "morph preserves matched child identity"
@@ -4767,11 +4791,12 @@
(dom-set-attr _el-child "id" "child")
(dom-set-inner-html _el-child "old")
(dom-set-attr _el-go "id" "go")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-go "_" "on click morph #target to \"<div id=target><div id=child>new</div></div>\"")
(dom-set-inner-html _el-go "go")
(dom-append (dom-body) _el-target)
(dom-append _el-target _el-child)
(dom-append (dom-body) _el-go)
(hs-activate! _el-go)
(dom-dispatch (dom-query-by-id "go") "click" nil)
))
(deftest "morph with variable content"
@@ -4856,6 +4881,7 @@
(let ((_el-cb1 (dom-create-element "input")) (_el-button (dom-create-element "button")))
(dom-set-attr _el-cb1 "id" "cb1")
(dom-set-attr _el-cb1 "type" "checkbox")
(dom-set-attr _el-cb1 "checked" "")
(dom-set-attr _el-button "_" "on click reset #cb1")
(dom-set-inner-html _el-button "Reset")
(dom-append (dom-body) _el-cb1)
@@ -4906,6 +4932,7 @@
(dom-set-attr _el-option "value" "a")
(dom-set-inner-html _el-option "A")
(dom-set-attr _el-option2 "value" "b")
(dom-set-attr _el-option2 "selected" "")
(dom-set-inner-html _el-option2 "B")
(dom-set-attr _el-option3 "value" "c")
(dom-set-inner-html _el-option3 "C")
@@ -5633,6 +5660,7 @@
(dom-set-attr _el-input "type" "radio")
(dom-set-attr _el-input "name" "color")
(dom-set-attr _el-input "value" "red")
(dom-set-attr _el-input "checked" "")
(dom-set-attr _el-input1 "_" "bind $color to me")
(dom-set-attr _el-input1 "type" "radio")
(dom-set-attr _el-input1 "name" "color")
@@ -6891,10 +6919,11 @@
(let ((_el-target (dom-create-element "div")) (_el-button (dom-create-element "button")))
(dom-set-attr _el-target "id" "target")
(dom-set-inner-html _el-target "old")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click set #target to \"<span id=target>new</span>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-target)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
(assert= (dom-text-content (dom-query-by-id "target")) "new")
))
@@ -6920,13 +6949,14 @@
(dom-set-inner-html _el-li2 "b")
(dom-add-class _el-li3 "item")
(dom-set-inner-html _el-li3 "c")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click set .item to \"<li class=item>replaced</li>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-list)
(dom-append _el-list _el-li)
(dom-append _el-list _el-li2)
(dom-append _el-list _el-li3)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
))
(deftest "set <query/> replaces all matching elements"
@@ -6935,22 +6965,24 @@
(dom-set-attr _el-box "id" "box")
(dom-set-inner-html _el-p "one")
(dom-set-inner-html _el-p2 "two")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click set <p/> in #box to \"<p>done</p>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-box)
(dom-append _el-box _el-p)
(dom-append _el-box _el-p2)
(dom-append (dom-body) _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
))
(deftest "set closest replaces ancestor"
(hs-cleanup!)
(let ((_el-div (dom-create-element "div")) (_el-button (dom-create-element "button")))
(dom-add-class _el-div "wrapper")
;; HS source has bare quotes or embedded HTML
(dom-set-attr _el-button "_" "on click set (closest <div/>) to \"<div class=wrapper>replaced</div>\"")
(dom-set-inner-html _el-button "go")
(dom-append (dom-body) _el-div)
(dom-append _el-div _el-button)
(hs-activate! _el-button)
(dom-dispatch _el-button "click" nil)
(assert= (dom-text-content (dom-query ".wrapper")) "replaced")
))
@@ -7195,10 +7227,12 @@
(let ((_el-table (dom-create-element "table")) (_el-tr (dom-create-element "tr")) (_el-td (dom-create-element "td")) (_el-input (dom-create-element "input")) (_el-tr4 (dom-create-element "tr")) (_el-td5 (dom-create-element "td")) (_el-input6 (dom-create-element "input")) (_el-tr7 (dom-create-element "tr")) (_el-td8 (dom-create-element "td")) (_el-input9 (dom-create-element "input")) (_el-tr10 (dom-create-element "tr")) (_el-td11 (dom-create-element "td")) (_el-master (dom-create-element "input")))
(dom-add-class _el-input "cb")
(dom-set-attr _el-input "type" "checkbox")
(dom-set-attr _el-input "checked" "")
(dom-add-class _el-input6 "cb")
(dom-set-attr _el-input6 "type" "checkbox")
(dom-add-class _el-input9 "cb")
(dom-set-attr _el-input9 "type" "checkbox")
(dom-set-attr _el-input9 "checked" "")
(dom-set-attr _el-master "id" "master")
(dom-set-attr _el-master "_" "set :checkboxes to <input[type=checkbox]/> in the closest <table/> where it is not me then on change set checked of the :checkboxes to my checked")
(dom-set-attr _el-master "type" "checkbox")
@@ -7223,10 +7257,12 @@
(let ((_el-table (dom-create-element "table")) (_el-tr (dom-create-element "tr")) (_el-td (dom-create-element "td")) (_el-input (dom-create-element "input")) (_el-tr4 (dom-create-element "tr")) (_el-td5 (dom-create-element "td")) (_el-input6 (dom-create-element "input")) (_el-tr7 (dom-create-element "tr")) (_el-td8 (dom-create-element "td")) (_el-input9 (dom-create-element "input")) (_el-tr10 (dom-create-element "tr")) (_el-td11 (dom-create-element "td")) (_el-master (dom-create-element "input")))
(dom-add-class _el-input "cb")
(dom-set-attr _el-input "type" "checkbox")
(dom-set-attr _el-input "checked" "")
(dom-add-class _el-input6 "cb")
(dom-set-attr _el-input6 "type" "checkbox")
(dom-add-class _el-input9 "cb")
(dom-set-attr _el-input9 "type" "checkbox")
(dom-set-attr _el-input9 "checked" "")
(dom-set-attr _el-master "id" "master")
(dom-set-attr _el-master "_" "set :checkboxes to <input[type=checkbox]/> in the closest <table/> where it is not me then on change set checked of the :checkboxes to my checked then on change from the closest <table/> then if no :checkboxes where it is checked then set my indeterminate to false then set my checked to false then else if no :checkboxes where it is not checked then set my indeterminate to false then set my checked to true then else then set my indeterminate to true then end")
(dom-set-attr _el-master "type" "checkbox")
@@ -8292,6 +8328,7 @@
(hs-cleanup!)
(let ((_el-b1 (dom-create-element "button")) (_el-b2 (dom-create-element "button")))
(dom-set-attr _el-b1 "id" "b1")
(dom-set-attr _el-b1 "disabled" "")
(dom-set-inner-html _el-b1 "Disabled")
(dom-set-attr _el-b2 "id" "b2")
(dom-set-inner-html _el-b2 "Enabled")

View File

@@ -16,9 +16,9 @@
"remove class from target"
(let
((sx (hs-to-sx-from-source "remove .old from #box")))
(assert= (quote dom-remove-class) (first sx))
(assert= (quote dom-query) (first (nth sx 1)))
(assert= "old" (nth sx 2))))
(assert= (quote for-each) (first sx))
(assert= (quote hs-query-all) (first (nth sx 2)))
(assert= "#box" (nth (nth sx 2) 1))))
(deftest
"toggle class"
(let
@@ -84,7 +84,7 @@
"for becomes for-each"
(let
((sx (hs-to-sx-from-source "for item in items log item end")))
(assert= (quote for-each) (first sx))
(assert= (quote hs-for-each) (first sx))
(assert= (quote fn) (first (nth sx 1)))))
(deftest
"tell rebinds me"
@@ -100,17 +100,16 @@
"hide sets display none"
(let
((sx (hs-to-sx-from-source "hide")))
(assert= (quote dom-set-style) (first sx))
(assert= (quote hs-hide!) (first sx))
(assert= (quote me) (nth sx 1))
(assert= "display" (nth sx 2))
(assert= "none" (nth sx 3))))
(assert= "display" (nth sx 2))))
(deftest
"show clears display"
(let
((sx (hs-to-sx-from-source "show")))
(assert= (quote dom-set-style) (first sx))
(assert= (quote hs-show!) (first sx))
(assert= (quote me) (nth sx 1))
(assert= "" (nth sx 3))))
(assert= "display" (nth sx 2))))
(deftest
"log passes through"
(let
@@ -121,7 +120,9 @@
"append becomes dom-append"
(let
((sx (hs-to-sx-from-source "append 'text' to me")))
(assert= (quote dom-append) (first sx)))))
(assert= (quote set!) (first sx))
(assert= (quote hs-append) (first (nth sx 2)))
(assert= "text" (nth (nth sx 2) 2)))))
;; ── Expressions ───────────────────────────────────────────────
(defsuite
@@ -138,7 +139,7 @@
"query emits dom-query"
(let
((sx (hs-to-sx (list (quote query) ".foo"))))
(assert= (quote dom-query) (first sx))
(assert= (quote hs-query-first) (first sx))
(assert= ".foo" (nth sx 1))))
(deftest
"attr emits dom-get-attr"
@@ -176,7 +177,7 @@
(let
((sx (hs-to-sx-from-source "on click from #btn add .clicked end")))
(assert= (quote hs-on) (first sx))
(assert= (quote dom-query) (first (nth sx 1)))))
(assert= (quote hs-query-first) (first (nth sx 1)))))
(deftest
"on every click"
(let
@@ -254,7 +255,10 @@
"hs-emit-return-throw"
(deftest
"return unwraps to value"
(let ((sx (hs-to-sx-from-source "return 42"))) (assert= 42 sx)))
(let
((sx (hs-to-sx-from-source "return 42")))
(assert= (quote raise) (first sx))
(assert= 42 (nth (nth sx 1) 2))))
(deftest
"throw becomes raise"
(let
@@ -306,11 +310,11 @@
(assert= (quote hs-on) (first sx))
(assert= "click" (nth sx 2))
(let
((body (nth (nth sx 3) 2)))
(assert= (quote do) (first body))
(assert= 3 (len (rest body)))
(assert= (quote hs-wait) (first (nth body 2)))
(assert= 1000 (nth (nth body 2) 1)))))
((body (nth (nth sx 3) 2)) (inner (nth (nth (nth sx 3) 2) 2)))
(assert= (quote let) (first body))
(assert= (quote let) (first inner))
(assert= (quote hs-wait) (first (nth (first (nth inner 1)) 1)))
(assert= 1000 (nth (nth (first (nth inner 1)) 1) 1)))))
(deftest
"count clicks: then chains increment and set in same handler"
(let
@@ -330,16 +334,16 @@
((sx (hs-to-sx-from-source "on click add .bounce to me then wait 1s then remove .bounce from me")))
(assert= (quote hs-on) (first sx))
(let
((body (nth (nth sx 3) 2)))
(assert= (quote do) (first body))
(assert= 3 (len (rest body)))
(assert= (quote hs-wait) (first (nth body 2)))
(assert= 1000 (nth (nth body 2) 1)))))
((inner (nth (nth (nth sx 3) 2) 2)))
(assert= (quote let) (first inner))
(assert= (quote hs-wait) (first (nth (first (nth inner 1)) 1)))
(assert= 1000 (nth (nth (first (nth inner 1)) 1) 1)))))
(deftest
"wait preserves ms value in handler"
(let
((sx (hs-to-sx-from-source "on click add .a then wait 2s then add .b")))
(let
((body (nth (nth sx 3) 2)))
(assert= (quote hs-wait) (first (nth body 2)))
(assert= 2000 (nth (nth body 2) 1))))))
((inner (nth (nth (nth sx 3) 2) 2)))
(assert= (quote let) (first inner))
(assert= (quote hs-wait) (first (nth (first (nth inner 1)) 1)))
(assert= 2000 (nth (nth (first (nth inner 1)) 1) 1))))))

View File

@@ -118,7 +118,7 @@
(let
((sx (hs-to-sx-from-source "fetch '/api'")))
(assert= (quote hs-fetch) (first sx))
(assert= "json" (nth sx 2))))
(assert= "text" (nth sx 2))))
(deftest
"source → SX shape: def function"
(let