New spec tests: test-cek-try-seq (CEK try/seq), test-htmx (htmx directive coverage, 292L), test-hs-diag, test-perform-chain (IO suspension chains). tests/hs-*.js: Node.js-side hyperscript runners for browser-mode testing (hs-behavioral-node, hs-behavioral-runner, hs-parse-audit, hs-run-timed). Vendors shared/static/scripts/htmx.min.js. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
3.0 KiB
Plaintext
63 lines
3.0 KiB
Plaintext
;; Tests for perform/IO suspension chaining through for-each
|
|
;; Bug: after resume from first perform inside for-each,
|
|
;; subsequent iterations' performs don't suspend — they complete
|
|
;; synchronously, breaking multi-step async sequences like test runners.
|
|
|
|
(defsuite
|
|
"perform-for-each-chain"
|
|
(deftest
|
|
"for-each with perform suspends on each iteration"
|
|
(let
|
|
((state1 (cek-step-loop (make-cek-state (quote (let ((results (list))) (for-each (fn (item) (let ((val (perform {:op "fetch" :key item}))) (append! results val))) (list "a" "b" "c")) results)) (make-env) (list)))))
|
|
(assert-true (cek-suspended? state1))
|
|
(assert= "a" (get (cek-io-request state1) :key))
|
|
(let
|
|
((state2 (cek-resume state1 "result-a")))
|
|
(assert-true (cek-suspended? state2))
|
|
(assert= "b" (get (cek-io-request state2) :key))
|
|
(let
|
|
((state3 (cek-resume state2 "result-b")))
|
|
(assert-true (cek-suspended? state3))
|
|
(assert= "c" (get (cek-io-request state3) :key))
|
|
(let
|
|
((final (cek-resume state3 "result-c")))
|
|
(assert-true (cek-terminal? final))
|
|
(assert= 3 (len (cek-value final))))))))
|
|
(deftest
|
|
"for-each with guard and perform chains correctly"
|
|
(let
|
|
((state1 (cek-step-loop (make-cek-state (quote (let ((results (list))) (for-each (fn (item) (guard (e (true (append! results (str "fail:" item)))) (let ((val (perform {:op "fetch" :key item}))) (append! results (str "ok:" val))))) (list "x" "y")) results)) (make-env) (list)))))
|
|
(assert-true (cek-suspended? state1))
|
|
(let
|
|
((state2 (cek-resume state1 "X")))
|
|
(assert-true (cek-suspended? state2))
|
|
(let
|
|
((final (cek-resume state2 "Y")))
|
|
(assert-true (cek-terminal? final))
|
|
(let
|
|
((results (cek-value final)))
|
|
(assert= 2 (len results))
|
|
(assert= "ok:X" (nth results 0))
|
|
(assert= "ok:Y" (nth results 1)))))))
|
|
(deftest
|
|
"nested performs in for-each — reload + wait pattern"
|
|
(let
|
|
((state1 (cek-step-loop (make-cek-state (quote (let ((log (list))) (for-each (fn (name) (perform {:op "wait" :ms 1000}) (append! log (str "reloaded:" name)) (perform {:op "wait" :ms 500}) (append! log (str "done:" name))) (list "t1" "t2")) log)) (make-env) (list)))))
|
|
(assert-true (cek-suspended? state1))
|
|
(assert= 1000 (get (cek-io-request state1) :ms))
|
|
(let
|
|
((s2 (cek-resume state1 nil)))
|
|
(assert-true (cek-suspended? s2))
|
|
(assert= 500 (get (cek-io-request s2) :ms))
|
|
(let
|
|
((s3 (cek-resume s2 nil)))
|
|
(assert-true (cek-suspended? s3))
|
|
(assert= 1000 (get (cek-io-request s3) :ms))
|
|
(let
|
|
((s4 (cek-resume s3 nil)))
|
|
(assert-true (cek-suspended? s4))
|
|
(assert= 500 (get (cek-io-request s4) :ms))
|
|
(let
|
|
((final (cek-resume s4 nil)))
|
|
(assert-true (cek-terminal? final))
|
|
(assert= 4 (len (cek-value final)))))))))) |