;; lib/dream/tests/flash.sx — codec + read-after-write across requests. (define dream-fl-pass 0) (define dream-fl-fail 0) (define dream-fl-fails (list)) (define dream-fl-test (fn (name actual expected) (if (= actual expected) (set! dream-fl-pass (+ dream-fl-pass 1)) (begin (set! dream-fl-fail (+ dream-fl-fail 1)) (append! dream-fl-fails {:name name :actual actual :expected expected}))))) ;; ── codec ────────────────────────────────────────────────────────── (dream-fl-test "encode one" (dr/flash-encode (list {:message "saved" :category "info"})) "info|saved") (dream-fl-test "encode two" (dr/flash-encode (list {:message "a" :category "info"} {:message "b" :category "error"})) "info|a~error|b") (dream-fl-test "decode one" (dr/flash-decode "info|saved") (list {:message "saved" :category "info"})) (dream-fl-test "decode empty" (dr/flash-decode "") (list)) (dream-fl-test "roundtrip special chars" (dr/flash-decode (dr/flash-encode (list {:message "a~b%c" :category "x|y"}))) (list {:message "a~b%c" :category "x|y"})) (dream-fl-test "escape pipe" (dr/flash-encode (list {:message "a|b" :category "c"})) "c|a%7Cb") ;; extract a cookie value from a Set-Cookie string (define dream-fl-cookie-val (fn (setc) (let ((after (substr setc (+ (index-of setc "=") 1)))) (substr after 0 (index-of after ";"))))) ;; ── read-after-write across requests ─────────────────────────────── (define dream-fl-set-h (fn (req) (begin (dream-add-flash-message req "info" "Saved!") (dream-text "done")))) (define dream-fl-set-app (dream-flash dream-fl-set-h)) ;; request 1: add a flash, no incoming -> sets the flash cookie (define dream-fl-r1 (dream-fl-set-app (dream-request "POST" "/save" {} ""))) (dream-fl-test "writer body" (dream-resp-body dream-fl-r1) "done") (dream-fl-test "writer sets flash cookie" (len (dream-resp-cookies dream-fl-r1)) 1) (dream-fl-test "writer has no incoming" (dream-flash-messages (assoc (dream-request "GET" "/" {} "") :dream-flash {:box (dr/flash-box) :incoming (list)})) (list)) ;; request 2: carries the flash cookie -> handler reads it, cookie cleared (define dream-fl-cval (dream-fl-cookie-val (first (dream-resp-cookies dream-fl-r1)))) (define dream-fl-read-h (fn (req) (let ((msgs (dream-flash-messages req))) (dream-text (if (empty? msgs) "none" (dream-flash-message (first msgs))))))) (define dream-fl-read-app (dream-flash dream-fl-read-h)) (define dream-fl-r2 (dream-fl-read-app (dream-request "GET" "/" {:Cookie (str "dream.flash=" dream-fl-cval)} ""))) (dream-fl-test "reader sees message" (dream-resp-body dream-fl-r2) "Saved!") (dream-fl-test "reader clears cookie (Max-Age=0)" (contains? (first (dream-resp-cookies dream-fl-r2)) "Max-Age=0") true) ;; request 3: no flash cookie -> nothing to read, no cookie set (define dream-fl-r3 (dream-fl-read-app (dream-request "GET" "/" {} ""))) (dream-fl-test "no flash -> none" (dream-resp-body dream-fl-r3) "none") (dream-fl-test "no flash -> no cookie" (len (dream-resp-cookies dream-fl-r3)) 0) ;; ── multiple categories ──────────────────────────────────────────── (define dream-fl-multi-h (fn (req) (begin (dream-add-flash-message req "info" "i1") (dream-add-flash-message req "error" "e1") (dream-add-flash-message req "info" "i2") (dream-text "ok")))) (define dream-fl-multi-r1 ((dream-flash dream-fl-multi-h) (dream-request "GET" "/" {} ""))) (define dream-fl-multi-val (dream-fl-cookie-val (first (dream-resp-cookies dream-fl-multi-r1)))) (define dream-fl-count-h (fn (req) (dream-text (str (len (dream-flash-messages req)) "/" (len (dream-flash-of req "info")))))) (define dream-fl-multi-r2 ((dream-flash dream-fl-count-h) (dream-request "GET" "/" {:Cookie (str "dream.flash=" dream-fl-multi-val)} ""))) (dream-fl-test "multi: all + filtered counts" (dream-resp-body dream-fl-multi-r2) "3/2") (define dream-fl-tests-run! (fn () {:total (+ dream-fl-pass dream-fl-fail) :passed dream-fl-pass :failed dream-fl-fail :fails dream-fl-fails}))