fix(test): silence expected errors and task fail arity

This commit is contained in:
Tienson Qin
2026-04-23 19:50:07 +08:00
parent f37025a364
commit d54484dff2
8 changed files with 143 additions and 44 deletions

View File

@@ -6,6 +6,11 @@
(defonce subtle (.. js/crypto -subtle))
(defn- expected-crypto-operation-error?
[e]
(= "OperationError" (or (some-> e .-name)
(some-> e ex-cause .-name))))
(defn <export-aes-key
[aes-key]
(assert (instance? js/CryptoKey aes-key))
@@ -156,7 +161,8 @@
#js ["decrypt"])]
private-key)
(p/catch (fn [e]
(log/error "decrypt-private-key" e)
(when-not (expected-crypto-operation-error? e)
(log/error "decrypt-private-key" e))
(ex-info "decrypt-private-key" {} e)))))
(defn <encrypt-aes-key
@@ -189,7 +195,8 @@
true
#js ["encrypt" "decrypt"]))
(p/catch (fn [e]
(log/error "decrypt-aes-key failed" e)
(when-not (expected-crypto-operation-error? e)
(log/error "decrypt-aes-key failed" e))
(ex-info "decrypt-aes-key" {} e)))))
(defn <encrypt-uint8array

View File

@@ -116,10 +116,11 @@
(m/reduce {} nil (m/eduction (take 1) f)))
(defn- fail-case-default-handler
[key' e]
(when-not (or (instance? Cancelled e)
(= "missionary.Cancelled" (ex-message e)))
(log/error :run-task-failed e :key key')))
[key' & fail-args]
(let [e (first fail-args)]
(when-not (or (instance? Cancelled e)
(= "missionary.Cancelled" (ex-message e)))
(log/error :run-task-failed e :key key'))))
(defn run-task
"Return the canceler"
@@ -150,8 +151,13 @@
(when-let [canceler (get @*background-task-cancelers key')]
(canceler)
(vswap! *background-task-cancelers assoc key' nil))
(prn :run-background-task key')
(let [canceler (run-task key' task :fail (fn [e] (log/error :background-task-stopped {:k key' :e e})))]
(let [canceler (run-task key'
task
:fail (fn [& fail-args]
(log/error :background-task-stopped
{:k key'
:e (first fail-args)
:fail-args fail-args})))]
(vswap! *background-task-cancelers assoc key' canceler)
nil))

View File

@@ -87,6 +87,12 @@
:worker-error-data error-data
:worker-cause-data cause-data}}])))
(defn- suppress-worker-error-log?
[error-value]
(= "Non-transact outliner ops contain numeric entity ids"
(or (:message error-value)
(get error-value "message"))))
(defn handle-message!
[^js worker wrapped-worker]
(assert worker "worker doesn't exists")
@@ -101,8 +107,10 @@
(if (and (= "HANDLER" (.-type data)) (= "throw" (.-name data)))
(if (.-isError (.-value ^js data))
(let [error-value (-> data bean/->clj (get-in [:value :value]))]
(js/console.error "Unexpected webworker error:" error-value)
(js/console.log (:stack error-value))
(when-not (suppress-worker-error-log? error-value)
(js/console.error "Unexpected webworker error:" error-value)
(when-let [stack (:stack error-value)]
(js/console.log stack)))
(report-worker-error! error-value))
(js/console.error "Unexpected webworker error :" data))
(if (string? data)

View File

@@ -166,6 +166,12 @@
(contains? #{:invalid-history-action-ops}
reason)))
(defn- expected-invalid-history-action-reason?
[reason]
(contains? #{:invalid-history-action-ops
:invalid-history-action-tx}
reason))
(declare undo-redo-aux)
(defn- empty-stack-result
@@ -226,11 +232,12 @@
:else
(do
(log/error ::undo-redo-worker-action-unavailable
{:undo? undo?
:repo repo
:tx-id tx-id
:result worker-result})
(when-not (expected-invalid-history-action-reason? (:reason worker-result))
(log/error ::undo-redo-worker-action-unavailable
{:undo? undo?
:repo repo
:tx-id tx-id
:result worker-result}))
(clear-history! repo)
(empty-stack-result undo?))))
(catch :default e

View File

@@ -5,6 +5,8 @@
(deftest handle-message-reports-comlink-worker-throw-with-extra-data-test
(let [captured-events (atom [])
logged-errors (atom [])
logged-stacks (atom [])
worker (js-obj)
worker-error {:message "Non-transact outliner ops contain numeric entity ids"
:data {:stage :forward-outliner-ops
@@ -14,19 +16,29 @@
event #js {:data #js {:type "HANDLER"
:name "throw"
:value #js {:isError true
:value (clj->js worker-error)}}}]
(with-redefs [state/pub-event! (fn [payload]
(swap! captured-events conj payload))]
(worker-handler/handle-message! worker nil)
((.-onmessage worker) event)
(is (= 1 (count @captured-events)))
(let [[event-type payload] (first @captured-events)]
(is (= :capture-error event-type))
(is (= true (get-in payload [:payload :worker-error?])))
(is (= {:stage "forward-outliner-ops"
:index 0}
(get-in payload [:extra :worker-error-data])))
(is (= {:op "save-block"}
(get-in payload [:extra :worker-cause-data])))
(is (= (:message worker-error)
(ex-message (:error payload))))))))
:value (clj->js worker-error)}}}
orig-console-error (.-error js/console)
orig-console-log (.-log js/console)]
(aset js/console "error" (fn [& args] (swap! logged-errors conj args)))
(aset js/console "log" (fn [& args] (swap! logged-stacks conj args)))
(try
(with-redefs [state/pub-event! (fn [payload]
(swap! captured-events conj payload))]
(worker-handler/handle-message! worker nil)
((.-onmessage worker) event)
(is (= 1 (count @captured-events)))
(let [[event-type payload] (first @captured-events)]
(is (= :capture-error event-type))
(is (= true (get-in payload [:payload :worker-error?])))
(is (= {:stage "forward-outliner-ops"
:index 0}
(get-in payload [:extra :worker-error-data])))
(is (= {:op "save-block"}
(get-in payload [:extra :worker-cause-data])))
(is (= (:message worker-error)
(ex-message (:error payload))))
(is (empty? @logged-errors))
(is (empty? @logged-stacks))))
(finally
(aset js/console "error" orig-console-error)
(aset js/console "log" orig-console-log)))))

