HS: extend parser/runtime + new node test runner; ignore test-results/
- Parser: `--` line comments, `|` op, `result` → `the-result`, query-scoped `<sel> in <expr>`, `is a/an <type>` predicate, multi-`as` chaining with `|`, `match`/`precede` keyword aliases, `[attr]` add/toggle, between attr forms - Runtime: per-element listener registry + hs-deactivate!, attr toggle variants, set-inner-html boots subtree, hs-append polymorphic on string/list/element, default? / array-set! / query-all-in / list-set via take+drop, hs-script idempotence guard - Integration: skip reserved (me/it/event/you/yourself) when collecting vars - Tokenizer: emit `--` comments and `|` op - Test framework + conformance runner updates; new tests/hs-run-filtered.js (single-process Node runner using OCaml VM step-limit to bound infinite loops); generate-sx-conformance-dev.py improvements - mcp_tree.ml + run_tests.ml: harness extensions - .gitignore: top-level test-results/ (Playwright artifacts) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,11 +18,18 @@
|
||||
;; 1. Test framework macros
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defmacro deftest (name &rest body)
|
||||
`(let ((result (try-call (fn () ,@body))))
|
||||
(if (get result "ok")
|
||||
(report-pass ,name)
|
||||
(report-fail ,name (get result "error")))))
|
||||
(defmacro
|
||||
deftest
|
||||
(name &rest body)
|
||||
(quasiquote
|
||||
(when
|
||||
(test-allowed? (unquote name))
|
||||
(let
|
||||
((result (try-call (fn () (splice-unquote body)))))
|
||||
(if
|
||||
(get result "ok")
|
||||
(report-pass (unquote name))
|
||||
(report-fail (unquote name) (get result "error")))))))
|
||||
|
||||
(defmacro defsuite (name &rest items)
|
||||
`(do (push-suite ,name)
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
"put into #id compiled"
|
||||
(let
|
||||
((sx (hs-to-sx-from-source "on click put \"foo\" into #d1")))
|
||||
(assert= (serialize sx) "SHOW")))
|
||||
(assert=
|
||||
(serialize sx)
|
||||
"(hs-on me \"click\" (fn (event) (hs-set-inner-html! (hs-query-first \"#d1\") \"foo\")))")))
|
||||
(deftest
|
||||
"put into #id works"
|
||||
(let
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@
|
||||
"set attribute"
|
||||
(let
|
||||
((sx (hs-to-sx-from-source "set @title to 'hello'")))
|
||||
(assert= (quote dom-set-attr) (first sx))
|
||||
(assert= (quote hs-set-attr!) (first sx))
|
||||
(assert= "title" (nth sx 2))
|
||||
(assert= "hello" (nth sx 3))))
|
||||
(deftest
|
||||
@@ -284,12 +284,16 @@
|
||||
"increment attribute"
|
||||
(let
|
||||
((sx (hs-to-sx-from-source "increment @count")))
|
||||
(assert= (quote dom-set-attr) (first sx))))
|
||||
(assert= (quote let) (first sx))
|
||||
(assert= (quote do) (first (nth sx 2)))
|
||||
(assert= (quote dom-set-attr) (first (nth (nth sx 2) 1)))))
|
||||
(deftest
|
||||
"decrement attribute"
|
||||
(let
|
||||
((sx (hs-to-sx-from-source "decrement @count")))
|
||||
(assert= (quote dom-set-attr) (first sx)))))
|
||||
(assert= (quote let) (first sx))
|
||||
(assert= (quote do) (first (nth sx 2)))
|
||||
(assert= (quote dom-set-attr) (first (nth (nth sx 2) 1))))))
|
||||
|
||||
(defsuite
|
||||
"hs-live-demo-toggle"
|
||||
|
||||
@@ -59,44 +59,73 @@
|
||||
)
|
||||
|
||||
;; ── collectionExpressions (12 tests) ──
|
||||
(defsuite "hs-dev-collectionExpressions"
|
||||
(deftest "filters an array by condition"
|
||||
(let ((result (eval-hs "set arr to [{name: \"a\", active: true}, {name: \"b\", active: false}, {name: \"c\", active: true}] then return arr where its active")))
|
||||
(defsuite
|
||||
"hs-dev-collectionExpressions"
|
||||
(deftest
|
||||
"filters an array by condition"
|
||||
(let
|
||||
((result (eval-hs "set arr to [{name: \"a\", active: true}, {name: \"b\", active: false}, {name: \"c\", active: true}] then return arr where its active")))
|
||||
(assert= (list "a" "c") (map (fn (x) (get x "name")) result))))
|
||||
(deftest "filters with comparison"
|
||||
(assert= (list 4 5) (eval-hs "set arr to [1, 2, 3, 4, 5] then return arr where it > 3"))
|
||||
)
|
||||
(deftest "sorts by a property"
|
||||
(let ((result (eval-hs "set arr to [{name: \"Charlie\"}, {name: \"Alice\"}, {name: \"Bob\"}] then return arr sorted by its name")))
|
||||
(assert= (list "Alice" "Bob" "Charlie") (map (fn (x) (get x "name")) result))))
|
||||
(deftest "sorts descending"
|
||||
(assert= (list 3 2 1) (eval-hs "set arr to [3, 1, 2] then return arr sorted by it descending"))
|
||||
)
|
||||
(deftest "sorts numbers by a computed key"
|
||||
(let ((result (eval-hs "set arr to [{name: \"b\", age: 30}, {name: \"a\", age: 20}, {name: \"c\", age: 25}] then return arr sorted by its age")))
|
||||
(deftest
|
||||
"filters with comparison"
|
||||
(assert=
|
||||
(list 4 5)
|
||||
(eval-hs "set arr to [1, 2, 3, 4, 5] then return arr where it > 3")))
|
||||
(deftest
|
||||
"sorts by a property"
|
||||
(let
|
||||
((result (eval-hs "set arr to [{name: \"Charlie\"}, {name: \"Alice\"}, {name: \"Bob\"}] then return arr sorted by its name")))
|
||||
(assert=
|
||||
(list "Alice" "Bob" "Charlie")
|
||||
(map (fn (x) (get x "name")) result))))
|
||||
(deftest
|
||||
"sorts descending"
|
||||
(assert=
|
||||
(list 3 2 1)
|
||||
(eval-hs "set arr to [3, 1, 2] then return arr sorted by it descending")))
|
||||
(deftest
|
||||
"sorts numbers by a computed key"
|
||||
(let
|
||||
((result (eval-hs "set arr to [{name: \"b\", age: 30}, {name: \"a\", age: 20}, {name: \"c\", age: 25}] then return arr sorted by its age")))
|
||||
(assert= (list "a" "c" "b") (map (fn (x) (get x "name")) result))))
|
||||
(deftest "maps to a property"
|
||||
(assert= (list "Alice" "Bob") (eval-hs "set arr to [{name: \"Alice\"}, {name: \"Bob\"}] then return arr mapped to its name"))
|
||||
)
|
||||
(deftest "maps with an expression"
|
||||
(assert= (list 2 4 6) (eval-hs "set arr to [1, 2, 3] then return arr mapped to (it * 2)"))
|
||||
)
|
||||
(deftest "where then mapped to"
|
||||
(assert= (list "Alice" "Charlie") (eval-hs "set arr to [{name: \"Alice\", active: true}, {name: \"Bob\", active: false}, {name: \"Charlie\", active: true}] then return arr where its active mapped to its name"))
|
||||
)
|
||||
(deftest "sorted by then mapped to"
|
||||
(assert= (list "Alice" "Charlie") (eval-hs "set arr to [{name: \"Charlie\", age: 30}, {name: \"Alice\", age: 20}] then return arr sorted by its age mapped to its name"))
|
||||
)
|
||||
(deftest "where then sorted by then mapped to"
|
||||
(assert= (list "Bob" "Charlie") (eval-hs "set arr to [{name: \"Charlie\", active: true, age: 30}, {name: \"Alice\", active: false, age: 20}, {name: \"Bob\", active: true, age: 25}] then return arr where its active sorted by its age mapped to its name"))
|
||||
)
|
||||
(deftest "the result inside where refers to previous command result, not current element"
|
||||
(assert= (list 4 5) (eval-hs "get 3 then set arr to [1, 2, 3, 4, 5] then return arr where it > the result"))
|
||||
)
|
||||
(deftest "where binds after property access"
|
||||
(assert= (list 3 4) (eval-hs "obj.items where it > 2"))
|
||||
)
|
||||
)
|
||||
(deftest
|
||||
"maps to a property"
|
||||
(assert=
|
||||
(list "Alice" "Bob")
|
||||
(eval-hs
|
||||
"set arr to [{name: \"Alice\"}, {name: \"Bob\"}] then return arr mapped to its name")))
|
||||
(deftest
|
||||
"maps with an expression"
|
||||
(assert=
|
||||
(list 2 4 6)
|
||||
(eval-hs "set arr to [1, 2, 3] then return arr mapped to (it * 2)")))
|
||||
(deftest
|
||||
"where then mapped to"
|
||||
(assert=
|
||||
(list "Alice" "Charlie")
|
||||
(eval-hs
|
||||
"set arr to [{name: \"Alice\", active: true}, {name: \"Bob\", active: false}, {name: \"Charlie\", active: true}] then return arr where its active mapped to its name")))
|
||||
(deftest
|
||||
"sorted by then mapped to"
|
||||
(assert=
|
||||
(list "Alice" "Charlie")
|
||||
(eval-hs
|
||||
"set arr to [{name: \"Charlie\", age: 30}, {name: \"Alice\", age: 20}] then return arr sorted by its age mapped to its name")))
|
||||
(deftest
|
||||
"where then sorted by then mapped to"
|
||||
(assert=
|
||||
(list "Bob" "Charlie")
|
||||
(eval-hs
|
||||
"set arr to [{name: \"Charlie\", active: true, age: 30}, {name: \"Alice\", active: false, age: 20}, {name: \"Bob\", active: true, age: 25}] then return arr where its active sorted by its age mapped to its name")))
|
||||
(deftest
|
||||
"the result inside where refers to previous command result, not current element"
|
||||
(assert=
|
||||
(list 4 5)
|
||||
(eval-hs
|
||||
"get 3 then set arr to [1, 2, 3, 4, 5] then return arr where it > the result")))
|
||||
(deftest
|
||||
"where binds after property access"
|
||||
(assert= (list 3 4) (eval-hs "obj.items where it > 2" {:locals {:obj {:items (list 1 2 3 4)}}}))))
|
||||
|
||||
;; ── splitJoin (7 tests) ──
|
||||
(defsuite "hs-dev-splitJoin"
|
||||
|
||||
@@ -302,7 +302,7 @@
|
||||
(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))))
|
||||
(assert= (list (quote empty?) (quote the-result)) (nth ast 1))))
|
||||
(deftest
|
||||
"comparison is not"
|
||||
(let
|
||||
@@ -375,7 +375,7 @@
|
||||
(let
|
||||
((ast (hs-compile "call alert(\"hello\")")))
|
||||
(assert= (quote call) (first ast))
|
||||
(assert= "alert" (nth ast 1))
|
||||
(assert= (list (quote ref) "alert") (nth ast 1))
|
||||
(assert= "hello" (nth ast 2)))))
|
||||
|
||||
;; ── Full expressions (matching tokenizer conformance) ─────────────
|
||||
@@ -462,7 +462,7 @@
|
||||
"the as article skip"
|
||||
(let
|
||||
((ast (hs-compile "set the result to 5")))
|
||||
(let ((tgt (nth ast 1))) (assert= (quote it) (first tgt))))))
|
||||
(let ((tgt (nth ast 1))) (assert= (quote the-result) tgt)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-as-conversion"
|
||||
|
||||
Reference in New Issue
Block a user