(defisland () (let ((results (signal nil)) (running (signal false))) (letrec ((run-tests (fn () (reset! running true) (let ((script-el (dom-query "script[data-for]")) (test-results (list))) (when script-el (let ((test-src (host-get script-el "textContent")) (parsed (let ((raw (host-get script-el "textContent")) (decoded (host-call raw "replaceAll" "&quot;" "\""))) (sx-parse (host-call decoded "replaceAll" "&amp;" "&"))))) (for-each (fn (expr) (when (and (list? expr) (not (empty? expr)) (= (type-of (first expr)) "symbol")) (let ((head (symbol-name (first expr)))) (cond (= head "defsuite") (for-each (fn (child) (when (and (list? child) (not (empty? child)) (= (type-of (first child)) "symbol") (= (symbol-name (first child)) "deftest")) (append! test-results (try-test (nth child 1) (last child))))) (slice expr 2)) (= head "deftest") (append! test-results (try-test (nth expr 1) (last expr))))))) parsed))) (reset! results test-results) (reset! running false)))) (try-test (fn (name body) (let ((result (cek-try (fn () (eval-expr body (global-env)) true) (fn (err) err)))) (if (= result true) {:pass true :error nil :name name} {:pass false :error (str result) :name name}))))) (run-tests) (div (~tw :tokens "rounded border border-stone-200 bg-stone-50 p-4") (div (~tw :tokens "flex items-center justify-between mb-3") (h4 (~tw :tokens "text-sm font-semibold text-stone-700") "Tests") (button (~tw :tokens "px-2 py-1 text-xs rounded bg-stone-200 hover:bg-stone-300 transition") :on-click (fn (e) (run-tests)) "Re-run")) (if (deref running) (p (~tw :tokens "text-stone-400 text-sm italic") "Running...") (if (nil? (deref results)) (p (~tw :tokens "text-stone-400 text-sm italic") "No test source found") (let ((r (deref results)) (pass-count (len (filter (fn (t) (get t "pass")) r))) (fail-count (len (filter (fn (t) (not (get t "pass"))) r)))) (div (~tw :tokens "space-y-2") (div (~tw :tokens "text-sm font-mono") (span :class (if (= fail-count 0) "text-emerald-600 font-semibold" "text-red-600 font-semibold") (str pass-count "/" (len r) " passed"))) (map (fn (t) (div (~tw :tokens "flex items-start gap-2 text-xs font-mono py-0.5") (span :class (if (get t "pass") "text-emerald-500" "text-red-500") (if (get t "pass") "✓" "✗")) (span (~tw :tokens "text-stone-600") (get t "name")) (when (get t "error") (span (~tw :tokens "text-red-400 ml-2") (get t "error"))))) r)))))))))
