Fase B8+B9: stateful code kernel and live notes bound to external URLs
B8 - executable code blocks with a real kernel: - worker/handler/kernel.cljs: one persistent SCI interpreter session per page, reused across block evaluations so defs/state survive between runs. Deliberately scoped to the same privileges the existing client-side single-shot evaluator already had (no shell/fs access, no call-api). - Run button + result display wired into block.cljs's code-block UI. - New :logseq.property.code/result and /executed-at properties (65.38). B9 - live notes: pages tagged #LiveNote that fetch external content on a refresh schedule and render it via the render-resource pipeline: - worker/handler/live_notes.cljs: per-block credential storage, scheduled refresh (Node-only), thread-apis for manual refresh and auth. - worker/handler/render_resource/live_note.cljs: reads back fetched content, watching [:entity block-uuid] for reactive invalidation. - New :logseq.class/LiveNote + :logseq.property.livenote/* properties (65.39). Bugs found and fixed along the way while actually exercising page creation through page-handler/create! for the first time in a test (previously only pure-fn tests existed for CalDAV/Event/Contact): - logseq-property-namespaces (property.cljs) was missing the citation/event/ contact/caldav/livenote namespaces, causing auto-create-ontology to treat already-built-in properties as new user idents. - outliner/page.cljs's build-page-tx always added the generic #Page tag even when the caller tagged with a built-in class that extends #Page, which malli-schema rejects as conflicting; it also lost the property type when building ref-typed property values for new pages, breaking non-:default types like :number. - entity-util/page? never recognized Event/Contact/LiveNote as pages (only Journal/Whiteboard/Tag/Property/Page had dedicated recognition), so pages tagged with those classes alone weren't treated as pages anywhere in the app; added built-in-page-child? alongside the existing per-class checks. - caldav.cljs's upsert-page! passed a bare keyword as a tag where an entity was required, and two error logs passed raw error objects to glogi that triggered runaway recursion in this test environment; both fixed.
This commit is contained in:
86
src/test/frontend/worker/handler/kernel_test.cljs
Normal file
86
src/test/frontend/worker/handler/kernel_test.cljs
Normal file
@@ -0,0 +1,86 @@
|
||||
(ns frontend.worker.handler.kernel-test
|
||||
(:require [cljs.test :refer [deftest is testing use-fixtures]]
|
||||
[frontend.worker.handler.kernel :as kernel]
|
||||
[frontend.worker.state :as worker-state]
|
||||
[logseq.db.test.helper :as db-test]))
|
||||
|
||||
(def ^:private test-repo "kernel-test-repo")
|
||||
|
||||
(defn- with-test-conn
|
||||
[f]
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
{:pages-and-blocks
|
||||
[{:page {:block/title "Kernel page"}
|
||||
:blocks [{:block/title "code block"}]}]})
|
||||
prev-conns @worker-state/*datascript-conns]
|
||||
(swap! worker-state/*datascript-conns assoc test-repo conn)
|
||||
(try
|
||||
(f conn)
|
||||
(finally
|
||||
(reset! worker-state/*datascript-conns prev-conns)
|
||||
(kernel/clear-repo-sessions! test-repo)))))
|
||||
|
||||
(use-fixtures :each
|
||||
{:after #(kernel/clear-repo-sessions! test-repo)})
|
||||
|
||||
(deftest eval-block-persists-result-onto-the-block
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-uuid (:block/uuid (:block/page block))
|
||||
result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "(+ 1 2)")]
|
||||
(is (= "3" (:result result)))
|
||||
(is (false? (:error? result)))
|
||||
(let [updated (db-test/find-block-by-content @conn "code block")]
|
||||
(is (= "3" (:logseq.property.code/result updated)))
|
||||
(is (number? (:logseq.property.code/executed-at updated))))))))
|
||||
|
||||
(deftest eval-block-formats-errors-with-a-prefix
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-uuid (:block/uuid (:block/page block))
|
||||
result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "(throw (ex-info \"boom\" {}))")]
|
||||
(is (true? (:error? result)))
|
||||
(is (re-find #"^Error: " (:result result)))))))
|
||||
|
||||
(deftest kernel-session-state-persists-across-evaluations-on-the-same-page
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-uuid (:block/uuid (:block/page block))]
|
||||
(kernel/eval-block! test-repo page-uuid (:block/uuid block) "(def counter 0)")
|
||||
(kernel/eval-block! test-repo page-uuid (:block/uuid block) "(def counter (inc counter))")
|
||||
(kernel/eval-block! test-repo page-uuid (:block/uuid block) "(def counter (inc counter))")
|
||||
(let [result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "counter")]
|
||||
(is (= "2" (:result result))))))))
|
||||
|
||||
(deftest kernel-sessions-are-isolated-per-page
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-a (random-uuid)
|
||||
page-b (random-uuid)]
|
||||
(kernel/eval-block! test-repo page-a (:block/uuid block) "(def shared 1)")
|
||||
(let [result (kernel/eval-block! test-repo page-b (:block/uuid block) "(def shared 2) shared")]
|
||||
(is (= "2" (:result result))))
|
||||
(let [result (kernel/eval-block! test-repo page-a (:block/uuid block) "shared")]
|
||||
(is (= "1" (:result result))))))))
|
||||
|
||||
(deftest restart-session-clears-persisted-state
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-uuid (:block/uuid (:block/page block))]
|
||||
(kernel/eval-block! test-repo page-uuid (:block/uuid block) "(def counter 0)")
|
||||
(kernel/restart-session! test-repo page-uuid)
|
||||
(let [result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "(def counter 0) counter")]
|
||||
(is (= "0" (:result result))))))))
|
||||
|
||||
(deftest kernel-namespace-exposes-the-same-helpers-as-the-client-evaluator
|
||||
(with-test-conn
|
||||
(fn [conn]
|
||||
(let [block (db-test/find-block-by-content @conn "code block")
|
||||
page-uuid (:block/uuid (:block/page block))]
|
||||
(is (= "6" (:result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "(sum [1 2 3])"))))
|
||||
(is (= "2" (:result (kernel/eval-block! test-repo page-uuid (:block/uuid block) "(average [1 2 3])"))))))))
|
||||
Reference in New Issue
Block a user