;; ========================================================================== ;; test-engine.sx — Tests for SxEngine pure logic (engine.sx) ;; ;; Requires: test-framework.sx loaded first. ;; Platform functions: parse-time, parse-trigger-spec, default-trigger, ;; parse-swap-spec, parse-retry-spec, next-retry-ms, filter-params ;; (loaded from bootstrapped output by test runners) ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; 1. parse-time — time string parsing ;; -------------------------------------------------------------------------- (defsuite "parse-time" (deftest "seconds to ms" (assert-equal 2000 (parse-time "2s"))) (deftest "milliseconds" (assert-equal 500 (parse-time "500ms"))) (deftest "nil returns 0" (assert-equal 0 (parse-time nil))) (deftest "plain number string" (assert-equal 100 (parse-time "100"))) (deftest "one second" (assert-equal 1000 (parse-time "1s"))) (deftest "large seconds" (assert-equal 30000 (parse-time "30s")))) ;; -------------------------------------------------------------------------- ;; 2. parse-trigger-spec — trigger attribute parsing ;; -------------------------------------------------------------------------- (defsuite "parse-trigger-spec" (deftest "nil returns nil" (assert-nil (parse-trigger-spec nil))) (deftest "single event" (let ((triggers (parse-trigger-spec "click"))) (assert-equal 1 (len triggers)) (assert-equal "click" (get (first triggers) "event")))) (deftest "event with once modifier" (let ((triggers (parse-trigger-spec "click once"))) (assert-equal 1 (len triggers)) (assert-equal "click" (get (first triggers) "event")) (assert-true (get (get (first triggers) "modifiers") "once")))) (deftest "event with delay modifier" (let ((triggers (parse-trigger-spec "click delay:500ms"))) (assert-equal 1 (len triggers)) (assert-equal 500 (get (get (first triggers) "modifiers") "delay")))) (deftest "multiple triggers comma-separated" (let ((triggers (parse-trigger-spec "click,change"))) (assert-equal 2 (len triggers)) (assert-equal "click" (get (first triggers) "event")) (assert-equal "change" (get (nth triggers 1) "event")))) (deftest "polling trigger" (let ((triggers (parse-trigger-spec "every 3s"))) (assert-equal 1 (len triggers)) (assert-equal "every" (get (first triggers) "event")) (assert-equal 3000 (get (get (first triggers) "modifiers") "interval")))) (deftest "event with from modifier" (let ((triggers (parse-trigger-spec "click from:body"))) (assert-equal "body" (get (get (first triggers) "modifiers") "from")))) (deftest "event with changed modifier" (let ((triggers (parse-trigger-spec "keyup changed"))) (assert-equal "keyup" (get (first triggers) "event")) (assert-true (get (get (first triggers) "modifiers") "changed"))))) ;; -------------------------------------------------------------------------- ;; 3. default-trigger — default trigger by element tag ;; -------------------------------------------------------------------------- (defsuite "default-trigger" (deftest "form submits" (let ((triggers (default-trigger "FORM"))) (assert-equal "submit" (get (first triggers) "event")))) (deftest "input changes" (let ((triggers (default-trigger "INPUT"))) (assert-equal "change" (get (first triggers) "event")))) (deftest "select changes" (let ((triggers (default-trigger "SELECT"))) (assert-equal "change" (get (first triggers) "event")))) (deftest "textarea changes" (let ((triggers (default-trigger "TEXTAREA"))) (assert-equal "change" (get (first triggers) "event")))) (deftest "div clicks" (let ((triggers (default-trigger "DIV"))) (assert-equal "click" (get (first triggers) "event")))) (deftest "button clicks" (let ((triggers (default-trigger "BUTTON"))) (assert-equal "click" (get (first triggers) "event"))))) ;; -------------------------------------------------------------------------- ;; 4. parse-swap-spec — swap specification parsing ;; -------------------------------------------------------------------------- (defsuite "parse-swap-spec" (deftest "default swap" (let ((spec (parse-swap-spec nil false))) (assert-equal "outerHTML" (get spec "style")) (assert-false (get spec "transition")))) (deftest "innerHTML" (let ((spec (parse-swap-spec "innerHTML" false))) (assert-equal "innerHTML" (get spec "style")))) (deftest "with transition true" (let ((spec (parse-swap-spec "innerHTML transition:true" false))) (assert-equal "innerHTML" (get spec "style")) (assert-true (get spec "transition")))) (deftest "transition false overrides global" (let ((spec (parse-swap-spec "outerHTML transition:false" true))) (assert-equal "outerHTML" (get spec "style")) (assert-false (get spec "transition")))) (deftest "global transition when not overridden" (let ((spec (parse-swap-spec "innerHTML" true))) (assert-equal "innerHTML" (get spec "style")) (assert-true (get spec "transition"))))) ;; -------------------------------------------------------------------------- ;; 5. parse-retry-spec — retry specification parsing ;; -------------------------------------------------------------------------- (defsuite "parse-retry-spec" (deftest "nil returns nil" (assert-nil (parse-retry-spec nil))) (deftest "exponential backoff" (let ((spec (parse-retry-spec "exponential:1000:30000"))) (assert-equal "exponential" (get spec "strategy")) (assert-equal 1000 (get spec "start-ms")) (assert-equal 30000 (get spec "cap-ms")))) (deftest "linear strategy" (let ((spec (parse-retry-spec "linear:2000:60000"))) (assert-equal "linear" (get spec "strategy")) (assert-equal 2000 (get spec "start-ms")) (assert-equal 60000 (get spec "cap-ms"))))) ;; -------------------------------------------------------------------------- ;; 6. next-retry-ms — exponential backoff calculation ;; -------------------------------------------------------------------------- (defsuite "next-retry-ms" (deftest "doubles current" (assert-equal 2000 (next-retry-ms 1000 30000))) (deftest "caps at maximum" (assert-equal 30000 (next-retry-ms 20000 30000))) (deftest "exact cap" (assert-equal 30000 (next-retry-ms 15000 30000))) (deftest "small initial" (assert-equal 200 (next-retry-ms 100 30000)))) ;; -------------------------------------------------------------------------- ;; 7. filter-params — form parameter filtering ;; -------------------------------------------------------------------------- (defsuite "filter-params" (deftest "nil passes all through" (let ((params (list (list "a" "1") (list "b" "2")))) (assert-equal 2 (len (filter-params nil params))))) (deftest "none returns empty" (let ((params (list (list "a" "1") (list "b" "2")))) (assert-equal 0 (len (filter-params "none" params))))) (deftest "star passes all" (let ((params (list (list "a" "1") (list "b" "2")))) (assert-equal 2 (len (filter-params "*" params))))) (deftest "whitelist" (let ((params (list (list "name" "Jo") (list "age" "30") (list "secret" "x")))) (let ((filtered (filter-params "name,age" params))) (assert-equal 2 (len filtered))))) (deftest "blacklist with not" (let ((params (list (list "name" "Jo") (list "csrf" "tok") (list "age" "30")))) (let ((filtered (filter-params "not csrf" params))) (assert-equal 2 (len filtered))))))