enhance(rtc): add testcases, mock idb-keyval ns

pull/10438/head
rcmerci 2023-10-30 22:24:46 +08:00
parent 45a3e6bf2f
commit 9eb2806305
10 changed files with 110 additions and 31 deletions

View File

@ -162,6 +162,7 @@
;; src/test
frontend.test.helper/deftest-async clojure.test/deftest
frontend.test.helper/with-reset cljs.test/async
frontend.db.rtc.idb-keyval-mock/with-reset-idb-keyval-mock cljs.test/async
frontend.react/defc clojure.core/defn}
:skip-comments true
:output {:progress true}}

View File

@ -151,12 +151,11 @@
;; another check on the value of this atom to ensure no 2-go-threads running for same value
(when-let [n (seq @r)]
(reset! r [])
(prn ::n n)
(doseq [{:keys [ops repo]} n]
(prn ::add-ops ops)
(<! (op/<add-ops! repo ops))))))))
(defn- generate-rtc-ops
(defn generate-rtc-ops
[repo db-before db-after datoms]
(let [same-entity-datoms-coll (->> datoms
(map vec)
@ -164,8 +163,7 @@
vals)
ops (mapcat (partial entity-datoms=>ops repo db-before db-after) same-entity-datoms-coll)]
(when (seq ops)
(swap! *ops-pending-to-store conj {:ops ops :repo repo})
(prn :*ops-pending-to-store @*ops-pending-to-store))))
(swap! *ops-pending-to-store conj {:ops ops :repo repo}))))
(defn listen-db-to-generate-ops

View File

@ -1,6 +1,6 @@
(ns frontend.db.rtc.ops-idb-store
"Fns to RW ops in indexeddb"
(:require ["/frontend/idbkv" :as idb-keyval :refer [Store]]
(:require ["/frontend/idbkv" :as idb-keyval]
[promesa.core :as p]
[cljs-time.core :as t]
[cljs-time.coerce :as tc]
@ -13,8 +13,10 @@
(defn- ensure-store
[repo]
{:pre [(some? repo)]}
(swap! stores assoc repo (Store. (str "rtc-ops-" repo) "ops"))
(@stores repo))
(if-let [s (@stores repo)]
s
(do (swap! stores assoc repo (idb-keyval/newStore (str "rtc-ops-" repo) "ops"))
(@stores repo))))
(defn <update-local-tx!
[repo tx]
@ -42,8 +44,7 @@
(defonce #_:clj-kondo/ignore _add-ops-loop
(async/go-loop []
(if-let [[repo ops] (async/<! add-ops-ch)]
(do (prn :add-ops ops)
(async/<! (p->c (<add-ops*! repo ops)))
(do (async/<! (p->c (<add-ops*! repo ops)))
(recur))
(recur))))

View File

@ -1,6 +1,6 @@
(ns frontend.idb
"This system component provides indexedDB functionality"
(:require ["/frontend/idbkv" :as idb-keyval :refer [Store]]
(:require ["/frontend/idbkv" :as idb-keyval]
[clojure.string :as string]
[frontend.config :as config]
[frontend.storage :as storage]
@ -12,7 +12,6 @@
;; To maintain backward compatibility
(defonce store (atom nil))
(defn clear-idb!
@ -81,4 +80,4 @@
(defn start
"This component's only responsibility is to create a Store object"
[]
(reset! store (Store. "localforage" "keyvaluepairs" 2)))
(reset! store (idb-keyval/newStore "localforage" "keyvaluepairs" 2)))

View File

@ -131,7 +131,12 @@ function close(store = getDefaultStore()) {
return store._close();
}
exports.Store = Store;
function newStore(dbName = 'keyval-store', storeName = 'keyval', version = 1) {
return new Store(dbName, storeName, version);
}
exports.newStore = newStore;
// exports.Store = Store; // use newStore instead
exports.get = get;
exports.set = set;
exports.setBatch = setBatch;

View File

@ -3,7 +3,11 @@
[cljs.core.async :as async :refer [<! >! chan go]]
[frontend.db.rtc.mock :as rtc-mock]
[frontend.db.rtc.core :as rtc-core]
[frontend.test.helper :as test-helper]))
[frontend.test.helper :as test-helper]
[datascript.core :as d]
[frontend.db.conn :as conn]
[frontend.db.rtc.db-listener :as db-listener]
[frontend.db.rtc.ops-idb-store :as ops-idb-store]))
(def *test-rtc-state (atom nil))
@ -25,7 +29,6 @@
(rtc-core/<loop-for-rtc state graph-uuid repo :loop-started-ch loop-started-ch)
(<! loop-started-ch))))
(def start-and-stop-rtc-loop-fixture
{:before
#(t/async done
@ -41,3 +44,22 @@
(>! stop-rtc-loop-chan true))
(reset! *test-rtc-state nil)
(done)))})
(def listen-test-db-fixture
{:before
#(let [test-db-conn (conn/get-db test-helper/test-db false)]
(assert (some? test-db-conn))
(d/listen! test-db-conn
::gen-ops
(fn [{:keys [tx-data tx-meta db-before db-after]}]
(when (:persist-op? tx-meta true)
(db-listener/generate-rtc-ops test-helper/test-db db-before db-after tx-data)))))
:after
#(when-let [test-db-conn (conn/get-db test-helper/test-db false)]
(d/unlisten! test-db-conn ::gen-ops))})
(def clear-ops-idb-stores-fixture
{:before #(swap! ops-idb-store/stores dissoc test-helper/test-db)
:after #(swap! ops-idb-store/stores dissoc test-helper/test-db)})

View File

@ -0,0 +1,14 @@
(ns frontend.db.rtc.idb-keyval-mock
(:require [frontend.test.helper :as test-helper]))
(defmacro with-reset-idb-keyval-mock
[reset & body]
`(test-helper/with-reset ~reset
[idb-keyval/set frontend.db.rtc.idb-keyval-mock/set
idb-keyval/get frontend.db.rtc.idb-keyval-mock/get
idb-keyval/del frontend.db.rtc.idb-keyval-mock/del
idb-keyval/keys frontend.db.rtc.idb-keyval-mock/keys
idb-keyval/newStore frontend.db.rtc.idb-keyval-mock/new-store]
~@body))

View File

@ -0,0 +1,25 @@
(ns frontend.db.rtc.idb-keyval-mock
"Mock fns for frontend/idbkv.js"
(:refer-clojure :exclude [get set keys])
(:require [promesa.core :as p]))
(defrecord Store [db-name store-name *kvs])
(defn new-store [db-name store-name & _args]
(Store. db-name store-name (atom {})))
(defn get
[key store]
(p/do! (clojure.core/get @(:*kvs store) key)))
(defn set
[key val store]
(p/do! (swap! (:*kvs store) assoc key val)))
(defn del
[key store]
(p/do! (swap! (:*kvs store) dissoc key)))
(defn keys
[store]
(p/do! (clojure.core/keys @(:*kvs store))))

View File

@ -55,16 +55,3 @@
;; (.set-push-data-fn ws f))
;;; websocket ends ;;;;
;;; frontend.db.rtc.op mock
;; (def *ops-store (atom {}))
;; (defn <get-ops&local-tx
;; [repo]
;; )
;;; frontend.db.rtc.op mock ends

View File

@ -1,15 +1,42 @@
(ns frontend.db.rtc-test
(:require [clojure.test :as t :refer [deftest is use-fixtures]]
(:require ["/frontend/idbkv" :as idb-keyval]
[cljs.core.async :as async :refer [<! go timeout]]
[clojure.test :as t :refer [deftest is use-fixtures]]
[frontend.db.rtc.fixture :as rtc-fixture]
[frontend.test.helper :as test-helper]
[frontend.db.rtc.idb-keyval-mock :as idb-keyval-mock :include-macros true]
[frontend.db.rtc.op :as rtc-op]
[frontend.handler.page :as page-handler]
[frontend.test.helper :as test-helper :include-macros true]
[spy.core :as spy]))
(use-fixtures :each
test-helper/start-and-destroy-db-map-fixture
rtc-fixture/start-and-stop-rtc-loop-fixture)
rtc-fixture/listen-test-db-fixture
rtc-fixture/start-and-stop-rtc-loop-fixture
rtc-fixture/clear-ops-idb-stores-fixture)
(deftest check-idbkv-mocked
(idb-keyval-mock/with-reset-idb-keyval-mock reset
(is (= idb-keyval-mock/Store (type (idb-keyval/newStore "db-name" "store-name"))))
(reset)))
(deftest rtc-loop-init-test
(let [ws @(:*ws @rtc-fixture/*test-rtc-state)
push-data-fn (:push-data-fn ws)
last-ws-msg (first (spy/last-call push-data-fn))]
(is (= "register-graph-updates" (:action last-ws-msg)))))
(deftest gen-local-ops-test--create-page
(t/async
done
(idb-keyval-mock/with-reset-idb-keyval-mock reset
(go
(page-handler/create! "gen-local-ops-test-1" {:redirect? false :create-first-block? false})
(<! (timeout 500))
(let [{:keys [ops]} (<! (rtc-op/<get-ops&local-tx test-helper/test-db))]
(is (= 1 (count ops)))
(is (= "update-page" (first (second (first ops))))))
(reset)
(done)))))