;; lib/dream/tests/websocket.sx — upgrade, send/receive/close, broadcast. (define dream-ws-pass 0) (define dream-ws-fail 0) (define dream-ws-fails (list)) (define dream-ws-test (fn (name actual expected) (if (= actual expected) (set! dream-ws-pass (+ dream-ws-pass 1)) (begin (set! dream-ws-fail (+ dream-ws-fail 1)) (append! dream-ws-fails {:name name :actual actual :expected expected}))))) ;; ── upgrade response ─────────────────────────────────────────────── (define dream-ws-echo (fn (ws) (dream-text "unused"))) (define dream-ws-up ((dream-websocket dream-ws-echo) (dream-request "GET" "/ws" {} ""))) (dream-ws-test "upgrade status 101" (dream-status dream-ws-up) 101) (dream-ws-test "is a websocket response" (dream-websocket? dream-ws-up) true) (dream-ws-test "plain response is not ws" (dream-websocket? (dream-html "x")) false) (dream-ws-test "upgrade header" (dream-resp-header dream-ws-up "upgrade") "websocket") ;; ── basic send / receive / close on a mock ───────────────────────── (define dream-ws-w1 (dream-mock-ws (list "hi" "there"))) (dream-ws-test "open initially" (dream-ws-open? dream-ws-w1) true) (dream-ws-test "receive first" (dream-receive dream-ws-w1) "hi") (dream-ws-test "receive second" (dream-receive dream-ws-w1) "there") (dream-ws-test "receive empty -> nil" (dream-receive dream-ws-w1) nil) (dream-send dream-ws-w1 "out1") (dream-send dream-ws-w1 "out2") (dream-ws-test "sent recorded" (dream-ws-sent dream-ws-w1) (list "out1" "out2")) (dream-close dream-ws-w1) (dream-ws-test "closed flag" (dream-ws-closed? dream-ws-w1) true) (dream-ws-test "open? false after close" (dream-ws-open? dream-ws-w1) false) ;; ── echo handler driven over the upgrade response ────────────────── (define dream-ws-echo-h (fn (ws) (let ((m (dream-receive ws))) (if (nil? m) (dream-close ws) (begin (dream-send ws (str "echo:" m)) (dream-ws-echo-h ws)))))) (define dream-ws-echo-up ((dream-websocket dream-ws-echo-h) (dream-request "GET" "/ws" {} ""))) (define dream-ws-echo-conn (dream-mock-ws (list "a" "b" "c"))) (dream-ws-run dream-ws-echo-up dream-ws-echo-conn) (dream-ws-test "echo all messages" (dream-ws-sent dream-ws-echo-conn) (list "echo:a" "echo:b" "echo:c")) (dream-ws-test "echo closes at end" (dream-ws-closed? dream-ws-echo-conn) true) ;; ── broadcast to a room ──────────────────────────────────────────── (define dream-ws-c1 (dream-mock-ws (list))) (define dream-ws-c2 (dream-mock-ws (list))) (define dream-ws-c3 (dream-mock-ws (list))) (dream-ws-broadcast (list dream-ws-c1 dream-ws-c2 dream-ws-c3) "hello room") (dream-ws-test "broadcast c1" (dream-ws-sent dream-ws-c1) (list "hello room")) (dream-ws-test "broadcast c2" (dream-ws-sent dream-ws-c2) (list "hello room")) (dream-ws-test "broadcast c3" (dream-ws-sent dream-ws-c3) (list "hello room")) (define dream-ws-tests-run! (fn () {:total (+ dream-ws-pass dream-ws-fail) :passed dream-ws-pass :failed dream-ws-fail :fails dream-ws-fails}))