Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 38s
booking-notify.sx walks the booking stream into ordered notifications by kind (booked/promoted/held/confirmed/released/cancelled/waitlisted). Promotion detected by folding the waitlist (a booking for a waitlisted actor is a promotion). id=occ-key/seq -> idempotent re-derivation, no double-ping. Connects ticketing to the delivery layer. 265/265 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
138 lines
4.3 KiB
Plaintext
138 lines
4.3 KiB
Plaintext
;; lib/events/tests/booking-notify.sx — lifecycle notifications from the stream.
|
|
|
|
(define ev-bn-pass 0)
|
|
(define ev-bn-fail 0)
|
|
(define ev-bn-failures (list))
|
|
|
|
(define
|
|
ev-bn-check!
|
|
(fn
|
|
(name got expected)
|
|
(if
|
|
(= got expected)
|
|
(set! ev-bn-pass (+ ev-bn-pass 1))
|
|
(do
|
|
(set! ev-bn-fail (+ ev-bn-fail 1))
|
|
(append!
|
|
ev-bn-failures
|
|
(str name "\n expected: " expected "\n got: " got))))))
|
|
|
|
(define
|
|
ev-bn-kinds
|
|
(fn
|
|
(notifs)
|
|
(map (fn (n) (list (get n :recipient) (get n :kind))) notifs)))
|
|
|
|
(define
|
|
ev-bn-run-all!
|
|
(fn
|
|
()
|
|
(do
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/book! b "o" 1 (quote a))
|
|
(ev/waitlist! b "o" 1 (quote x))
|
|
(ev/cancel-promote! b "o" 1 (quote a))
|
|
(let
|
|
((ns (ev/booking-notifications b "o" (quote yoga))))
|
|
(do
|
|
(ev-bn-check!
|
|
"lifecycle notifications in order"
|
|
(ev-bn-kinds ns)
|
|
(list
|
|
(list (quote a) :booked)
|
|
(list (quote x) :waitlisted)
|
|
(list (quote a) :cancelled)
|
|
(list (quote x) :promoted)))
|
|
(ev-bn-check!
|
|
"promotion targets the waitlisted actor"
|
|
(map
|
|
(fn (n) (get n :recipient))
|
|
(ev/notify-of-kind ns :promoted))
|
|
(list (quote x)))
|
|
(ev-bn-check!
|
|
"a fresh booking is not flagged as a promotion"
|
|
(len (ev/notify-of-kind ns :booked))
|
|
1)
|
|
(ev-bn-check!
|
|
"every notification carries the event label"
|
|
(get (first ns) :event)
|
|
(quote yoga))))))
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/hold! b "p" 3 (quote q))
|
|
(ev/confirm! b "p" (quote q))
|
|
(ev-bn-check!
|
|
"hold then confirm notifications"
|
|
(ev-bn-kinds (ev/booking-notifications b "p" (quote gig)))
|
|
(list (list (quote q) :held) (list (quote q) :confirmed)))))
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/hold! b "r" 1 (quote q))
|
|
(ev/release! b "r" (quote q))
|
|
(ev-bn-check!
|
|
"hold then release notifications"
|
|
(ev-bn-kinds (ev/booking-notifications b "r" (quote gig)))
|
|
(list (list (quote q) :held) (list (quote q) :released)))))
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/book! b "k" 5 (quote a))
|
|
(ev/book! b "k" 5 (quote c))
|
|
(let
|
|
((ns (ev/booking-notifications b "k" (quote talk))))
|
|
(do
|
|
(ev-bn-check!
|
|
"notification ids are occ-key/seq"
|
|
(map (fn (n) (get n :id)) ns)
|
|
(list "k/1" "k/2"))
|
|
(ev-bn-check!
|
|
"re-deriving yields identical ids (idempotent)"
|
|
(map
|
|
(fn (n) (get n :id))
|
|
(ev/booking-notifications b "k" (quote talk)))
|
|
(list "k/1" "k/2"))))))
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/book! b "w" 5 (quote a))
|
|
(ev-bn-check!
|
|
"notification projects to (id recipient body)"
|
|
(ev/booking-notify->msg
|
|
(first (ev/booking-notifications b "w" (quote talk))))
|
|
(list
|
|
"w/1"
|
|
(quote a)
|
|
(list :booking-event :booked (quote talk))))))
|
|
(let
|
|
((b (persist/open)))
|
|
(do
|
|
(ev/book! b "u" 1 (quote a))
|
|
(ev/waitlist! b "u" 1 (quote x))
|
|
(ev/leave-waitlist! b "u" (quote x))
|
|
(ev-bn-check!
|
|
"leaving the waitlist emits no notification"
|
|
(len
|
|
(ev/notify-of-kind
|
|
(ev/booking-notifications b "u" (quote e))
|
|
:left-waitlist))
|
|
0)
|
|
(ev-bn-check!
|
|
"unbooked occurrence has no notifications"
|
|
(ev/booking-notifications b "empty" (quote e))
|
|
(list)))))))
|
|
|
|
(define
|
|
ev-booking-notify-tests-run!
|
|
(fn
|
|
()
|
|
(do
|
|
(set! ev-bn-pass 0)
|
|
(set! ev-bn-fail 0)
|
|
(set! ev-bn-failures (list))
|
|
(ev-bn-run-all!)
|
|
{:failures ev-bn-failures :total (+ ev-bn-pass ev-bn-fail) :passed ev-bn-pass :failed ev-bn-fail})))
|