dream: hello + counter demos + 10 end-to-end tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m6s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 14:54:46 +00:00
parent 2b42aabe6b
commit 2551109ffa
5 changed files with 147 additions and 5 deletions

View File

@@ -31,6 +31,8 @@ MODULES=(
"lib/dream/websocket.sx"
"lib/dream/static.sx"
"lib/dream/run.sx"
"lib/dream/demos/hello.sx"
"lib/dream/demos/counter.sx"
)
# Suites: NAME RUNNER-FN PATH
@@ -44,6 +46,7 @@ SUITES=(
"websocket dream-ws-tests-run! lib/dream/tests/websocket.sx"
"static dream-st-tests-run! lib/dream/tests/static.sx"
"run dream-rn-tests-run! lib/dream/tests/run.sx"
"demos dream-dm-tests-run! lib/dream/tests/demos.sx"
)
TMPFILE=$(mktemp); trap "rm -f $TMPFILE" EXIT

View File

@@ -0,0 +1,35 @@
;; lib/dream/demos/counter.sx — per-session visit counter (counter.ml).
;; Demonstrates the session middleware: each browser session keeps its own count.
(define
dream-counter-handler
(fn
(req)
(let
((n (+ 1 (or (dream-session-field req "count") 0))))
(begin
(dream-set-session-field req "count" n)
(dream-html (str "<p>You have visited this page " n " time(s).</p>"))))))
;; reset clears the session counter
(define
dream-counter-reset
(fn
(req)
(begin
(dream-set-session-field req "count" 0)
(dream-redirect "/"))))
(define
dream-counter-app-with
(fn
(backend)
((dream-sessions backend)
(dream-router
(list
(dream-get "/" dream-counter-handler)
(dream-post "/reset" dream-counter-reset))))))
(define dream-counter-app (dream-counter-app-with (dream-memory-sessions)))
;; entry point: (dream-run (dream-counter-app-with (dream-memory-sessions)))

16
lib/dream/demos/hello.sx Normal file
View File

@@ -0,0 +1,16 @@
;; lib/dream/demos/hello.sx — the canonical Dream "Hello, World!" (hello.ml).
;; Dream.run (Dream.router [Dream.get "/" (fun _ -> Dream.html "Hello!")]).
(define
dream-hello-app
(dream-router
(list
(dream-get "/" (fn (req) (dream-html "<h1>Hello, World!</h1>")))
(dream-get
"/hello/:name"
(fn
(req)
(dream-html (str "<h1>Hello, " (dream-param req "name") "!</h1>")))))))
;; entry point (installs the handler on the host):
;; (dream-run dream-hello-app)

83
lib/dream/tests/demos.sx Normal file
View File

@@ -0,0 +1,83 @@
;; lib/dream/tests/demos.sx — end-to-end demo apps exercising the full stack.
(define dream-dm-pass 0)
(define dream-dm-fail 0)
(define dream-dm-fails (list))
(define
dream-dm-test
(fn
(name actual expected)
(if
(= actual expected)
(set! dream-dm-pass (+ dream-dm-pass 1))
(begin
(set! dream-dm-fail (+ dream-dm-fail 1))
(append! dream-dm-fails {:name name :actual actual :expected expected})))))
(define
dream-dm-req
(fn (method target headers) (dream-request method target headers "")))
;; ── hello ──────────────────────────────────────────────────────────
(dream-dm-test
"hello root"
(dream-resp-body (dream-hello-app (dream-dm-req "GET" "/" {})))
"<h1>Hello, World!</h1>")
(dream-dm-test
"hello name"
(dream-resp-body
(dream-hello-app (dream-dm-req "GET" "/hello/Ada" {})))
"<h1>Hello, Ada!</h1>")
(dream-dm-test
"hello content-type"
(dream-resp-header
(dream-hello-app (dream-dm-req "GET" "/" {}))
"content-type")
"text/html; charset=utf-8")
;; ── counter (sessions) ─────────────────────────────────────────────
(define dream-dm-cbackend (dream-memory-sessions))
(define dream-dm-capp (dream-counter-app-with dream-dm-cbackend))
;; first visit: no cookie -> count 1, session cookie set
(define dream-dm-c1 (dream-dm-capp (dream-dm-req "GET" "/" {})))
(dream-dm-test
"counter first visit"
(dream-resp-body dream-dm-c1)
"<p>You have visited this page 1 time(s).</p>")
(dream-dm-test
"counter sets cookie"
(len (dream-resp-cookies dream-dm-c1))
1)
;; subsequent visits with the cookie increment
(dream-dm-test
"counter second visit"
(dream-resp-body (dream-dm-capp (dream-dm-req "GET" "/" {:Cookie "dream.session=s1"})))
"<p>You have visited this page 2 time(s).</p>")
(dream-dm-test
"counter third visit"
(dream-resp-body (dream-dm-capp (dream-dm-req "GET" "/" {:Cookie "dream.session=s1"})))
"<p>You have visited this page 3 time(s).</p>")
;; reset zeroes the counter then redirects
(define
dream-dm-reset
(dream-dm-capp (dream-dm-req "POST" "/reset" {:Cookie "dream.session=s1"})))
(dream-dm-test
"counter reset redirects"
(dream-status dream-dm-reset)
303)
(dream-dm-test
"counter after reset"
(dream-resp-body (dream-dm-capp (dream-dm-req "GET" "/" {:Cookie "dream.session=s1"})))
"<p>You have visited this page 1 time(s).</p>")
;; a different session is independent
(dream-dm-test
"counter distinct session"
(dream-resp-body (dream-dm-capp (dream-dm-req "GET" "/" {})))
"<p>You have visited this page 1 time(s).</p>")
(define dream-dm-tests-run! (fn () {:total (+ dream-dm-pass dream-dm-fail) :passed dream-dm-pass :failed dream-dm-fail :fails dream-dm-fails}))