AtlatestRepositorysigil-web
1
;; Regression test for the live-stream SSE endpoint 500 ("car: expected pair").2
;;3
;; `stream-events-handler` called `http-response/sse-broadcast` while OMITTING4
;; the broadcast handler positional, relying on it defaulting to the identity5
;; function. That default only exists in the `. opts` form of6
;; `http-response/sse-broadcast` (sigil-http 0.16.7+). In releases 0.16.1–0.16.67
;; the signature was a `keys:` form with `handler` as a *required* positional;8
;; omitting it (and jumping to the `on-connect:` keyword) crashed the SSE connect9
;; with `type-error: car: expected pair` — a 500 on GET /feed. The fix passes the10
;; identity handler EXPLICITLY, which is valid for every release.11
;;12
;; NOTE: fully invoking the handler starts the lazy heartbeat via `(go ...)`,13
;; which needs a live scheduler and never terminates, so we can't drive it from14
;; a plain `sigil test`. Instead we pin the two things the fix actually depends15
;; on: (1) the exact `http-response/sse-broadcast` call SHAPE the handler now16
;; uses builds a well-formed streaming SSE response, and (2) `live-routes` wires17
;; a handler for both a stream and a collection. End-to-end proof (GET /feed ->18
;; 200 text/event-stream on a real server) is recorded in the task note.20
(import (sigil test)21
(sigil core)22
(sigil channels)23
(sigil web live)24
(sigil web routes)25
(sigil http request)26
(sigil http response))28
(test-group "live-stream SSE endpoint (regression: /feed 500)"29
;; This is the call shape stream-events-handler now emits. Under the keys-form30
;; sigil-http releases this exact shape is what avoids the "car: expected pair"31
;; crash (the handler positional is supplied); under the `. opts` form it is the32
;; identity handler, matching the previous default behaviour.33
(test "sse-broadcast with an explicit identity handler + on-connect: builds an SSE response"34
(let* ((hub (make-broadcast))35
(resp (http-response/sse-broadcast hub identity on-connect: #f)))36
(assert-true (http-response? resp))37
(assert-equal 200 (http-response-status resp))38
;; streaming responses carry a procedure body (write-chunk close) ...39
(assert-true (procedure? (http-response-body resp)))40
;; ... and advertise the SSE content type.41
(assert-equal "text/event-stream"42
(dict-ref (http-response-headers resp) content-type:))))44
(test "live-routes wires a handler for a plain stream"45
(let* ((feed (live-stream path: "/feed"))46
(app (live-routes feed)))47
(assert-true (procedure? app))))49
(test "live-routes wires a handler for a collection"50
(let* ((coll (live-collection render: (lambda (item) `(li ,(dict-ref item text:)))51
container: "#list" path: "/events"))52
(app (live-routes coll)))53
(assert-true (procedure? app)))))