W14: C23 adapter-dom render-output tests (test-only) — section C complete

The DOM adapter's only test file asserts membership predicates ("if is a
render form") — zero tests inspect what render-to-dom actually builds
(hosts.md C23), and the file is excluded from the runner as browser-only.

Discovery: the browser-only assumption is false for render output —
(import (web adapter-dom)) disk-resolves in the OCaml runner and
render-to-dom works against its mock DOM. Add
web/tests/test-adapter-dom-render.sx (8 tests) pinning the adapter's real
output contract (probed first): text renders as a nodeType-3 child text
node; when/map wrap output in a FRAGMENT child; if inlines the chosen
branch; attrs/class/id land on the element; voids have no children.

Auto-included in default runs — first render-output coverage of the
1512-line adapter in the standard gate. Remaining depth (boolean attrs,
on-*/bind/ref/key, reactive attrs, hydration cursor) tracked on the
checklist. 254/0 standalone.

Test-only: no semantics edits, no push.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 02:55:26 +00:00
parent 53c0ec14da
commit bf5c238218
2 changed files with 111 additions and 1 deletions

View File

@@ -76,7 +76,10 @@ Pin each confirmed-and-fixed finding with a minimal repro. Add suites to
logging; 5 pins incl. the S10 map-over-perform probe (CEK keeps all
elements — the drop class is serving-JIT-side). Runner-only (needs
cek-* driver bindings)
- [ ] C23 — adapter-dom render-output tests
- [x] C23 — adapter-dom render-output tests
(`web/tests/test-adapter-dom-render.sx`, 8 tests vs runner mock DOM;
follow-up depth still open: boolean attrs, on-*/bind/ref/key,
reactive attrs, hydration cursor)
### D. WASM corpus runner
- [ ] F2 — promote conformance's `run_wasm.js` prototype into CI
@@ -91,6 +94,20 @@ Pin each confirmed-and-fixed finding with a minimal repro. Add suites to
## Progress log (newest first)
- 2026-07-04 — **C23 adapter-dom render-output tests (item C.4) — section C
COMPLETE**. Key discovery: the "browser-only" exclusion of adapter-dom
testing is FALSE for render output — `(import (web adapter-dom))`
disk-resolves in the OCaml runner and `render-to-dom` works against its
mock DOM (dom-* → host-* → mock elements). New
`web/tests/test-adapter-dom-render.sx` (8 tests): tag/text-child-node,
class+id, ordered children, void element, when-false empty FRAGMENT,
when-true branch-in-fragment, map N-children-in-fragment, if inlines
branch. Probed the adapter's output contract first (text = nodeType-3
child; control flow = FRAGMENT wrapper; if inlines). Auto-included in
default runs (not on the exclusion list) — first render-output coverage
of the 1512-line adapter in the standard gate. Follow-up depth (boolean
attrs, on-*/bind/ref/key, reactive, hydration) noted on the checklist.
254/0 standalone. Test-only.
- 2026-07-04 — **C21 perform-mode harness (item C.3)**. Added
`harness-run-perform` to spec/harness.sx (exported): drives
`make-cek-state`/`cek-step-loop`, services each

View File

@@ -0,0 +1,93 @@
;; ==========================================================================
;; test-adapter-dom-render.sx — C23 (W14): actual render-OUTPUT tests for
;; the DOM adapter. The pre-existing test-adapter-dom.sx asserts membership
;; predicates only ("if is a render form") — zero tests inspected what
;; render-to-dom actually builds, leaving the 1512-line adapter the
;; thinnest-tested relative to size (hosts.md C23).
;;
;; Runs against the OCaml runner's mock DOM (host-* primitives) through the
;; real (web adapter-dom) library, disk-resolved by import.
;;
;; Adapter output contract (probed 2026-07-04):
;; - text renders as a CHILD TEXT NODE (nodeType 3, textContent set);
;; the parent's own textContent prop stays "" in the mock
;; - control-flow forms (when/map/...) wrap their output in a FRAGMENT
;; child; `if` inlines the chosen branch directly
;; ==========================================================================
(import (web adapter-dom))
(defsuite
"adapter-dom-render-output"
(deftest
"simple element: tag, text child node"
(let
((el (render-to-dom (quote (div "hello")) (make-env))))
(assert= (dom-node-name el) "DIV")
(let
((kids (dom-get-prop el "children")))
(assert= (len kids) 1)
(assert= (dom-get-prop (first kids) "nodeType") 3)
(assert= (dom-text-content (first kids)) "hello"))))
(deftest
"class and id land on the element"
(let
((el (render-to-dom (quote (div :class "card" :id "main" "x")) (make-env))))
(assert= (dom-get-prop el "className") "card")
(assert
(or
(= (dom-get-prop el "id") "main")
(= (get (dom-get-prop el "attributes") "id") "main"))
"id not set as prop or attribute")))
(deftest
"nested children are appended in order"
(let
((el (render-to-dom (quote (ul (li "a") (li "b") (li "c"))) (make-env))))
(let
((kids (dom-get-prop el "children")))
(assert= (len kids) 3)
(assert= (dom-node-name (first kids)) "LI")
(assert=
(dom-text-content
(first (dom-get-prop (nth kids 2) "children")))
"c"))))
(deftest
"void element renders with no children"
(let
((el (render-to-dom (quote (input :type "text")) (make-env))))
(assert= (dom-node-name el) "INPUT")
(assert= (len (dom-get-prop el "children")) 0)))
(deftest
"when false yields an empty fragment"
(let
((el (render-to-dom (quote (div (when false (span "hidden")))) (make-env))))
(let
((kids (dom-get-prop el "children")))
(assert= (len kids) 1)
(assert= (dom-node-name (first kids)) "FRAGMENT")
(assert= (len (dom-get-prop (first kids) "children")) 0))))
(deftest
"when true renders the branch inside its fragment"
(let
((el (render-to-dom (quote (div (when true (span "shown")))) (make-env))))
(let
((frag (first (dom-get-prop el "children"))))
(assert= (dom-node-name frag) "FRAGMENT")
(assert=
(dom-node-name (first (dom-get-prop frag "children")))
"SPAN"))))
(deftest
"map render form produces one child per element inside its fragment"
(let
((el (render-to-dom (quote (ul (map (fn (x) (li x)) (list "1" "2" "3")))) (make-env))))
(let
((frag (first (dom-get-prop el "children"))))
(assert= (dom-node-name frag) "FRAGMENT")
(let
((items (dom-get-prop frag "children")))
(assert= (len items) 3)
(assert= (dom-node-name (first items)) "LI")))))
(deftest
"if render form inlines the chosen branch directly"
(let
((el (render-to-dom (quote (div (if true (b "yes") (i "no")))) (make-env))))
(assert= (dom-node-name (first (dom-get-prop el "children"))) "B"))))