(defsuite "sx-swap:innerHTML" (deftest "replaces children of target" (let ((result (sx-swap "(div :id \"t\" (p \"old\"))" "innerHTML" "t" "(p \"new\")"))) (assert-equal result "(div :id \"t\" (p \"new\"))"))) (deftest "replaces multiple children" (let ((result (sx-swap "(div :id \"t\" (p \"a\") (p \"b\"))" "innerHTML" "t" "(span \"x\")"))) (assert-equal result "(div :id \"t\" (span \"x\"))"))) (deftest "handles nested target" (let ((result (sx-swap "(main (div :id \"t\" (p \"old\")))" "innerHTML" "t" "(p \"new\")"))) (assert-equal result "(main (div :id \"t\" (p \"new\")))"))) (deftest "preserves attrs" (let ((result (sx-swap "(div :id \"t\" :class \"box\" (p \"old\"))" "innerHTML" "t" "(p \"new\")"))) (assert-equal result "(div :id \"t\" :class \"box\" (p \"new\"))")))) (defsuite "sx-swap:outerHTML" (deftest "replaces entire element" (let ((result (sx-swap "(main (div :id \"t\" (p \"old\")) (footer \"f\"))" "outerHTML" "t" "(section \"new\")"))) (assert-equal result "(main (section \"new\") (footer \"f\"))"))) (deftest "replaces at root" (let ((result (sx-swap "(div :id \"t\" (p \"old\"))" "outerHTML" "t" "(span \"new\")"))) (assert-equal result "(span \"new\")")))) (defsuite "sx-swap:beforeend" (deftest "appends to children" (let ((result (sx-swap "(ul :id \"t\" (li \"a\"))" "beforeend" "t" "(li \"b\")"))) (assert-equal result "(ul :id \"t\" (li \"a\") (li \"b\"))"))) (deftest "appends to empty element" (let ((result (sx-swap "(div :id \"t\")" "beforeend" "t" "(p \"new\")"))) (assert-equal result "(div :id \"t\" (p \"new\"))")))) (defsuite "sx-swap:afterbegin" (deftest "prepends to children" (let ((result (sx-swap "(ul :id \"t\" (li \"b\"))" "afterbegin" "t" "(li \"a\")"))) (assert-equal result "(ul :id \"t\" (li \"a\") (li \"b\"))")))) (defsuite "sx-swap:beforebegin" (deftest "inserts before element" (let ((result (sx-swap "(div (p :id \"t\" \"x\"))" "beforebegin" "t" "(hr)"))) (assert-equal result "(div (hr)(p :id \"t\" \"x\"))")))) (defsuite "sx-swap:afterend" (deftest "inserts after element" (let ((result (sx-swap "(div (p :id \"t\" \"x\") (span \"y\"))" "afterend" "t" "(hr)"))) (assert-equal result "(div (p :id \"t\" \"x\")(hr) (span \"y\"))")))) (defsuite "sx-swap:delete" (deftest "removes element" (let ((result (sx-swap "(div (p :id \"t\" \"bye\") (p \"stay\"))" "delete" "t" ""))) (assert-true (contains? result "stay")) (assert-false (contains? result "bye"))))) (defsuite "sx-swap:none" (deftest "returns unchanged" (let ((page "(div :id \"t\" (p \"x\"))")) (assert-equal (sx-swap page "none" "t" "(p \"y\")") page)))) (defsuite "sx-swap:missing-target" (deftest "returns unchanged when id not found" (let ((page "(div :id \"other\" (p \"x\"))")) (assert-equal (sx-swap page "innerHTML" "missing" "(p \"y\")") page)))) (defsuite "sx-swap:oob" (deftest "finds oob elements" (let ((src "(<> (p \"main\") (div :id \"oob-t\" :sx-swap-oob \"innerHTML\" (p \"oob\")))")) (let ((oobs (find-oob-elements src))) (assert-equal (len oobs) 1) (assert-equal (get (first oobs) "id") "oob-t") (assert-equal (get (first oobs) "mode") "innerHTML")))) (deftest "strips oob from response" (let ((src "(<> (p \"main\") (div :id \"oob-t\" :sx-swap-oob \"innerHTML\" (p \"oob\")))")) (let ((oobs (find-oob-elements src))) (let ((main (strip-oob src oobs))) (assert-true (contains? main "main")) (assert-false (contains? main "oob-t")))))) (deftest "full pipeline applies primary + oob" (let ((page "(div (div :id \"a\" (p \"A old\")) (div :id \"b\" (p \"B old\")))") (response "(<> (p \"A new\") (div :id \"b\" :sx-swap-oob \"innerHTML\" (p \"B new\")))")) (let ((result (apply-response page response "innerHTML" "a"))) (assert-true (contains? result "A new")) (assert-true (contains? result "B new")) (assert-false (contains? result "A old")) (assert-false (contains? result "B old"))))))