forked from tonsky/datascript
/
entity.cljc
94 lines (83 loc) · 3.79 KB
/
entity.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(ns datascript.test.entity
(:require
[#?(:cljs cljs.reader :clj clojure.edn) :as edn]
#?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
:clj [clojure.test :as t :refer [is are deftest testing]])
[datascript.core :as d]
[datascript.db :as db]
[datascript.test.core :as tdc])
#?(:clj
(:import [clojure.lang ExceptionInfo])))
(deftest test-entity
(let [db (-> (d/empty-db {:aka {:db/cardinality :db.cardinality/many}})
(d/db-with [{:db/id 1, :name "Ivan", :age 19, :aka ["X" "Y"]}
{:db/id 2, :name "Ivan", :sex "male", :aka ["Z"]}
[:db/add 3 :huh? false]]))
e (d/entity db 1)]
(is (= (:db/id e) 1))
(is (identical? (d/entity-db e) db))
(is (= (:name e) "Ivan"))
(is (= (e :name) "Ivan")) ; IFn form
(is (= (:age e) 19))
(is (= (:aka e) #{"X" "Y"}))
(is (= true (contains? e :age)))
(is (= false (contains? e :not-found)))
(is (= (into {} e)
{:name "Ivan", :age 19, :aka #{"X" "Y"}}))
(is (= (into {} (d/entity db 1))
{:name "Ivan", :age 19, :aka #{"X" "Y"}}))
(is (= (into {} (d/entity db 2))
{:name "Ivan", :sex "male", :aka #{"Z"}}))
(let [e3 (d/entity db 3)]
(is (= (into {} e3) {:huh? false})) ; Force caching.
(is (false? (:huh? e3))))
(is (= (pr-str (d/entity db 1)) "{:db/id 1}"))
(is (= (pr-str (let [e (d/entity db 1)] (:unknown e) e)) "{:db/id 1}"))
;; read back in to account for unordered-ness
(is (= (edn/read-string (pr-str (let [e (d/entity db 1)] (:name e) e)))
(edn/read-string "{:name \"Ivan\", :db/id 1}")))))
(deftest test-entity-refs
(let [db (-> (d/empty-db {:father {:db/valueType :db.type/ref}
:children {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}})
(d/db-with
[{:db/id 1, :children [10]}
{:db/id 10, :father 1, :children [100 101]}
{:db/id 100, :father 10}
{:db/id 101, :father 10}]))
e #(d/entity db %)]
(is (= (:children (e 1)) #{(e 10)}))
(is (= (:children (e 10)) #{(e 100) (e 101)}))
(testing "empty attribute"
(is (= (:children (e 100)) nil)))
(testing "nested navigation"
(is (= (-> (e 1) :children first :children) #{(e 100) (e 101)}))
(is (= (-> (e 10) :children first :father) (e 10)))
(is (= (-> (e 10) :father :children) #{(e 10)}))
(testing "after touch"
(let [e1 (e 1)
e10 (e 10)]
(d/touch e1)
(d/touch e10)
(is (= (-> e1 :children first :children) #{(e 100) (e 101)}))
(is (= (-> e10 :children first :father) (e 10)))
(is (= (-> e10 :father :children) #{(e 10)})))))
(testing "backward navigation"
(is (= (:_children (e 1)) nil))
(is (= (:_father (e 1)) #{(e 10)}))
(is (= (:_children (e 10)) #{(e 1)}))
(is (= (:_father (e 10)) #{(e 100) (e 101)}))
(is (= (-> (e 100) :_children first :_children) #{(e 1)}))
)))
(deftest test-entity-misses
(let [db (-> (d/empty-db {:name {:db/unique :db.unique/identity}})
(d/db-with [{:db/id 1, :name "Ivan"}
{:db/id 2, :name "Oleg"}]))]
(is (nil? (d/entity db nil)))
(is (nil? (d/entity db "abc")))
;;(is (nil? (d/entity db :keyword)))
(is (thrown-with-msg? ExceptionInfo #"You must have :db/ident marked as :db/unique in your schema to use keyword refs" (d/entity db :keyword)))
(is (nil? (d/entity db [:name "Petr"])))
(is (= 777 (:db/id (d/entity db 777))))
(is (thrown-with-msg? ExceptionInfo #"Lookup ref attribute should be marked as :db/unique"
(d/entity db [:not-an-attr 777])))))