Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
(ns components.datomic.core-test
(:require
[clojure.pprint :refer [pprint]]
[clojure.test :refer :all]
[datomic.client.api :as d]
[datomic.client.api.impl :as di]
[datomic.api :as db-free])
(:import (java.util UUID)))
(declare test-conn)
; client code below, un-aware of type of db
(deftest query-empty-db
(let [conn (test-conn)
db (d/db conn)]
(is (= [] (d/q '[:find ?e
:in $
:where
[?e :user/username ?n]]
db))
"No entities present")))
(deftest query-populated-db
(let [conn (test-conn)
{:keys [db-after tempids] :as tx-result} (d/transact conn {:tx-data [{:db/id "tempid" ; client api uses strings for tempids
:user/username "Steve"}]})
entity-id (get tempids "tempid")]
(is (= {:db/id entity-id
:user/username "Steve"} (d/pull db-after '[*] entity-id))
"pulls all attributes ok")
(is (= [[entity-id "Steve"]] (d/q '[:find ?e ?n
:in $ ?e
:where
[?e :user/username ?n]]
db-after
entity-id))
"query returns entity ok")
(is (= [[{:user/username "Steve"}]] (d/q '[:find (pull ?e [:user/username])
:in $ ?e
:where]
db-after
entity-id))
"query with pull expr ok")))
;;;;;;; TEST SETUP USING IN-MEM LOCAL DB
(defn- todo
[]
(throw (ex-info "unsupported TODO" {})))
(defrecord QueryableMemDB
[in-mem-db]
d/Db
(pull [db selector eid]
(db-free/pull in-mem-db selector eid))
; TODO all fns below need delegation
(pull [db arg-map] (todo))
(as-of [db time-point] (todo))
(datoms [db arg-map] (todo))
(db-stats [db] (todo))
(history [db] (todo))
(index-range [db arg-map] (todo))
(since [db t] (todo))
(with [db arg-map] (todo))
; Queryable is required to work with the d/q fn in datomic.client.api
di/Queryable ; <<<< is considered public????
(q [_ arg-map]
(let [args (->> (:args arg-map)
(map (fn lift-db [v]
(if (instance? QueryableMemDB v)
(:in-mem-db v)
v))))]
(-> (partial db-free/q (:query arg-map))
(apply args)
; return a vector to emulate client api behaviour
vec))))
(defrecord ClientMemConnection
[in-mem-conn]
d/Connection ; < public/documented API - should be stable
(db [_] (->QueryableMemDB (db-free/db in-mem-conn)))
(transact [_ arg-map] (-> @(db-free/transact in-mem-conn (:tx-data arg-map))
; need to wrap the 2 db-results so they can be used for reads
(update :db-before ->QueryableMemDB)
(update :db-after ->QueryableMemDB)))
(tx-range [_ arg-map] (todo))
(with-db [_] (todo)))
(def test-schema [{:db/ident :user/username
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}])
(def ^:dynamic *test-conn*)
(defn- test-conn [] *test-conn*)
(defn once-fixtures
([schema-resources] (once-fixtures schema-resources {}))
([schema-resources {:keys [extras uri]
:or {uri (str "datomic:mem://test-" (UUID/randomUUID))}
:as opts}]
(fn [test]
(let [_ (db-free/create-database uri)
conn (db-free/connect uri)
conn (->ClientMemConnection conn)]
(binding [*test-conn* conn]
(d/transact conn {:tx-data test-schema})
(try
(test)
(finally
(db-free/delete-database uri))))))))
(use-fixtures :once (once-fixtures test-schema))
(defproject components "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.9.0"]
[com.datomic/client-cloud "0.8.54"]
]
:profiles {:dev {:dependencies [[com.datomic/datomic-free "0.9.5561.62"]]}}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment