Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 16s
Blog posts now live in the durable SX store (persist/durable-backend, on-disk under $SX_PERSIST_DIR — already built: sx_persist_store.ml + lib/persist/ durable.sx). Publishing appends insert ops to the slug's content stream; posts survive restarts (verified: seq/log stable across container restart, re-seed idempotent). Read path: http-listen handlers can't drive per-request perform/IO (sx_call doesn't resolve the CEK IO suspension the way the main loop does), so posts are materialised from the store into an in-memory view at boot (host/blog-load-all! + host/blog-seed!) and request handlers read the view — perform-free. Store is source of truth; view is a boot-rebuilt cache. Deploy: docker-compose.dev-sx-host.yml mounts /root/sx-host-persist (chowned to appuser 10001) at /data/persist; SX_PERSIST_DIR set. blog.rose-ash.com/welcome/ live. Per-request-IO kernel fix tracked in the plan as the next task. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
92 lines
3.1 KiB
Plaintext
92 lines
3.1 KiB
Plaintext
;; lib/host/tests/blog.sx — the blog published-post read endpoint. A registered
|
|
;; post renders to HTML at GET /<slug>/; unknown slugs 404. Also pins route
|
|
;; precedence: the catch-all :slug must NOT shadow domain routes mounted before it.
|
|
|
|
(define host-bl-pass 0)
|
|
(define host-bl-fail 0)
|
|
(define host-bl-fails (list))
|
|
|
|
(define
|
|
host-bl-test
|
|
(fn
|
|
(name actual expected)
|
|
(if
|
|
(= actual expected)
|
|
(set! host-bl-pass (+ host-bl-pass 1))
|
|
(begin
|
|
(set! host-bl-fail (+ host-bl-fail 1))
|
|
(append! host-bl-fails {:name name :actual actual :expected expected})))))
|
|
|
|
(define host-bl-req (fn (target) (dream-request "GET" target {} "")))
|
|
;; feed mounted BEFORE blog so /feed is not captured by the :slug catch-all.
|
|
(define host-bl-app
|
|
(host/make-app (list host/feed-routes host/blog-routes)))
|
|
|
|
;; ── publish a post to a fresh in-memory store (hermetic) ────────────
|
|
(host/blog-use-store! (persist/open))
|
|
(host/blog-publish! "welcome" "Hello SX" "Served by lib/host." 1)
|
|
|
|
(host-bl-test
|
|
"post 200"
|
|
(dream-status (host-bl-app (host-bl-req "/welcome/")))
|
|
200)
|
|
(host-bl-test
|
|
"post content-type html"
|
|
(contains? (dream-resp-header (host-bl-app (host-bl-req "/welcome/")) "content-type") "text/html")
|
|
true)
|
|
(host-bl-test
|
|
"post renders heading"
|
|
(contains? (dream-resp-body (host-bl-app (host-bl-req "/welcome/"))) "<h1>Hello SX</h1>")
|
|
true)
|
|
(host-bl-test
|
|
"post renders body"
|
|
(contains? (dream-resp-body (host-bl-app (host-bl-req "/welcome/"))) "Served by lib/host.")
|
|
true)
|
|
;; trailing slash optional — /welcome and /welcome/ both resolve
|
|
(host-bl-test
|
|
"no trailing slash also 200"
|
|
(dream-status (host-bl-app (host-bl-req "/welcome")))
|
|
200)
|
|
|
|
;; golden: endpoint body == the exact rendered HTML of the published post
|
|
(host-bl-test
|
|
"golden render"
|
|
(dream-resp-body (host-bl-app (host-bl-req "/welcome/")))
|
|
"<h1>Hello SX</h1><p>Served by lib/host.</p>")
|
|
|
|
;; persistence: a post materialises from the op-log (replay), and re-seeding is
|
|
;; idempotent (no duplicate blocks appended).
|
|
(host-bl-test "lookup materialises 2 blocks" (content/count (host/blog-lookup "welcome")) 2)
|
|
(host/blog-seed! "welcome" "Hello SX" "Served by lib/host." 2)
|
|
(host-bl-test "re-seed is idempotent" (content/count (host/blog-lookup "welcome")) 2)
|
|
|
|
;; ── unknown slug -> 404 ─────────────────────────────────────────────
|
|
(host-bl-test
|
|
"unknown slug 404"
|
|
(dream-status (host-bl-app (host-bl-req "/nope/")))
|
|
404)
|
|
(host-bl-test
|
|
"404 names the slug"
|
|
(contains? (dream-resp-body (host-bl-app (host-bl-req "/nope/"))) "nope")
|
|
true)
|
|
|
|
;; ── route precedence: domain routes win over the :slug catch-all ────
|
|
(feed/reset!)
|
|
(host-bl-test
|
|
"/feed served by feed, not blog 404"
|
|
(dream-status (host-bl-app (host-bl-req "/feed")))
|
|
200)
|
|
(host-bl-test
|
|
"/feed body is the feed envelope, not HTML"
|
|
(contains? (dream-resp-body (host-bl-app (host-bl-req "/feed"))) "\"ok\":true")
|
|
true)
|
|
|
|
(define
|
|
host-bl-tests-run!
|
|
(fn
|
|
()
|
|
{:total (+ host-bl-pass host-bl-fail)
|
|
:passed host-bl-pass
|
|
:failed host-bl-fail
|
|
:fails host-bl-fails}))
|