mirror of
https://github.com/logseq/logseq.git
synced 2026-05-28 14:39:48 +00:00
Merge pull request #12707 from logseq/codex/fix-cli-block-inline-properties
fix(cli): handle inline block properties
This commit is contained in:
@@ -674,6 +674,77 @@
|
||||
:upsert ["--blocks-file" "--target-id" "--pos"]}},
|
||||
:tags [:upsert],
|
||||
:extends :non-sync/graph-json-env}
|
||||
{:id "block-upsert-blocks-file-inline-property-name-json",
|
||||
:setup
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert page --graph {{graph-arg}} --page Home >/dev/null"
|
||||
"{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert property --graph {{graph-arg}} --name 'Correct Answer' --type default --cardinality one --public true >/dev/null"
|
||||
"printf '%s' '[{:block/title \"Question block\" \"Correct Answer\" \"answer\"}]' > {{export-path-arg}}"],
|
||||
:cmds
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert block --graph {{graph-arg}} --target-page Home --blocks-file {{export-path-arg}} >/dev/null"
|
||||
"{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output human show --graph {{graph-arg}} --page Home"],
|
||||
:expect
|
||||
{:exit 0,
|
||||
:stdout-contains ["Question block" "Correct Answer:" "answer"]},
|
||||
:covers
|
||||
{:commands ["upsert block" "upsert property" "show"],
|
||||
:options
|
||||
{:global ["--config" "--graph" "--root-dir" "--output"],
|
||||
:upsert ["--blocks-file" "--target-page" "--name" "--type" "--cardinality" "--public"],
|
||||
:show ["--page"]}},
|
||||
:tags [:upsert :show],
|
||||
:extends :non-sync/graph-json-env}
|
||||
{:id "block-upsert-blocks-inline-property-missing-does-not-create-target-page-json",
|
||||
:cmds
|
||||
["set +e; out=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert block --graph {{graph-arg}} --target-page NewPage --blocks '[{:block/title \"Q\" \"Missing Prop\" \"x\"}]' 2>&1)\"; code=$?; set -e; printf '%s\n' \"$out\"; test \"$code\" -ne 0; printf '%s' \"$out\" | python3 -c 'import sys,json; data=json.load(sys.stdin); assert data[\"status\"] == \"error\"; assert data[\"error\"][\"code\"] == \"property-not-found\"'; page=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json query --graph {{graph-arg}} --query '[:find ?e . :where [?e :block/title \"NewPage\"]]')\"; printf '%s\n' \"$page\"; printf '%s' \"$page\" | python3 -c 'import sys,json; data=json.load(sys.stdin); assert data[\"data\"][\"result\"] is None'"],
|
||||
:expect
|
||||
{:exit 0,
|
||||
:stdout-contains ["property-not-found"]},
|
||||
:covers
|
||||
{:commands ["upsert block" "query"],
|
||||
:options
|
||||
{:global ["--config" "--graph" "--root-dir" "--output"],
|
||||
:upsert ["--blocks" "--target-page"],
|
||||
:query ["--query"]}},
|
||||
:tags [:upsert],
|
||||
:extends :non-sync/graph-json-env}
|
||||
{:id "block-upsert-blocks-inline-properties-per-block-json",
|
||||
:setup
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert page --graph {{graph-arg}} --page Home >/dev/null"
|
||||
"{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert property --graph {{graph-arg}} --name 'Inline Note' --type default --cardinality one --public true >/dev/null"],
|
||||
:cmds
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert block --graph {{graph-arg}} --target-page Home --blocks '[{:block/title \"First inline\" \"Inline Note\" \"First note\"} {:block/title \"Second inline\" \"Inline Note\" \"Second note\"}]' >/dev/null"
|
||||
"first_id=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json query --graph {{graph-arg}} --query '[:find ?e . :where [?e :block/title \"First inline\"]]' | python3 -c 'import sys,json; print(json.load(sys.stdin)[\"data\"][\"result\"])')\"; second_id=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json query --graph {{graph-arg}} --query '[:find ?e . :where [?e :block/title \"Second inline\"]]' | python3 -c 'import sys,json; print(json.load(sys.stdin)[\"data\"][\"result\"])')\"; first_show=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output human show --graph {{graph-arg}} --id \"$first_id\")\"; second_show=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output human show --graph {{graph-arg}} --id \"$second_id\")\"; printf '%s\n---\n%s\n' \"$first_show\" \"$second_show\"; printf '%s' \"$first_show\" | grep 'Inline Note: First note' >/dev/null; ! printf '%s' \"$first_show\" | grep 'Second note' >/dev/null; printf '%s' \"$second_show\" | grep 'Inline Note: Second note' >/dev/null; ! printf '%s' \"$second_show\" | grep 'First note' >/dev/null"],
|
||||
:expect
|
||||
{:exit 0,
|
||||
:stdout-contains ["First inline" "Inline Note: First note" "Second inline" "Inline Note: Second note"]},
|
||||
:covers
|
||||
{:commands ["upsert block" "upsert property" "query" "show"],
|
||||
:options
|
||||
{:global ["--config" "--graph" "--root-dir" "--output"],
|
||||
:upsert ["--blocks" "--target-page" "--name" "--type" "--cardinality" "--public"],
|
||||
:query ["--query"],
|
||||
:show ["--id"]}},
|
||||
:tags [:upsert :show],
|
||||
:extends :non-sync/graph-json-env}
|
||||
{:id "block-upsert-blocks-inline-property-numeric-id-json",
|
||||
:setup
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert page --graph {{graph-arg}} --page Home >/dev/null"
|
||||
"{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert property --graph {{graph-arg}} --name 'Numeric Prop' --type default --cardinality one --public true >/dev/null"],
|
||||
:cmds
|
||||
["prop_id=\"$({{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json query --graph {{graph-arg}} --query '[:find ?e . :where [?e :block/title \"Numeric Prop\"]]' | python3 -c 'import sys,json; print(json.load(sys.stdin)[\"data\"][\"result\"])')\"; {{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert block --graph {{graph-arg}} --target-page Home --blocks \"[{:block/title \\\"Inline numeric\\\" $prop_id \\\"inline\\\"}]\" >/dev/null"
|
||||
"{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output human show --graph {{graph-arg}} --page Home"],
|
||||
:expect
|
||||
{:exit 0,
|
||||
:stdout-contains ["Inline numeric" "Numeric Prop: inline"]},
|
||||
:covers
|
||||
{:commands ["upsert block" "upsert property" "query" "show"],
|
||||
:options
|
||||
{:global ["--config" "--graph" "--root-dir" "--output"],
|
||||
:upsert ["--blocks" "--target-page" "--name" "--type" "--cardinality" "--public"],
|
||||
:query ["--query"],
|
||||
:show ["--page"]}},
|
||||
:tags [:upsert :show],
|
||||
:extends :non-sync/graph-json-env}
|
||||
{:id "block-upsert-target-uuid-json",
|
||||
:setup
|
||||
["{{cli}} --root-dir {{root-dir-arg}} --config {{config-path-arg}} --output json upsert page --graph {{graph-arg}} --page Home >/dev/null"
|
||||
|
||||
@@ -168,6 +168,80 @@
|
||||
block)))
|
||||
blocks))
|
||||
|
||||
(def ^:private inline-property-key-namespace-prefixes
|
||||
["logseq.property" "user.property" "plugin.property"])
|
||||
|
||||
(defn- inline-property-key-namespace?
|
||||
[key-namespace]
|
||||
(boolean
|
||||
(and key-namespace
|
||||
(some (fn [prefix]
|
||||
(or (= key-namespace prefix)
|
||||
(string/starts-with? key-namespace (str prefix "."))))
|
||||
inline-property-key-namespace-prefixes))))
|
||||
|
||||
(defn- public-built-in-property-key?
|
||||
[k]
|
||||
(if-let [property (get db-property/built-in-properties k)]
|
||||
(true? (get-in property [:schema :public?]))
|
||||
true))
|
||||
|
||||
(defn- inline-property-key?
|
||||
[k]
|
||||
(cond
|
||||
(string? k)
|
||||
(seq (string/trim k))
|
||||
|
||||
(or (number? k) (uuid? k))
|
||||
true
|
||||
|
||||
(qualified-keyword? k)
|
||||
(and (inline-property-key-namespace? (namespace k))
|
||||
(public-built-in-property-key? k))
|
||||
|
||||
(keyword? k)
|
||||
true
|
||||
|
||||
:else
|
||||
false))
|
||||
|
||||
(defn- split-inline-property-attrs
|
||||
[block]
|
||||
(reduce-kv (fn [acc k v]
|
||||
(if (inline-property-key? k)
|
||||
(update acc :properties assoc k v)
|
||||
(update acc :block assoc k v)))
|
||||
{:block {}
|
||||
:properties {}}
|
||||
block))
|
||||
|
||||
(defn- extract-inline-properties
|
||||
[blocks]
|
||||
(letfn [(walk-block [block]
|
||||
(let [{block-without-inline-properties :block
|
||||
inline-properties :properties} (split-inline-property-attrs block)
|
||||
children (:block/children block-without-inline-properties)
|
||||
walked-children (when (seq children)
|
||||
(mapv walk-block children))
|
||||
block' (if (seq walked-children)
|
||||
(assoc block-without-inline-properties :block/children (mapv :block walked-children))
|
||||
block-without-inline-properties)
|
||||
block-uuid (:block/uuid block')]
|
||||
(when (and (seq inline-properties) (nil? block-uuid))
|
||||
(throw (ex-info "block uuid is required for inline properties"
|
||||
{:code :missing-block-uuid-for-inline-properties
|
||||
:properties (keys inline-properties)})))
|
||||
{:block block'
|
||||
:property-assignments (cond-> []
|
||||
(seq inline-properties)
|
||||
(conj {:block-uuid block-uuid
|
||||
:properties inline-properties})
|
||||
(seq walked-children)
|
||||
(into (mapcat :property-assignments walked-children)))}))]
|
||||
(let [walked (mapv walk-block blocks)]
|
||||
{:blocks (mapv :block walked)
|
||||
:property-assignments (vec (mapcat :property-assignments walked))})))
|
||||
|
||||
(defn- normalize-created-ids
|
||||
[ids]
|
||||
(->> ids
|
||||
@@ -1063,6 +1137,27 @@
|
||||
properties))]
|
||||
(vec resolved-entries)))))
|
||||
|
||||
(defn- resolve-inline-property-assignments
|
||||
[config repo property-assignments]
|
||||
(if (seq property-assignments)
|
||||
(p/let [resolved (p/all
|
||||
(map (fn [{:keys [block-uuid properties]}]
|
||||
(p/let [resolved-properties (resolve-properties config repo properties
|
||||
{:allow-non-built-in? true})]
|
||||
{:block-uuid block-uuid
|
||||
:properties resolved-properties}))
|
||||
property-assignments))]
|
||||
(vec resolved))
|
||||
(p/resolved nil)))
|
||||
|
||||
(defn- inline-property-assignment-ops
|
||||
[property-assignments]
|
||||
(mapcat (fn [{:keys [block-uuid properties]}]
|
||||
(map (fn [[property-ident value]]
|
||||
[:batch-set-property [[block-uuid] property-ident value {}]])
|
||||
properties))
|
||||
property-assignments))
|
||||
|
||||
(defn- resolve-add-target
|
||||
[config {:keys [repo target-id target-uuid target-page-name]}]
|
||||
(cond
|
||||
@@ -1163,17 +1258,21 @@
|
||||
(defn execute-add-block
|
||||
[action config]
|
||||
(-> (p/let [cfg (cli-server/ensure-server! config (:repo action))
|
||||
target-block-uuid (resolve-add-target cfg action)
|
||||
action-blocks (normalize-block-content-keys (:blocks action))
|
||||
ref-values (collect-page-refs action-blocks)
|
||||
{blocks-without-inline-properties :blocks
|
||||
inline-property-assignments :property-assignments} (extract-inline-properties action-blocks)
|
||||
inline-property-assignments (resolve-inline-property-assignments cfg (:repo action)
|
||||
inline-property-assignments)
|
||||
target-block-uuid (resolve-add-target cfg action)
|
||||
ref-values (collect-page-refs blocks-without-inline-properties)
|
||||
{:keys [uuid-refs page-refs id-refs]} (partition-ref-values ref-values)
|
||||
_ (ensure-block-refs-exist! cfg (:repo action) uuid-refs)
|
||||
page-refs' (or (resolve-page-ref-entities cfg (:repo action) page-refs) [])
|
||||
id-refs' (or (resolve-id-ref-entities cfg (:repo action) id-refs) [])
|
||||
refs (into page-refs' id-refs')
|
||||
blocks (if (seq refs)
|
||||
(normalize-block-title-refs action-blocks refs)
|
||||
action-blocks)
|
||||
(normalize-block-title-refs blocks-without-inline-properties refs)
|
||||
blocks-without-inline-properties)
|
||||
blocks-for-insert (flatten-block-tree blocks)
|
||||
status (:status action)
|
||||
tags (if (contains? action :resolved-tags)
|
||||
@@ -1220,7 +1319,9 @@
|
||||
(and (seq properties) (seq block-uuids))
|
||||
(into (map (fn [[k v]]
|
||||
[:batch-set-property [block-uuids k v {}]])
|
||||
properties)))
|
||||
properties))
|
||||
(seq inline-property-assignments)
|
||||
(into (inline-property-assignment-ops inline-property-assignments)))
|
||||
apply-result (transport/invoke cfg :thread-api/apply-outliner-ops [(:repo action) ops {}])
|
||||
created-ids (resolve-created-block-ids cfg (:repo action) blocks-for-insert apply-result)]
|
||||
{:status :ok
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
[cljs.test :refer [async deftest is testing]]
|
||||
[clojure.string :as string]
|
||||
[logseq.cli.command.add :as add-command]
|
||||
[logseq.cli.server :as cli-server]
|
||||
[logseq.common.util.date-time :as date-time-util]
|
||||
[logseq.cli.transport :as transport]
|
||||
[promesa.core :as p]))
|
||||
@@ -96,6 +97,65 @@
|
||||
(is (empty? (:id-refs result)))
|
||||
(is (= ["3.14" "1e5"] (:page-refs result))))))
|
||||
|
||||
(deftest test-extract-inline-properties-from-blocks
|
||||
(testing "removes inline property attrs while preserving block uuids and children"
|
||||
(let [root-uuid (uuid "00000000-0000-0000-0000-000000000101")
|
||||
child-uuid (uuid "00000000-0000-0000-0000-000000000102")
|
||||
result (#'add-command/extract-inline-properties
|
||||
[{:block/title "Root"
|
||||
:block/uuid root-uuid
|
||||
:block/page [:block/name "Home"]
|
||||
:block/tags [1]
|
||||
:user.property/root-answer "root"
|
||||
"Correct Answer" "named value"
|
||||
:logseq.property/status :logseq.property/status.todo
|
||||
:block/children [{:block/title "Child"
|
||||
:block/uuid child-uuid
|
||||
:user.property/child-answer "child"}]}])]
|
||||
(is (= [{:block/title "Root"
|
||||
:block/uuid root-uuid
|
||||
:block/page [:block/name "Home"]
|
||||
:block/tags [1]
|
||||
:block/children [{:block/title "Child"
|
||||
:block/uuid child-uuid}]}]
|
||||
(:blocks result)))
|
||||
(is (= [{:block-uuid root-uuid
|
||||
:properties {:user.property/root-answer "root"
|
||||
"Correct Answer" "named value"
|
||||
:logseq.property/status :logseq.property/status.todo}}
|
||||
{:block-uuid child-uuid
|
||||
:properties {:user.property/child-answer "child"}}]
|
||||
(:property-assignments result))))))
|
||||
|
||||
(deftest test-extract-inline-properties-keeps-non-property-attrs
|
||||
(testing "property selectors are extracted without treating normal block attrs as properties"
|
||||
(let [block-uuid (uuid "00000000-0000-0000-0000-000000000103")
|
||||
property-uuid (uuid "00000000-0000-0000-0000-000000000104")
|
||||
result (#'add-command/extract-inline-properties
|
||||
[{:block/title "Block"
|
||||
:block/uuid block-uuid
|
||||
:db/id 101
|
||||
:build/keep-uuid? true
|
||||
:plugin/option "kept"
|
||||
:logseq.property.asset/type "png"
|
||||
:plugin.property._test_plugin/rating "5"
|
||||
801 "by id"
|
||||
property-uuid "by uuid"
|
||||
:plain-title "by keyword"}])]
|
||||
(is (= [{:block/title "Block"
|
||||
:block/uuid block-uuid
|
||||
:db/id 101
|
||||
:build/keep-uuid? true
|
||||
:plugin/option "kept"
|
||||
:logseq.property.asset/type "png"}]
|
||||
(:blocks result)))
|
||||
(is (= [{:block-uuid block-uuid
|
||||
:properties {:plugin.property._test_plugin/rating "5"
|
||||
801 "by id"
|
||||
property-uuid "by uuid"
|
||||
:plain-title "by keyword"}}]
|
||||
(:property-assignments result))))))
|
||||
|
||||
(def ^:private mock-transport-invoke
|
||||
(fn [_ method args]
|
||||
(case method
|
||||
@@ -302,3 +362,143 @@
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally done))))
|
||||
|
||||
(deftest test-execute-add-block-applies-inline-properties-per-block
|
||||
(async done
|
||||
(let [target-uuid (uuid "00000000-0000-0000-0000-000000000200")
|
||||
root-uuid (uuid "00000000-0000-0000-0000-000000000201")
|
||||
child-uuid (uuid "00000000-0000-0000-0000-000000000202")
|
||||
ops* (atom nil)
|
||||
resolve-properties-calls* (atom [])]
|
||||
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
|
||||
add-command/resolve-tags (fn [_ _ _] (p/resolved nil))
|
||||
add-command/resolve-properties
|
||||
(fn [_ _ properties & [opts]]
|
||||
(swap! resolve-properties-calls* conj {:properties properties
|
||||
:opts opts})
|
||||
(p/resolved properties))
|
||||
add-command/resolve-property-identifiers (fn [_ _ _ & _] (p/resolved nil))
|
||||
transport/invoke
|
||||
(fn [_ method args]
|
||||
(case method
|
||||
:thread-api/pull
|
||||
(let [[_ _ lookup] args]
|
||||
(p/resolved
|
||||
(cond
|
||||
(= lookup 900)
|
||||
{:db/id 900 :block/uuid target-uuid}
|
||||
|
||||
(= lookup [:block/uuid root-uuid])
|
||||
{:db/id 901 :block/uuid root-uuid}
|
||||
|
||||
(= lookup [:block/uuid child-uuid])
|
||||
{:db/id 902 :block/uuid child-uuid}
|
||||
|
||||
:else {})))
|
||||
|
||||
:thread-api/apply-outliner-ops
|
||||
(let [[_ ops _] args]
|
||||
(reset! ops* ops)
|
||||
(p/resolved {:result :ok}))
|
||||
|
||||
(p/rejected (ex-info "unexpected invoke" {:method method :args args}))))]
|
||||
(p/let [result (add-command/execute-add-block
|
||||
{:type :add-block
|
||||
:repo "demo"
|
||||
:target-id 900
|
||||
:pos "last-child"
|
||||
:blocks [{:block/title "Root"
|
||||
:block/uuid root-uuid
|
||||
:user.property/root-answer "root"
|
||||
:block/children [{:block/title "Child"
|
||||
:block/uuid child-uuid
|
||||
:user.property/child-answer "child"}]}]}
|
||||
{})]
|
||||
(is (= :ok (:status result)))
|
||||
(is (= [901 902] (get-in result [:data :result])))
|
||||
(let [ops @ops*
|
||||
insert-op (first ops)
|
||||
inserted-blocks (get-in insert-op [1 0])]
|
||||
(is (= :insert-blocks (first insert-op)))
|
||||
(is (= [{:block/title "Root"
|
||||
:block/uuid root-uuid}
|
||||
{:block/title "Child"
|
||||
:block/uuid child-uuid
|
||||
:block/parent [:block/uuid root-uuid]}]
|
||||
inserted-blocks))
|
||||
(is (some #(= [:batch-set-property [[root-uuid]
|
||||
:user.property/root-answer
|
||||
"root"
|
||||
{}]]
|
||||
%)
|
||||
ops))
|
||||
(is (some #(= [:batch-set-property [[child-uuid]
|
||||
:user.property/child-answer
|
||||
"child"
|
||||
{}]]
|
||||
%)
|
||||
ops))
|
||||
(is (some #(= {:properties {:user.property/root-answer "root"}
|
||||
:opts {:allow-non-built-in? true}}
|
||||
%)
|
||||
@resolve-properties-calls*))
|
||||
(is (some #(= {:properties {:user.property/child-answer "child"}
|
||||
:opts {:allow-non-built-in? true}}
|
||||
%)
|
||||
@resolve-properties-calls*)))))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally done)))))
|
||||
|
||||
(deftest test-execute-add-block-does-not-create-target-page-when-inline-property-resolution-fails
|
||||
(async done
|
||||
(let [created-page-uuid (uuid "00000000-0000-0000-0000-000000000203")
|
||||
ops* (atom [])]
|
||||
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
|
||||
add-command/resolve-properties
|
||||
(fn [_ _ properties & _]
|
||||
(if (= {"Missing Prop" "x"} properties)
|
||||
(p/rejected (ex-info "property not found: \"Missing Prop\""
|
||||
{:code :property-not-found
|
||||
:property "Missing Prop"}))
|
||||
(p/resolved properties)))
|
||||
transport/invoke
|
||||
(fn [_ method args]
|
||||
(case method
|
||||
:thread-api/q
|
||||
(p/resolved [])
|
||||
|
||||
:thread-api/pull
|
||||
(let [[_ _ lookup] args]
|
||||
(p/resolved
|
||||
(if (= lookup [:block/name "newpage"])
|
||||
{:db/id 900
|
||||
:block/uuid created-page-uuid
|
||||
:block/name "newpage"
|
||||
:block/title "NewPage"}
|
||||
{})))
|
||||
|
||||
:thread-api/apply-outliner-ops
|
||||
(let [[_ ops _] args]
|
||||
(swap! ops* conj ops)
|
||||
(p/resolved {:result :ok}))
|
||||
|
||||
(p/rejected (ex-info "unexpected invoke" {:method method :args args}))))]
|
||||
(-> (add-command/execute-add-block
|
||||
{:type :add-block
|
||||
:repo "demo"
|
||||
:target-page-name "NewPage"
|
||||
:pos "last-child"
|
||||
:blocks [{:block/title "Q"
|
||||
:block/uuid (uuid "00000000-0000-0000-0000-000000000204")
|
||||
"Missing Prop" "x"}]}
|
||||
{})
|
||||
(p/then (fn [_]
|
||||
(is false "expected inline property resolution error")))
|
||||
(p/catch (fn [e]
|
||||
(is (= :property-not-found (-> e ex-data :code)))
|
||||
(is (empty? @ops*)
|
||||
"target page creation must not run before inline properties validate")))))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally done)))))
|
||||
|
||||
Reference in New Issue
Block a user