(define (ahtml expr) (render-to-html expr {})) (define (ahtml-env expr env) (render-to-html expr env)) (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 "defcomp renders" (assert-true (string-contains? (ahtml (quote (begin (defcomp ~test-card (&key title) (div :class "card" (h2 title))) (~test-card :title "Hello")))) "Hello"))) (deftest "defcomp with children" (assert-true (string-contains? (ahtml (quote (begin (defcomp ~test-box (&rest children) (div :class "box" children)) (~test-box (p "inside"))))) "inside"))) (deftest "defcomp keyword and rest" (assert-true (string-contains? (ahtml (quote (begin (defcomp ~test-panel (&key heading &rest children) (section (h3 heading) children)) (~test-panel :heading "Title" (p "body"))))) "Title")))) (defsuite "adapter-html-lambda" (deftest "lambda call renders body" (assert-equal "ok" (ahtml (quote (let ((f (fn (x) (b x)))) (f "ok"))))))) (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 (ahtml (quote (begin (defisland ~test-counter (&key count) (span (str count))) (~test-counter :count 0)))))) (assert-true (string-contains? html "data-sx-island")) (assert-true (string-contains? html "test-counter")))) (deftest "island includes state" (let ((html (ahtml (quote (begin (defisland ~test-display (&key label) (span label)) (~test-display :label "hi")))))) (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-scope" (deftest "scope renders body" (assert-true (string-contains? (ahtml (quote (scope (p "scoped")))) "scoped"))) (deftest "provide renders body" (assert-true (string-contains? (ahtml (quote (provide "theme" "dark" (span "themed")))) "themed")))) (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))))))