Files
rose-ash/sx/sx/reactive-islands/test-temperature.sx
giles 5754a9ff9f Add inline test runner for temperature converter demo
Temperature converter tests (6 tests): initial value, computed
fahrenheit derivation, +5/-5 click handlers, reactive propagation,
multiple click accumulation.

New components:
- sx/sx/reactive-islands/test-runner.sx — reusable defisland that
  parses test source, runs defsuite/deftest forms via cek-eval, and
  displays pass/fail results with re-run button
- sx/sx/reactive-islands/test-temperature.sx — standalone test file

Added cek-try primitive to both browser (sx_browser.ml) and server
(sx_server.ml) for safe test execution with error catching.

Browser bundle now includes harness files (harness.sx,
harness-reactive.sx, harness-web.sx) for inline test execution.

Known: SSR renders test runner body instead of placeholder, causing
arity error on complex str expressions. Needs island SSR handling fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 01:00:07 +00:00

77 lines
2.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;; Tests for ~reactive-islands/index/demo-temperature
;;
;; Tests the reactive logic: signal creation, computed derivation,
;; button click handlers, and value propagation.
(defsuite "temperature converter"
(deftest "initial celsius is 20"
(let ((celsius (signal 20)))
(assert-signal-value celsius 20)))
(deftest "computed fahrenheit derives from celsius"
(let ((celsius (signal 20))
(fahrenheit (computed (fn () (+ (* (deref celsius) 1.8) 32)))))
(assert-signal-value fahrenheit 68)
(assert-computed-depends-on fahrenheit celsius)))
(deftest "+5 button increments celsius by 5"
(let ((celsius (signal 20))
(btn (mock-element "button")))
(mock-add-listener! btn "click"
(fn (e) (swap! celsius (fn (c) (+ c 5)))))
(simulate-click btn)
(assert-signal-value celsius 25)))
(deftest "5 button decrements celsius by 5"
(let ((celsius (signal 20))
(btn (mock-element "button")))
(mock-add-listener! btn "click"
(fn (e) (swap! celsius (fn (c) (- c 5)))))
(simulate-click btn)
(assert-signal-value celsius 15)))
(deftest "fahrenheit updates when celsius changes"
(let ((celsius (signal 20))
(fahrenheit (computed (fn () (+ (* (deref celsius) 1.8) 32)))))
(assert-signal-value fahrenheit 68)
(reset! celsius 25)
(assert-signal-value fahrenheit 77)
(reset! celsius 0)
(assert-signal-value fahrenheit 32)
(reset! celsius 100)
(assert-signal-value fahrenheit 212)))
(deftest "multiple clicks accumulate"
(let ((celsius (signal 20))
(fahrenheit (computed (fn () (+ (* (deref celsius) 1.8) 32))))
(plus-btn (mock-element "button"))
(minus-btn (mock-element "button")))
(mock-add-listener! plus-btn "click"
(fn (e) (swap! celsius (fn (c) (+ c 5)))))
(mock-add-listener! minus-btn "click"
(fn (e) (swap! celsius (fn (c) (- c 5)))))
;; +5 +5 +5
(simulate-click plus-btn)
(simulate-click plus-btn)
(simulate-click plus-btn)
(assert-signal-value celsius 35)
(assert-signal-value fahrenheit 95)
;; -5
(simulate-click minus-btn)
(assert-signal-value celsius 30)
(assert-signal-value fahrenheit 86)))
(deftest "celsius signal has subscribers after computed"
(let ((celsius (signal 20))
(fahrenheit (computed (fn () (+ (* (deref celsius) 1.8) 32)))))
(assert-signal-has-subscribers celsius)))
(deftest "click events are logged on mock element"
(let ((btn (mock-element "button")))
(mock-add-listener! btn "click" (fn (e) nil))
(simulate-click btn)
(simulate-click btn)
(assert-event-fired btn "click")
(assert= (event-fire-count btn "click") 2 "Expected 2 click events"))))