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>
77 lines
2.8 KiB
Plaintext
77 lines
2.8 KiB
Plaintext
;; 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"))))
|