Files
rose-ash/web/tests/test-adapter-html.sx
giles 1dd7c22201 Fix &rest param binding in OCaml evaluator + clean test suite: 0 failures
OCaml evaluator: has_rest_param and bind_lambda_params checked for
String "&rest" but the parser produces Symbol "&rest". Both forms now
accepted. Fixes swap! extra args (signal 10 → swap! s + 5 → 15).

test-adapter-html.sx: fix define shorthand → explicit fn form, move
defcomp/defisland to top level with (test-env) for component resolution.

2515 passed, 0 failed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:41:13 +00:00

210 lines
6.1 KiB
Plaintext

(define ahtml (fn (expr) (render-to-html expr {})))
(defcomp ~ahtml-card (&key title) (div :class "card" (h2 title)))
(defcomp ~ahtml-box (&rest children) (div :class "box" children))
(defcomp
~ahtml-panel
(&key heading &rest children)
(section (h3 heading) children))
(defisland ~ahtml-counter (&key count) (span (str count)))
(defisland ~ahtml-display (&key label) (span label))
(defsuite
"adapter-html-basics"
(deftest "nil renders empty" (assert-equal "" (ahtml nil)))
(deftest "string escapes html" (assert-equal "&lt;b&gt;" (ahtml "<b>")))
(deftest "number renders as string" (assert-equal "42" (ahtml 42)))
(deftest
"boolean renders"
(assert-equal "true" (ahtml true))
(assert-equal "false" (ahtml false)))
(deftest "keyword renders name" (assert-equal "foo" (ahtml :foo))))
(defsuite
"adapter-html-elements"
(deftest
"div with text"
(assert-equal "<div>hello</div>" (ahtml (quote (div "hello")))))
(deftest
"div with class"
(assert-equal
"<div class=\"card\">hi</div>"
(ahtml (quote (div :class "card" "hi")))))
(deftest
"nested elements"
(assert-equal
"<div><span>inner</span></div>"
(ahtml (quote (div (span "inner"))))))
(deftest
"void element"
(assert-true (starts-with? (ahtml (quote (br))) "<br")))
(deftest
"input void with attrs"
(assert-true
(string-contains?
(ahtml (quote (input :type "text" :name "q")))
"type=\"text\"")))
(deftest
"multiple children"
(assert-equal
"<ul><li>a</li><li>b</li></ul>"
(ahtml (quote (ul (li "a") (li "b")))))))
(defsuite
"adapter-html-control-flow"
(deftest
"if true branch"
(assert-equal
"<b>yes</b>"
(ahtml (quote (if true (b "yes") (i "no"))))))
(deftest
"if false branch"
(assert-equal
"<i>no</i>"
(ahtml (quote (if false (b "yes") (i "no"))))))
(deftest
"when truthy renders body"
(assert-equal "<p>ok</p>" (ahtml (quote (when true (p "ok"))))))
(deftest
"when falsy renders empty"
(assert-equal "" (ahtml (quote (when false (p "no")))))))
(defsuite
"adapter-html-let"
(deftest
"let binds and renders"
(assert-equal
"<span>hi</span>"
(ahtml (quote (let ((x "hi")) (span x))))))
(deftest
"let multiple bindings"
(assert-equal
"<div>AB</div>"
(ahtml (quote (let ((a "A") (b "B")) (div (begin a b))))))))
(defsuite
"adapter-html-map"
(deftest
"map renders each item"
(assert-true
(string-contains?
(ahtml
(quote
(let
((items (list "a" "b" "c")))
(map (fn (x) (li x)) items))))
"<li>a</li>")))
(deftest
"for-each renders items"
(assert-true
(string-contains?
(ahtml (quote (for-each (fn (x) (span x)) (list "x" "y"))))
"<span>x</span>"))))
(defsuite
"adapter-html-components"
(deftest
"component with kwargs renders"
(let
((html (render-to-html (quote (~ahtml-card :title "Hello")) (test-env))))
(assert-true (string-contains? html "Hello"))
(assert-true (string-contains? html "card"))))
(deftest
"component with children renders"
(let
((html (render-to-html (quote (~ahtml-box (p "inside"))) (test-env))))
(assert-true (string-contains? html "inside"))
(assert-true (string-contains? html "box"))))
(deftest
"component with keyword and rest"
(let
((html (render-to-html (quote (~ahtml-panel :heading "Title" (p "body"))) (test-env))))
(assert-true (string-contains? html "Title"))
(assert-true (string-contains? html "body")))))
(defsuite
"adapter-html-fragments"
(deftest
"fragment renders children"
(assert-equal "<b>a</b><i>b</i>" (ahtml (quote (<> (b "a") (i "b"))))))
(deftest "empty fragment" (assert-equal "" (ahtml (quote (<>))))))
(defsuite
"adapter-html-raw"
(deftest
"raw! passes through unescaped"
(assert-equal "<b>bold</b>" (ahtml (quote (raw! "<b>bold</b>"))))))
(defsuite
"adapter-html-render-form-predicate"
(deftest "if is a render form" (assert-true (render-html-form? "if")))
(deftest "when is a render form" (assert-true (render-html-form? "when")))
(deftest "map is a render form" (assert-true (render-html-form? "map")))
(deftest
"div is not a render form"
(assert-false (render-html-form? "div")))
(deftest
"scope is a render form"
(assert-true (render-html-form? "scope")))
(deftest
"provide is a render form"
(assert-true (render-html-form? "provide"))))
(defsuite
"adapter-html-serialize-island-state"
(deftest
"empty dict returns nil"
(assert-nil (serialize-island-state {})))
(deftest
"non-empty dict returns sx string"
(let
((result (serialize-island-state {:count 0})))
(assert-true (string? result))
(assert-true (string-contains? result "count")))))
(defsuite
"adapter-html-islands"
(deftest
"island renders with data attributes"
(let
((html (render-to-html (quote (~ahtml-counter :count 0)) (test-env))))
(assert-true (string-contains? html "data-sx-island"))
(assert-true (string-contains? html "ahtml-counter"))))
(deftest
"island includes state"
(let
((html (render-to-html (quote (~ahtml-display :label "hi")) (test-env))))
(assert-true (string-contains? html "data-sx-state"))
(assert-true (string-contains? html "label")))))
(defsuite
"adapter-html-lakes"
(deftest
"lake renders with data attribute"
(let
((html (ahtml (quote (lake :id "my-lake" (p "content"))))))
(assert-true (string-contains? html "data-sx-lake"))
(assert-true (string-contains? html "content")))))
(defsuite
"adapter-html-marshes"
(deftest
"marsh renders with data attribute"
(let
((html (ahtml (quote (marsh :id "my-marsh" (p "data"))))))
(assert-true (string-contains? html "data-sx-marsh"))
(assert-true (string-contains? html "data")))))
(defsuite
"adapter-html-definitions"
(deftest
"define renders empty"
(assert-equal "" (ahtml (quote (define test-val 42)))))
(deftest
"defmacro renders empty"
(assert-equal "" (ahtml (quote (defmacro test-m (x) x))))))