;; ========================================================================== ;; test-render.sx — Tests for the HTML rendering adapter ;; ;; Requires: test-framework.sx loaded first. ;; Modules tested: render.sx, adapter-html.sx ;; ;; Platform functions required (beyond test framework): ;; render-html (sx-source) -> HTML string ;; Parses the sx-source string, evaluates via render-to-html in a ;; fresh env, and returns the resulting HTML string. ;; (This is a test-only convenience that wraps parse + render-to-html.) ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; Basic element rendering ;; -------------------------------------------------------------------------- (defsuite "render-elements" (deftest "simple div" (assert-equal "
hello
" (render-html "(div \"hello\")"))) (deftest "nested elements" (assert-equal "
hi
" (render-html "(div (span \"hi\"))"))) (deftest "multiple children" (assert-equal "

a

b

" (render-html "(div (p \"a\") (p \"b\"))"))) (deftest "text content" (assert-equal "

hello world

" (render-html "(p \"hello\" \" world\")"))) (deftest "number content" (assert-equal "42" (render-html "(span 42)")))) ;; -------------------------------------------------------------------------- ;; Attributes ;; -------------------------------------------------------------------------- (defsuite "render-attrs" (deftest "string attribute" (let ((html (render-html "(div :id \"main\" \"content\")"))) (assert-true (string-contains? html "id=\"main\"")) (assert-true (string-contains? html "content")))) (deftest "class attribute" (let ((html (render-html "(div :class \"foo bar\" \"x\")"))) (assert-true (string-contains? html "class=\"foo bar\"")))) (deftest "multiple attributes" (let ((html (render-html "(a :href \"/home\" :class \"link\" \"Home\")"))) (assert-true (string-contains? html "href=\"/home\"")) (assert-true (string-contains? html "class=\"link\"")) (assert-true (string-contains? html "Home"))))) ;; -------------------------------------------------------------------------- ;; Void elements ;; -------------------------------------------------------------------------- (defsuite "render-void" (deftest "br is self-closing" (assert-equal "
" (render-html "(br)"))) (deftest "img with attrs" (let ((html (render-html "(img :src \"pic.jpg\" :alt \"A pic\")"))) (assert-true (string-contains? html "")) ;; void elements should not have a closing tag (assert-false (string-contains? html "")))) (deftest "input is self-closing" (let ((html (render-html "(input :type \"text\" :name \"q\")"))) (assert-true (string-contains? html ""))))) ;; -------------------------------------------------------------------------- ;; Boolean attributes ;; -------------------------------------------------------------------------- (defsuite "render-boolean-attrs" (deftest "true boolean attr emits name only" (let ((html (render-html "(input :disabled true :type \"text\")"))) (assert-true (string-contains? html "disabled")) ;; Should NOT have disabled="true" (assert-false (string-contains? html "disabled=\"")))) (deftest "false boolean attr omitted" (let ((html (render-html "(input :disabled false :type \"text\")"))) (assert-false (string-contains? html "disabled"))))) ;; -------------------------------------------------------------------------- ;; Fragments ;; -------------------------------------------------------------------------- (defsuite "render-fragments" (deftest "fragment renders children without wrapper" (assert-equal "

a

b

" (render-html "(<> (p \"a\") (p \"b\"))"))) (deftest "empty fragment" (assert-equal "" (render-html "(<>)")))) ;; -------------------------------------------------------------------------- ;; HTML escaping ;; -------------------------------------------------------------------------- (defsuite "render-escaping" (deftest "text content is escaped" (let ((html (render-html "(p \"\")"))) (assert-false (string-contains? html "