;; _hyperscript runtime tests ;; Pure function tests run directly; DOM-dependent shims tested via Playwright. ;; ── Type coercion ───────────────────────────────────────────── (defsuite "hs-runtime-coerce" (deftest "coerce string to Int" (assert= 42 (hs-coerce "42" "Int"))) (deftest "coerce string to Float" (assert= 3.14 (hs-coerce "3.14" "Float"))) (deftest "coerce number to String" (assert= "42" (hs-coerce 42 "String"))) (deftest "coerce truthy to Boolean" (assert= true (hs-coerce 1 "Boolean"))) (deftest "coerce falsy to Boolean" (assert= false (hs-coerce nil "Boolean"))) (deftest "coerce value to Array wraps" (let ((result (hs-coerce 5 "Array"))) (assert= true (list? result)) (assert= 5 (first result)))) (deftest "coerce list to Array passes through" (let ((result (hs-coerce (list 1 2) "Array"))) (assert= 2 (len result)))) (deftest "unknown type passes through" (assert= "hello" (hs-coerce "hello" "Foo")))) ;; ── Object creation ─────────────────────────────────────────── (defsuite "hs-runtime-make" (deftest "make Object returns dict" (let ((obj (hs-make "Object"))) (assert= true (dict? obj)))) (deftest "make Array returns list" (let ((arr (hs-make "Array"))) (assert= true (list? arr)) (assert= 0 (len arr)))) (deftest "make Set returns list" (let ((s (hs-make "Set"))) (assert= true (list? s)))) (deftest "make Map returns dict" (let ((m (hs-make "Map"))) (assert= true (dict? m))))) ;; ── Iteration ───────────────────────────────────────────────── (defsuite "hs-runtime-repeat" (deftest "repeat-times calls thunk N times" (let ((count 0)) (hs-repeat-times 5 (fn () (set! count (+ count 1)))) (assert= 5 count))) (deftest "repeat-times zero does nothing" (let ((count 0)) (hs-repeat-times 0 (fn () (set! count (+ count 1)))) (assert= 0 count))) (deftest "repeat-times one" (let ((count 0)) (hs-repeat-times 1 (fn () (set! count (+ count 1)))) (assert= 1 count)))) ;; ── Init ────────────────────────────────────────────────────── (defsuite "hs-runtime-init" (deftest "init calls thunk" (let ((called false)) (hs-init (fn () (set! called true))) (assert= true called)))) ;; ── End-to-end pipeline ─────────────────────────────────────── (defsuite "hs-runtime-e2e" (deftest "source → SX shape: add class" (let ((sx (hs-to-sx-from-source "add .active to me"))) (assert= (quote dom-add-class) (first sx)) (assert= 3 (len sx)))) (deftest "source → SX shape: sequence" (let ((sx (hs-to-sx-from-source "add .a to me then add .b to me"))) (assert= (quote do) (first sx)) (assert= 3 (len sx)))) (deftest "source → SX shape: on handler" (let ((sx (hs-to-sx-from-source "on click log 'hi' end"))) (assert= (quote hs-on) (first sx)) (assert= (quote me) (nth sx 1)) (assert= "click" (nth sx 2)))) (deftest "source → SX shape: if-else" (let ((sx (hs-to-sx-from-source "if true log 1 else log 0 end"))) (assert= (quote if) (first sx)))) (deftest "source → SX shape: set variable" (let ((sx (hs-to-sx-from-source "set x to 42"))) (assert= (quote set!) (first sx)) (assert= (quote x) (nth sx 1)) (assert= 42 (nth sx 2)))) (deftest "source → SX shape: fetch" (let ((sx (hs-to-sx-from-source "fetch '/api'"))) (assert= (quote hs-fetch) (first sx)) (assert= "json" (nth sx 2)))) (deftest "source → SX shape: def function" (let ((sx (hs-to-sx-from-source "def add(a, b) return a end"))) (assert= (quote define) (first sx)) (assert= (quote add) (nth sx 1)) (assert= (quote fn) (first (nth sx 2)))))) (defsuite "hs-handler-extensions" (deftest "render compiles to render-to-html" (let ((sx (hs-to-sx-from-source "render ~badge :label 'New'"))) (assert= (quote render-to-html) (first sx)) (assert= (quote ~badge) (nth sx 1)))) (deftest "eval inlines SX with variable access" (let ((h (hs-handler "set x to 10 then set y to eval (+ x 5)"))) (h "el") (assert= 15 y))) (deftest "eval as command in handler" (let ((h (hs-handler "eval (set! z 99)"))) (h "el") (assert= 99 z))))