View File

@@ -0,0 +1,31 @@
(ns frontend.test.noise
"Shared helpers for muting noisy console output in passing test namespaces.")
(def ^:private default-console-methods
["error" "warn" "log" "info" "debug"])
(defonce ^:private *console-state
(atom {}))
(defn- mute-console!
[key methods*]
(let [originals (zipmap methods* (map #(aget js/console %) methods*))]
(swap! *console-state assoc key originals)
(doseq [method methods*]
(aset js/console method (fn [& _] nil)))))
(defn- restore-console!
[key methods*]
(when-let [originals (get @*console-state key)]
(doseq [method methods*]
(when-let [original (get originals method)]
(aset js/console method original)))
(swap! *console-state dissoc key)))
(defn mute-console-fixture
"Returns a cljs.test fixture map that mutes console output during the namespace run."
([key]
(mute-console-fixture key default-console-methods))
([key methods*]
{:before #(mute-console! key methods*)
:after #(restore-console! key methods*)}))

View File

@@ -1,11 +1,12 @@
(ns frontend.worker.db-sync-sim-test
(:require [cljs.test :refer [deftest is testing]]
(:require [cljs.test :refer [deftest is testing use-fixtures]]
[clojure.data :as data]
[clojure.set :as set]
[clojure.string :as string]
[datascript.core :as d]
[frontend.db.conn-state :as db-conn-state]
[frontend.state :as state]
[frontend.test.noise :as test-noise]
[frontend.worker.handler.page :as worker-page]
[frontend.worker.state :as worker-state]
[frontend.worker.sync :as db-sync]
@@ -26,6 +27,8 @@
(def ^:private base-page-title "Home")
(def ^:private default-seed 1337)
(use-fixtures :once (test-noise/mute-console-fixture ::db-sync-sim-test))
(defn- new-client-ops-db
[]
(let [Database (js/require "better-sqlite3")

View File

@@ -1,6 +1,6 @@
(ns frontend.worker.db-sync-test
(:require
[cljs.test :refer [async deftest is testing]]
[cljs.test :refer [async deftest is testing use-fixtures]]
[clojure.set :as set]
[clojure.string :as string]
[datascript.core :as d]
@@ -22,6 +22,7 @@
[frontend.worker.sync.temp-sqlite :as sync-temp-sqlite]
[frontend.worker.sync.transport :as sync-transport]
[frontend.worker.sync.upload :as sync-upload]
[frontend.test.noise :as test-noise]
[frontend.worker.undo-redo :as undo-redo]
[logseq.common.config :as common-config]
[logseq.common.util :as common-util]
@@ -52,6 +53,18 @@
:logseq.property.recycle/original-page
:logseq.property.recycle/original-order})
(defn- with-silenced-console-error
"Silences expected error logging without swallowing thrown exceptions."
[f]
(let [original-console-error (.-error js/console)]
(aset js/console "error" (fn [& _] nil))
(try
(f)
(finally
(aset js/console "error" original-console-error)))))
(use-fixtures :once (test-noise/mute-console-fixture ::db-sync-test))
(defn- js-row
[m]
(let [row (js-obj)]
@@ -724,7 +737,8 @@
(reset! *captured {:type type
:payload payload}))]
(try
(sync-handle-message/handle-message! test-repo client raw-message)
(with-silenced-console-error
#(sync-handle-message/handle-message! test-repo client raw-message))
(is false "expected tx/reject to fail-fast with rejected tx details")
(catch :default error
(let [data (ex-data error)
@@ -763,12 +777,17 @@
:db-sync/pending? true}])
(with-redefs [client-op/get-local-tx (constantly 0)]
(let [error (try
(sync-handle-message/handle-message! test-repo client raw-message)
(with-silenced-console-error
#(sync-handle-message/handle-message! test-repo client raw-message))
nil
(catch :default e
e))
ent (client-op-tx-row client-ops-conn tx-id)]
(is (some? error))
(is (= :db-sync/tx-rejected
(:type (ex-data error))))
(is (= "db transact failed"
(:reason (ex-data error))))
(is (= [] @(:inflight client)))
(is (= 0 (aget ent "pending")))
(is (= 1 (aget ent "failed"))))))))))
@@ -805,7 +824,8 @@
:db-sync/pending? true}])
(with-redefs [client-op/get-local-tx (constantly 0)]
(let [error (try
(sync-handle-message/handle-message! test-repo client raw-message)
(with-silenced-console-error
#(sync-handle-message/handle-message! test-repo client raw-message))
nil
(catch :default e
e))
@@ -813,6 +833,10 @@
failed-ent (client-op-tx-row client-ops-conn failed-tx-id)
untouched-ent (client-op-tx-row client-ops-conn untouched-tx-id)]
(is (some? error))
(is (= :db-sync/tx-rejected
(:type (ex-data error))))
(is (= "db transact failed"
(:reason (ex-data error))))
(is (= [] @(:inflight client)))
(is (= 0 (aget success-ent "pending")))
(is (not= 1 (aget success-ent "failed")))
@@ -2373,14 +2397,15 @@
page-uuid (:block/uuid (:block/page seed))
block-uuid (random-uuid)]
(is (thrown? js/Error
(#'sync-apply/replay-canonical-outliner-op!
conn
[:save-block [{:block/uuid block-uuid
:block/title ""
:block/parent [:block/uuid page-uuid]
:block/page [:block/uuid page-uuid]
:block/order "a0"}
nil]])))
(with-silenced-console-error
#(#'sync-apply/replay-canonical-outliner-op!
conn
[:save-block [{:block/uuid block-uuid
:block/title ""
:block/parent [:block/uuid page-uuid]
:block/page [:block/uuid page-uuid]
:block/order "a0"}
nil]]))))
(is (nil? (d/entity @conn [:block/uuid block-uuid]))))))
(deftest apply-history-action-redo-replays-status-property-test