Tokenizer: * and % now emit as operators (were silently swallowed) Added keywords: install, measure, behavior, called 5 new arithmetic operator tests Parser — expression layer: Arithmetic (+, -, *, /, %) via parse-arith Unary not, no, unary minus the X of Y possessive (parse-the-expr) as Type conversion, X in Y membership, array literals [...] fetch URL parsing fixed — no longer consumes "as" meant for fetch Parser — 8 new commands: return, throw, append...to, tell...end, for...in...end, make a Type, install Behavior, measure Parser — 2 new features: def name(params)...end, behavior Name(params)...end Parser — enhanced: wait for event [from target], on every event modifier 33 new parser tests (16 suites), 5 tokenizer tests. 3043/3043 full build, zero regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
712 lines
20 KiB
Plaintext
712 lines
20 KiB
Plaintext
;; _hyperscript parser tests
|
|
;; Tests that hs-compile (tokenize + parse) produces correct SX AST
|
|
|
|
;; ── Basic commands ────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-basic-commands"
|
|
(deftest
|
|
"add class to me"
|
|
(let
|
|
((ast (hs-compile "add .foo")))
|
|
(assert= (list (quote add-class) "foo" (list (quote me))) ast)))
|
|
(deftest
|
|
"add class to target"
|
|
(let
|
|
((ast (hs-compile "add .active to #btn")))
|
|
(assert=
|
|
(list (quote add-class) "active" (list (quote query) "#btn"))
|
|
ast)))
|
|
(deftest
|
|
"remove class from me"
|
|
(let
|
|
((ast (hs-compile "remove .hidden")))
|
|
(assert= (list (quote remove-class) "hidden" (list (quote me))) ast)))
|
|
(deftest
|
|
"remove class from target"
|
|
(let
|
|
((ast (hs-compile "remove .active from #nav")))
|
|
(assert=
|
|
(list (quote remove-class) "active" (list (quote query) "#nav"))
|
|
ast)))
|
|
(deftest
|
|
"toggle class on me"
|
|
(let
|
|
((ast (hs-compile "toggle .open")))
|
|
(assert= (list (quote toggle-class) "open" (list (quote me))) ast)))
|
|
(deftest
|
|
"toggle class on target"
|
|
(let
|
|
((ast (hs-compile "toggle .visible on #modal")))
|
|
(assert=
|
|
(list (quote toggle-class) "visible" (list (quote query) "#modal"))
|
|
ast)))
|
|
(deftest
|
|
"toggle between two classes"
|
|
(let
|
|
((ast (hs-compile "toggle between .red and .blue")))
|
|
(assert=
|
|
(list (quote toggle-between) "red" "blue" (list (quote me)))
|
|
ast)))
|
|
(deftest
|
|
"toggle between on target"
|
|
(let
|
|
((ast (hs-compile "toggle between .on and .off on #lamp")))
|
|
(assert=
|
|
(list
|
|
(quote toggle-between)
|
|
"on"
|
|
"off"
|
|
(list (quote query) "#lamp"))
|
|
ast))))
|
|
|
|
;; ── Assignment commands ───────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-assignment"
|
|
(deftest
|
|
"set property to string"
|
|
(let
|
|
((ast (hs-compile "set my.innerHTML to \"hello\"")))
|
|
(assert=
|
|
(list
|
|
(quote set!)
|
|
(list (quote .) (list (quote me)) "innerHTML")
|
|
"hello")
|
|
ast)))
|
|
(deftest
|
|
"set id property to value"
|
|
(let
|
|
((ast (hs-compile "set #d1.textContent to \"foo\"")))
|
|
(assert=
|
|
(list
|
|
(quote set!)
|
|
(list (quote .) (list (quote query) "#d1") "textContent")
|
|
"foo")
|
|
ast)))
|
|
(deftest
|
|
"put into"
|
|
(let
|
|
((ast (hs-compile "put \"Clicked\" into my.innerHTML")))
|
|
(assert=
|
|
(list
|
|
(quote set!)
|
|
(list (quote .) (list (quote me)) "innerHTML")
|
|
"Clicked")
|
|
ast)))
|
|
(deftest
|
|
"put before"
|
|
(let
|
|
((ast (hs-compile "put \"<hr>\" before #content")))
|
|
(assert=
|
|
(list (quote put!) "<hr>" "before" (list (quote query) "#content"))
|
|
ast)))
|
|
(deftest
|
|
"put after"
|
|
(let
|
|
((ast (hs-compile "put \"<hr>\" after #content")))
|
|
(assert=
|
|
(list (quote put!) "<hr>" "after" (list (quote query) "#content"))
|
|
ast))))
|
|
|
|
;; ── Event handlers ────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-events"
|
|
(deftest
|
|
"on click add class"
|
|
(let
|
|
((ast (hs-compile "on click add .called")))
|
|
(assert=
|
|
(list
|
|
(quote on)
|
|
"click"
|
|
(list (quote add-class) "called" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"on click from target"
|
|
(let
|
|
((ast (hs-compile "on click from #bar add .clicked")))
|
|
(assert=
|
|
(list
|
|
(quote on)
|
|
"click"
|
|
:from (list (quote query) "#bar")
|
|
(list (quote add-class) "clicked" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"on event with filter"
|
|
(let
|
|
((ast (hs-compile "on click[buttons==0] log event")))
|
|
(assert= (quote on) (first ast))
|
|
(assert= "click" (nth ast 1))))
|
|
(deftest
|
|
"on with command sequence"
|
|
(let
|
|
((ast (hs-compile "on click add .one then add .two")))
|
|
(assert= (quote on) (first ast))
|
|
(let
|
|
((body (last ast)))
|
|
(assert= (quote do) (first body))
|
|
(assert= 2 (len (rest body)))))))
|
|
|
|
;; ── Sequencing ────────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-sequencing"
|
|
(deftest
|
|
"then chains commands"
|
|
(let
|
|
((ast (hs-compile "add .a then add .b then add .c")))
|
|
(assert= (quote do) (first ast))
|
|
(assert= 3 (len (rest ast)))))
|
|
(deftest
|
|
"wait then add"
|
|
(let
|
|
((ast (hs-compile "wait 100ms then add .done")))
|
|
(assert= (quote do) (first ast))
|
|
(assert= (list (quote wait) 100) (nth ast 1))
|
|
(assert=
|
|
(list (quote add-class) "done" (list (quote me)))
|
|
(nth ast 2))))
|
|
(deftest
|
|
"wait seconds"
|
|
(let
|
|
((ast (hs-compile "wait 2s then add .done")))
|
|
(assert= (quote do) (first ast))
|
|
(assert= (list (quote wait) 2000) (nth ast 1)))))
|
|
|
|
;; ── Conditional ───────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-conditional"
|
|
(deftest
|
|
"if then end"
|
|
(let
|
|
((ast (hs-compile "if true add .x end")))
|
|
(assert= (quote if) (first ast))
|
|
(assert= true (nth ast 1))
|
|
(assert= (list (quote add-class) "x" (list (quote me))) (nth ast 2))))
|
|
(deftest
|
|
"if else end"
|
|
(let
|
|
((ast (hs-compile "if true add .a else add .b end")))
|
|
(assert= (quote if) (first ast))
|
|
(assert= (list (quote add-class) "a" (list (quote me))) (nth ast 2))
|
|
(assert= (list (quote add-class) "b" (list (quote me))) (nth ast 3)))))
|
|
|
|
;; ── Special commands ──────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-special-commands"
|
|
(deftest
|
|
"log expression"
|
|
(let
|
|
((ast (hs-compile "log event")))
|
|
(assert= (list (quote log) (list (quote event))) ast)))
|
|
(deftest
|
|
"increment attribute"
|
|
(let
|
|
((ast (hs-compile "increment @count")))
|
|
(assert=
|
|
(list
|
|
(quote increment!)
|
|
(list (quote attr) "count" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"decrement attribute"
|
|
(let
|
|
((ast (hs-compile "decrement @score")))
|
|
(assert=
|
|
(list
|
|
(quote decrement!)
|
|
(list (quote attr) "score" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"hide"
|
|
(let
|
|
((ast (hs-compile "hide")))
|
|
(assert= (list (quote hide) (list (quote me))) ast)))
|
|
(deftest
|
|
"show target"
|
|
(let
|
|
((ast (hs-compile "show #panel")))
|
|
(assert= (list (quote show) (list (quote query) "#panel")) ast)))
|
|
(deftest
|
|
"settle"
|
|
(let
|
|
((ast (hs-compile "settle")))
|
|
(assert= (list (quote settle)) ast))))
|
|
|
|
;; ── Send and trigger ──────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-send-trigger"
|
|
(deftest
|
|
"send event to target"
|
|
(let
|
|
((ast (hs-compile "send custom to #d1")))
|
|
(assert= (quote send) (first ast))
|
|
(assert= "custom" (nth ast 1))
|
|
(assert= (list (quote query) "#d1") (last ast))))
|
|
(deftest
|
|
"trigger event on target"
|
|
(let
|
|
((ast (hs-compile "trigger reset on #form")))
|
|
(assert=
|
|
(list (quote trigger) "reset" (list (quote query) "#form"))
|
|
ast)))
|
|
(deftest
|
|
"trigger event on me"
|
|
(let
|
|
((ast (hs-compile "trigger click")))
|
|
(assert= (list (quote trigger) "click" (list (quote me))) ast))))
|
|
|
|
;; ── DOM traversal ─────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-dom-traversal"
|
|
(deftest
|
|
"closest class"
|
|
(let
|
|
((ast (hs-compile "log closest .card")))
|
|
(assert= (quote log) (first ast))
|
|
(assert= (quote closest) (first (nth ast 1)))
|
|
(assert= ".card" (nth (nth ast 1) 1))))
|
|
(deftest
|
|
"next sibling"
|
|
(let
|
|
((ast (hs-compile "log next .item")))
|
|
(assert= (quote next) (first (nth ast 1)))))
|
|
(deftest
|
|
"previous sibling"
|
|
(let
|
|
((ast (hs-compile "log previous .item")))
|
|
(assert= (quote previous) (first (nth ast 1))))))
|
|
|
|
;; ── Expressions ───────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-expressions"
|
|
(deftest
|
|
"property chain"
|
|
(let
|
|
((ast (hs-compile "log my.style.color")))
|
|
(assert= (quote log) (first ast))
|
|
(let
|
|
((expr (nth ast 1)))
|
|
(assert= (quote .) (first expr))
|
|
(assert= "color" (nth expr 2)))))
|
|
(deftest
|
|
"it reference"
|
|
(let
|
|
((ast (hs-compile "log it")))
|
|
(assert= (list (quote log) (list (quote it))) ast)))
|
|
(deftest
|
|
"comparison is empty"
|
|
(let
|
|
((ast (hs-compile "if result is empty add .hidden end")))
|
|
(assert= (quote if) (first ast))
|
|
(assert= (list (quote empty?) (list (quote it))) (nth ast 1))))
|
|
(deftest
|
|
"comparison is not"
|
|
(let
|
|
((ast (hs-compile "if result is not null add .ok end")))
|
|
(assert= (quote if) (first ast))
|
|
(assert= (quote not) (first (nth ast 1)))))
|
|
(deftest
|
|
"exists predicate"
|
|
(let
|
|
((ast (hs-compile "if #panel exists show #panel end")))
|
|
(assert= (quote if) (first ast))
|
|
(assert= (quote exists?) (first (nth ast 1)))))
|
|
(deftest
|
|
"attribute ref"
|
|
(let
|
|
((ast (hs-compile "log @data-id")))
|
|
(assert=
|
|
(list (quote log) (list (quote attr) "data-id" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"style ref"
|
|
(let
|
|
((ast (hs-compile "log *color")))
|
|
(assert=
|
|
(list (quote log) (list (quote style) "color" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"local ref"
|
|
(let
|
|
((ast (hs-compile "log :myVar")))
|
|
(assert= (list (quote log) (list (quote local) "myVar")) ast)))
|
|
(deftest
|
|
"selector query"
|
|
(let
|
|
((ast (hs-compile "log <div.card/>")))
|
|
(assert= (list (quote log) (list (quote query) "div.card")) ast))))
|
|
|
|
;; ── Repeat ────────────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-repeat"
|
|
(deftest
|
|
"repeat forever"
|
|
(let
|
|
((ast (hs-compile "repeat forever add .pulse then settle end")))
|
|
(assert= (quote repeat) (first ast))
|
|
(assert= (list (quote forever)) (nth ast 1))))
|
|
(deftest
|
|
"repeat N times"
|
|
(let
|
|
((ast (hs-compile "repeat 3 times add .flash then settle end")))
|
|
(assert= (quote repeat) (first ast))
|
|
(assert= (list (quote times) 3) (nth ast 1)))))
|
|
|
|
;; ── Fetch and call ────────────────────────────────────────────────
|
|
(defsuite
|
|
"hs-parse-fetch-call"
|
|
(deftest
|
|
"fetch url"
|
|
(let
|
|
((ast (hs-compile "fetch \"/api/data\"")))
|
|
(assert= (quote fetch) (first ast))
|
|
(assert= "/api/data" (nth ast 1))))
|
|
(deftest
|
|
"fetch as text"
|
|
(let
|
|
((ast (hs-compile "fetch \"/api/data\" as text")))
|
|
(assert= "text" (nth ast 2))))
|
|
(deftest
|
|
"call function"
|
|
(let
|
|
((ast (hs-compile "call alert(\"hello\")")))
|
|
(assert= (quote call) (first ast))
|
|
(assert= "alert" (nth ast 1))
|
|
(assert= "hello" (nth ast 2)))))
|
|
|
|
;; ── Full expressions (matching tokenizer conformance) ─────────────
|
|
(defsuite
|
|
"hs-parse-arithmetic"
|
|
(deftest
|
|
"addition"
|
|
(let
|
|
((ast (hs-compile "set x to 1 + 2")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote +) (first val))
|
|
(assert= 1 (nth val 1))
|
|
(assert= 2 (nth val 2)))))
|
|
(deftest
|
|
"subtraction"
|
|
(let
|
|
((ast (hs-compile "set x to 10 - 3")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote -) (first val))
|
|
(assert= 10 (nth val 1))
|
|
(assert= 3 (nth val 2)))))
|
|
(deftest
|
|
"multiplication"
|
|
(let
|
|
((ast (hs-compile "set x to 4 * 5")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote *) (first val))
|
|
(assert= 4 (nth val 1))
|
|
(assert= 5 (nth val 2)))))
|
|
(deftest
|
|
"division"
|
|
(let
|
|
((ast (hs-compile "set x to 10 / 2")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote /) (first val))
|
|
(assert= 10 (nth val 1))
|
|
(assert= 2 (nth val 2)))))
|
|
(deftest
|
|
"chained arithmetic"
|
|
(let
|
|
((ast (hs-compile "set x to 1 + 2 + 3")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote +) (first val))
|
|
(assert= 3 (nth val 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-unary"
|
|
(deftest
|
|
"not expr"
|
|
(let
|
|
((ast (hs-compile "if not x end")))
|
|
(let ((cnd (nth ast 1))) (assert= (quote not) (first cnd)))))
|
|
(deftest
|
|
"no expr"
|
|
(let
|
|
((ast (hs-compile "if no x end")))
|
|
(let ((cnd (nth ast 1))) (assert= (quote no) (first cnd)))))
|
|
(deftest
|
|
"unary minus"
|
|
(let
|
|
((ast (hs-compile "set x to -5")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote -) (first val))
|
|
(assert= 0 (nth val 1))
|
|
(assert= 5 (nth val 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-the-of"
|
|
(deftest
|
|
"the innerHTML of me"
|
|
(let
|
|
((ast (hs-compile "set the innerHTML of me to 'hi'")))
|
|
(let
|
|
((tgt (nth ast 1)))
|
|
(assert= (make-symbol ".") (first tgt))
|
|
(assert= "innerHTML" (nth tgt 2)))))
|
|
(deftest
|
|
"the as article skip"
|
|
(let
|
|
((ast (hs-compile "set the result to 5")))
|
|
(let ((tgt (nth ast 1))) (assert= (quote it) (first tgt))))))
|
|
|
|
(defsuite
|
|
"hs-parse-as-conversion"
|
|
(deftest
|
|
"expr as Int"
|
|
(let
|
|
((ast (hs-compile "set x to y as Int")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote as) (first val))
|
|
(assert= "Int" (nth val 2)))))
|
|
(deftest
|
|
"expr as String"
|
|
(let
|
|
((ast (hs-compile "set x to count as String")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote as) (first val))
|
|
(assert= "String" (nth val 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-in-operator"
|
|
(deftest
|
|
"x in collection"
|
|
(let
|
|
((ast (hs-compile "if x in items end")))
|
|
(let ((cnd (nth ast 1))) (assert= (quote in?) (first cnd))))))
|
|
|
|
(defsuite
|
|
"hs-parse-array-literals"
|
|
(deftest
|
|
"empty array"
|
|
(let
|
|
((ast (hs-compile "set x to []")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote array) (first val))
|
|
(assert= 1 (len val)))))
|
|
(deftest
|
|
"array with elements"
|
|
(let
|
|
((ast (hs-compile "set x to [1, 2, 3]")))
|
|
(let
|
|
((val (nth ast 2)))
|
|
(assert= (quote array) (first val))
|
|
(assert= 4 (len val))
|
|
(assert= 1 (nth val 1))
|
|
(assert= 2 (nth val 2))
|
|
(assert= 3 (nth val 3))))))
|
|
|
|
(defsuite
|
|
"hs-parse-return-throw"
|
|
(deftest
|
|
"return expr"
|
|
(let
|
|
((ast (hs-compile "return 42")))
|
|
(assert= (quote return) (first ast))
|
|
(assert= 42 (nth ast 1))))
|
|
(deftest
|
|
"return bare"
|
|
(let
|
|
((ast (hs-compile "return")))
|
|
(assert= (quote return) (first ast))
|
|
(assert= nil (nth ast 1))))
|
|
(deftest
|
|
"throw expr"
|
|
(let
|
|
((ast (hs-compile "throw 'error'")))
|
|
(assert= (quote throw) (first ast))
|
|
(assert= "error" (nth ast 1)))))
|
|
|
|
(defsuite
|
|
"hs-parse-append"
|
|
(deftest
|
|
"append to target"
|
|
(let
|
|
((ast (hs-compile "append 'hello' to me")))
|
|
(assert= (quote append!) (first ast))
|
|
(assert= "hello" (nth ast 1))
|
|
(assert= (quote me) (first (nth ast 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-tell"
|
|
(deftest
|
|
"tell target commands end"
|
|
(let
|
|
((ast (hs-compile "tell <div/> add .active end")))
|
|
(assert= (quote tell) (first ast))
|
|
(assert= (quote query) (first (nth ast 1)))
|
|
(assert= (quote add-class) (first (nth ast 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-for"
|
|
(deftest
|
|
"for x in items end"
|
|
(let
|
|
((ast (hs-compile "for item in items log item end")))
|
|
(assert= (quote for) (first ast))
|
|
(assert= "item" (nth ast 1))
|
|
(assert= (quote ref) (first (nth ast 2)))
|
|
(assert= (quote log) (first (nth ast 3)))))
|
|
(deftest
|
|
"for with index"
|
|
(let
|
|
((ast (hs-compile "for item in items index i log item end")))
|
|
(assert= (quote for) (first ast))
|
|
(assert= "item" (nth ast 1)))))
|
|
|
|
(defsuite
|
|
"hs-parse-make"
|
|
(deftest
|
|
"make a Object"
|
|
(let
|
|
((ast (hs-compile "make a Object")))
|
|
(assert= (quote make) (first ast))
|
|
(assert= "Object" (nth ast 1))))
|
|
(deftest
|
|
"make a Set called s"
|
|
(let
|
|
((ast (hs-compile "make a Set called s")))
|
|
(assert= (quote make) (first ast))
|
|
(assert= "Set" (nth ast 1))
|
|
(assert= "s" (nth ast 2)))))
|
|
|
|
(defsuite
|
|
"hs-parse-install"
|
|
(deftest
|
|
"install behavior"
|
|
(let
|
|
((ast (hs-compile "install Draggable")))
|
|
(assert= (quote install) (first ast))
|
|
(assert= "Draggable" (nth ast 1))))
|
|
(deftest
|
|
"install with args"
|
|
(let
|
|
((ast (hs-compile "install Sortable(true)")))
|
|
(assert= (quote install) (first ast))
|
|
(assert= "Sortable" (nth ast 1))
|
|
(assert= true (nth ast 2)))))
|
|
|
|
(defsuite
|
|
"hs-parse-measure"
|
|
(deftest
|
|
"measure target"
|
|
(let
|
|
((ast (hs-compile "measure me")))
|
|
(assert= (quote measure) (first ast))
|
|
(assert= (quote me) (first (nth ast 1))))))
|
|
|
|
(defsuite
|
|
"hs-parse-wait-for"
|
|
(deftest
|
|
"wait for transitionend"
|
|
(let
|
|
((ast (hs-compile "wait for transitionend")))
|
|
(assert= (quote wait-for) (first ast))
|
|
(assert= "transitionend" (nth ast 1))))
|
|
(deftest
|
|
"wait for click from target"
|
|
(let
|
|
((ast (hs-compile "wait for click from #btn")))
|
|
(assert= (quote wait-for) (first ast))
|
|
(assert= "click" (nth ast 1))
|
|
(assert= :from (nth ast 2)))))
|
|
|
|
(defsuite
|
|
"hs-parse-def-behavior"
|
|
(deftest
|
|
"def function"
|
|
(let
|
|
((ast (hs-compile "def greet(name) log name end")))
|
|
(assert= (quote def) (first ast))
|
|
(assert= "greet" (nth ast 1))
|
|
(assert= 1 (len (nth ast 2)))
|
|
(assert= (quote log) (first (nth ast 3)))))
|
|
(deftest
|
|
"behavior with on handler"
|
|
(let
|
|
((ast (hs-compile "behavior Clickable on click add .clicked end end")))
|
|
(assert= (quote behavior) (first ast))
|
|
(assert= "Clickable" (nth ast 1))
|
|
(assert= 1 (len (nth ast 3)))))
|
|
(deftest
|
|
"def no params"
|
|
(let
|
|
((ast (hs-compile "def reset() set x to 0 end")))
|
|
(assert= (quote def) (first ast))
|
|
(assert= "reset" (nth ast 1))
|
|
(assert= 0 (len (nth ast 2))))))
|
|
|
|
(defsuite
|
|
"hs-parse-every-modifier"
|
|
(deftest
|
|
"on every click"
|
|
(let
|
|
((ast (hs-compile "on every click add .pulse end")))
|
|
(assert= (quote on) (first ast))
|
|
(assert= "click" (nth ast 1))
|
|
(assert= :every (nth ast 2))
|
|
(assert= true (nth ast 3)))))
|
|
|
|
(defsuite
|
|
"hs-parse-conformance"
|
|
(deftest
|
|
"on click add .called → full AST"
|
|
(let
|
|
((ast (hs-compile "on click add .called")))
|
|
(assert=
|
|
(list
|
|
(quote on)
|
|
"click"
|
|
(list (quote add-class) "called" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"toggle between .foo and .bar → full AST"
|
|
(let
|
|
((ast (hs-compile "toggle between .foo and .bar")))
|
|
(assert=
|
|
(list (quote toggle-between) "foo" "bar" (list (quote me)))
|
|
ast)))
|
|
(deftest
|
|
"wait 100ms then add .done → full AST"
|
|
(let
|
|
((ast (hs-compile "wait 100ms then add .done")))
|
|
(assert=
|
|
(list
|
|
(quote do)
|
|
(list (quote wait) 100)
|
|
(list (quote add-class) "done" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"increment @count → full AST"
|
|
(let
|
|
((ast (hs-compile "increment @count")))
|
|
(assert=
|
|
(list
|
|
(quote increment!)
|
|
(list (quote attr) "count" (list (quote me))))
|
|
ast)))
|
|
(deftest
|
|
"on click from #bar add .clicked → full AST"
|
|
(let
|
|
((ast (hs-compile "on click from #bar add .clicked")))
|
|
(assert=
|
|
(list
|
|
(quote on)
|
|
"click"
|
|
:from (list (quote query) "#bar")
|
|
(list (quote add-class) "clicked" (list (quote me))))
|
|
ast))))
|