; lib/blogimport/tests/source.sx — live-source adapter (Q-M4 internal-data query) (st-bootstrap-classes!) (content-bootstrap-blocks!) (content-bootstrap-doc!) (content-bootstrap-callout!) (content-bootstrap-media!) ; ---- canned service responses (lexical arrives as a JSON STRING, the DB column) ---- (define lex1 "{\"root\":{\"children\":[{\"type\":\"heading\",\"tag\":\"h2\",\"children\":[{\"type\":\"text\",\"text\":\"Live\"}]},{\"type\":\"paragraph\",\"children\":[{\"type\":\"text\",\"text\":\"from db\"}]}]}}") (define row1 {:uuid "post-1" :slug "live" :title "Live" :status "published" :visibility "public" :tags (list "x") :authors (list "u") :lexical lex1}) (define row2 {:uuid "post-2" :slug "two" :title "Two" :status "published" :lexical "{\"children\":[{\"type\":\"paragraph\",\"children\":[{\"type\":\"text\",\"text\":\"second\"}]}]}"}) ; ---- mock transport: (fetch-fn query params) -> response ---- (define mock-fetch (fn (query params) (cond ((equal? query "published-posts") (list "post-1" "post-2")) ((equal? query "post-by-id") (cond ((equal? (get params :id) "post-1") row1) ((equal? (get params :id) "post-2") row2) (else nil))) (else nil)))) ; ---- parse-row maps fields + parses the lexical JSON string ---- (define post1 (blogimport/parse-row row1)) (bi-test "parse-row id from uuid" (get post1 :id) "post-1") (bi-test "parse-row title" (get post1 :title) "Live") (bi-test "parse-row tags" (get post1 :tags) (list "x")) (bi-test "parse-row lexical parsed to blocks" (map blk-type (blogimport/lex-blocks (get post1 :lexical))) (list "heading" "text")) ; ---- id fallback (:id when no :uuid) + structured (non-string) lexical ---- (define post3 (blogimport/parse-row {:id "post-3" :slug "s3" :lexical {:children (list {:type "paragraph" :children (list {:type "text" :text "x"})})}})) (bi-test "parse-row id fallback" (get post3 :id) "post-3") (bi-test "parse-row structured lexical used as-is" (map blk-type (blogimport/lex-blocks (get post3 :lexical))) (list "text")) ; ---- enumeration + source-posts ---- (bi-test "published-ids" (blogimport/published-ids mock-fetch) (list "post-1" "post-2")) (bi-test "source-posts ids" (map (fn (p) (get p :id)) (blogimport/source-posts mock-fetch)) (list "post-1" "post-2")) ; ---- end-to-end backfill from the live source ---- (define B (persist/open)) (define cov (blogimport/backfill! B mock-fetch 10)) (bi-test "backfill total" (get cov :total) 2) (bi-test "backfill imported" (get cov :imported) 2) (bi-test "backfill post-1 version-count" (content/version-count B "post-1") 2) (bi-test "backfill post-1 head ids" (doc-ids (content/head B "post-1")) (list "b0" "b1")) (bi-test "backfill post-1 body text" (str (blk-send (doc-find (content/head B "post-1") "b1") "text")) "from db") (bi-test "backfill meta title" (get (blogimport/load-meta B "post-1") :title) "Live") ; ---- backfill is idempotent (one-way sync re-run) ---- (define cov2 (blogimport/backfill! B mock-fetch 11)) (bi-test "backfill rerun skipped" (get cov2 :skipped) 2) ; ---- sync-verify: persisted streams match the live-source oracle ---- (define sv (blogimport/sync-verify B mock-fetch)) (bi-test "sync-verify total" (get sv :total) 2) (bi-test "sync-verify ok" (get sv :ok) 2) (bi-test "sync-verify no mismatch" (get sv :mismatched) (list)) ; ---- explicit-id fallback path (before the enumeration query lands) ---- (define B2 (persist/open)) (define covx (blogimport/backfill-ids! B2 mock-fetch (list "post-2") 10)) (bi-test "backfill-ids imported" (get covx :imported) 1) (bi-test "backfill-ids post-2 ids" (doc-ids (content/head B2 "post-2")) (list "b0"))