(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 "<b>" (ahtml ""))) (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 "
hello
" (ahtml (quote (div "hello"))))) (deftest "div with class" (assert-equal "
hi
" (ahtml (quote (div :class "card" "hi"))))) (deftest "nested elements" (assert-equal "
inner
" (ahtml (quote (div (span "inner")))))) (deftest "void element" (assert-true (starts-with? (ahtml (quote (br))) "
  • a
  • b
  • " (ahtml (quote (ul (li "a") (li "b"))))))) (defsuite "adapter-html-control-flow" (deftest "if true branch" (assert-equal "yes" (ahtml (quote (if true (b "yes") (i "no")))))) (deftest "if false branch" (assert-equal "no" (ahtml (quote (if false (b "yes") (i "no")))))) (deftest "when truthy renders body" (assert-equal "

    ok

    " (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 "hi" (ahtml (quote (let ((x "hi")) (span x)))))) (deftest "let multiple bindings" (assert-equal "
    AB
    " (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)))) "
  • a
  • "))) (deftest "for-each renders items" (assert-true (string-contains? (ahtml (quote (for-each (fn (x) (span x)) (list "x" "y")))) "x")))) (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 "ab" (ahtml (quote (<> (b "a") (i "b")))))) (deftest "empty fragment" (assert-equal "" (ahtml (quote (<>)))))) (defsuite "adapter-html-raw" (deftest "raw! passes through unescaped" (assert-equal "bold" (ahtml (quote (raw! "bold")))))) (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))))))