Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m4s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
157 lines
6.1 KiB
Plaintext
157 lines
6.1 KiB
Plaintext
;; lib/dream/tests/session.sx — cookies, store, session round-trip.
|
|
|
|
(define dream-ss-pass 0)
|
|
(define dream-ss-fail 0)
|
|
(define dream-ss-fails (list))
|
|
|
|
(define
|
|
dream-ss-test
|
|
(fn
|
|
(name actual expected)
|
|
(if
|
|
(= actual expected)
|
|
(set! dream-ss-pass (+ dream-ss-pass 1))
|
|
(begin
|
|
(set! dream-ss-fail (+ dream-ss-fail 1))
|
|
(append! dream-ss-fails {:name name :actual actual :expected expected})))))
|
|
|
|
;; ── cookie parsing ─────────────────────────────────────────────────
|
|
(define dream-ss-creq (dream-request "GET" "/" {:Cookie "a=1; b=2; dream.session=s9"} ""))
|
|
(dream-ss-test "parse cookie a" (dream-cookie dream-ss-creq "a") "1")
|
|
(dream-ss-test "parse cookie b" (dream-cookie dream-ss-creq "b") "2")
|
|
(dream-ss-test
|
|
"parse session cookie"
|
|
(dream-cookie dream-ss-creq "dream.session")
|
|
"s9")
|
|
(dream-ss-test "missing cookie nil" (dream-cookie dream-ss-creq "z") nil)
|
|
(dream-ss-test
|
|
"no cookie header"
|
|
(dream-cookie (dream-request "GET" "/" {} "") "a")
|
|
nil)
|
|
|
|
;; ── cookie building ────────────────────────────────────────────────
|
|
(dream-ss-test
|
|
"build basic cookie"
|
|
(dr/build-cookie "k" "v" {})
|
|
"k=v; Path=/")
|
|
(dream-ss-test
|
|
"build httponly samesite"
|
|
(dr/build-cookie "sid" "x" {:http-only true :same-site "Lax"})
|
|
"sid=x; Path=/; HttpOnly; SameSite=Lax")
|
|
(dream-ss-test
|
|
"build max-age"
|
|
(dr/build-cookie "k" "v" {:max-age 0})
|
|
"k=v; Path=/; Max-Age=0")
|
|
(dream-ss-test
|
|
"set-cookie appends"
|
|
(len
|
|
(dream-resp-cookies
|
|
(dream-set-cookie (dream-html "x") "k" "v" {})))
|
|
1)
|
|
(dream-ss-test
|
|
"set-cookie two"
|
|
(len
|
|
(dream-resp-cookies
|
|
(dream-set-cookie
|
|
(dream-set-cookie (dream-html "x") "a" "1" {})
|
|
"b"
|
|
"2"
|
|
{})))
|
|
2)
|
|
(dream-ss-test
|
|
"drop cookie max-age 0"
|
|
(contains?
|
|
(first (dream-resp-cookies (dream-drop-cookie (dream-html "x") "k")))
|
|
"Max-Age=0")
|
|
true)
|
|
|
|
;; ── in-memory store ────────────────────────────────────────────────
|
|
(define dream-ss-store (dream-memory-sessions))
|
|
(define dream-ss-sid (dream-ss-store {:op "session/create"}))
|
|
(dream-ss-test "create returns id" dream-ss-sid "s1")
|
|
(dream-ss-test "new session exists" (dream-ss-store {:op "session/exists" :sid "s1"}) true)
|
|
(dream-ss-test "absent session not exists" (dream-ss-store {:op "session/exists" :sid "s99"}) false)
|
|
(dream-ss-test "get missing key nil" (dream-ss-store {:key "k" :op "session/get" :sid "s1"}) nil)
|
|
(dream-ss-store {:val "ada" :key "user" :op "session/set" :sid "s1"})
|
|
(dream-ss-test "set then get" (dream-ss-store {:key "user" :op "session/get" :sid "s1"}) "ada")
|
|
(dream-ss-store {:val "admin" :key "role" :op "session/set" :sid "s1"})
|
|
(dream-ss-test "load all fields" (dream-ss-store {:op "session/load" :sid "s1"}) {:role "admin" :user "ada"})
|
|
(dream-ss-test "second create distinct" (dream-ss-store {:op "session/create"}) "s2")
|
|
(dream-ss-store {:op "session/clear" :sid "s1"})
|
|
(dream-ss-test "clear removes" (dream-ss-store {:op "session/exists" :sid "s1"}) false)
|
|
|
|
;; ── middleware round-trip ──────────────────────────────────────────
|
|
(define dream-ss-backend (dream-memory-sessions))
|
|
(define
|
|
dream-ss-counter-h
|
|
(fn
|
|
(req)
|
|
(let
|
|
((n (or (dream-session-field req "count") 0)))
|
|
(begin
|
|
(dream-set-session-field req "count" (+ n 1))
|
|
(dream-text (str "count=" (+ n 1)))))))
|
|
(define dream-ss-app ((dream-sessions dream-ss-backend) dream-ss-counter-h))
|
|
|
|
;; first request: no cookie -> creates session, sets cookie
|
|
(define dream-ss-r1 (dream-ss-app (dream-request "GET" "/" {} "")))
|
|
(dream-ss-test "first body count=1" (dream-resp-body dream-ss-r1) "count=1")
|
|
(dream-ss-test
|
|
"first sets one cookie"
|
|
(len (dream-resp-cookies dream-ss-r1))
|
|
1)
|
|
(dream-ss-test
|
|
"session cookie name+id"
|
|
(contains? (first (dream-resp-cookies dream-ss-r1)) "dream.session=s1")
|
|
true)
|
|
(dream-ss-test
|
|
"session cookie httponly"
|
|
(contains? (first (dream-resp-cookies dream-ss-r1)) "HttpOnly")
|
|
true)
|
|
|
|
;; second request: carries the cookie -> reuses, sees prior count, no new cookie
|
|
(define dream-ss-r2 (dream-ss-app (dream-request "GET" "/" {:Cookie "dream.session=s1"} "")))
|
|
(dream-ss-test "second body count=2" (dream-resp-body dream-ss-r2) "count=2")
|
|
(dream-ss-test
|
|
"second sets no cookie"
|
|
(len (dream-resp-cookies dream-ss-r2))
|
|
0)
|
|
|
|
;; third request continues
|
|
(define dream-ss-r3 (dream-ss-app (dream-request "GET" "/" {:Cookie "dream.session=s1"} "")))
|
|
(dream-ss-test "third body count=3" (dream-resp-body dream-ss-r3) "count=3")
|
|
|
|
;; unknown cookie id -> fresh session created
|
|
(define dream-ss-r4 (dream-ss-app (dream-request "GET" "/" {:Cookie "dream.session=bogus"} "")))
|
|
(dream-ss-test
|
|
"bogus id starts fresh"
|
|
(dream-resp-body dream-ss-r4)
|
|
"count=1")
|
|
(dream-ss-test
|
|
"bogus id gets new cookie"
|
|
(len (dream-resp-cookies dream-ss-r4))
|
|
1)
|
|
|
|
;; ── session-all + invalidate via middleware ────────────────────────
|
|
(define
|
|
dream-ss-inspect-h
|
|
(fn (req) (dream-text (str (dream-session-all req)))))
|
|
(define dream-ss-app2 ((dream-sessions dream-ss-backend) dream-ss-inspect-h))
|
|
(define dream-ss-r5 (dream-ss-app2 (dream-request "GET" "/" {:Cookie "dream.session=s1"} "")))
|
|
(dream-ss-test
|
|
"session-all shows count"
|
|
(dream-session-all
|
|
(assoc (dream-request "GET" "/" {} "") :dream-session {:io dream-ss-backend :sid "s1"}))
|
|
{:count 3})
|
|
|
|
(define
|
|
dream-ss-invalidate-h
|
|
(fn (req) (begin (dream-invalidate-session req) (dream-text "bye"))))
|
|
(define
|
|
dream-ss-app3
|
|
((dream-sessions dream-ss-backend) dream-ss-invalidate-h))
|
|
(dream-ss-app3 (dream-request "GET" "/" {:Cookie "dream.session=s1"} ""))
|
|
(dream-ss-test "invalidate clears store" (dream-ss-backend {:op "session/exists" :sid "s1"}) false)
|
|
|
|
(define dream-ss-tests-run! (fn () {:total (+ dream-ss-pass dream-ss-fail) :passed dream-ss-pass :failed dream-ss-fail :fails dream-ss-fails}))
|