datahike-browser-tests 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,92 @@
1
+ (ns datahike.test.components-test
2
+ (:require
3
+ [#?(:cljs cljs.reader :clj clojure.edn) :as edn]
4
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
5
+ :clj [clojure.test :as t :refer [is deftest testing]])
6
+ [datahike.api :as d]
7
+ [datahike.db :as db]
8
+ [datahike.test.core-test :as tdc]
9
+ [datahike.impl.entity :as de]))
10
+
11
+ (t/use-fixtures :once tdc/no-namespace-maps)
12
+
13
+ #?(:cljs
14
+ (def Throwable js/Error))
15
+
16
+ (deftest test-components
17
+ (is (thrown-with-msg? Throwable
18
+ #"Bad attribute specification for :profile: \{:db/isComponent true\} should also have \{:db/valueType :db.type/ref\}"
19
+ (db/empty-db {:profile {:db/isComponent true}})))
20
+ (is (thrown-with-msg? Throwable
21
+ #"Bad attribute specification for \{:profile \{:db/isComponent \"aaa\"\}\}, expected one of #\{true false\}"
22
+ (db/empty-db {:profile {:db/isComponent "aaa" :db/valueType :db.type/ref}})))
23
+
24
+ (let [db (d/db-with
25
+ (db/empty-db {:profile {:db/valueType :db.type/ref
26
+ :db/isComponent true}})
27
+ [{:db/id 1 :name "Ivan" :profile 3}
28
+ {:db/id 3 :email "@3"}
29
+ {:db/id 4 :email "@4"}])
30
+ visible #(edn/read-string (pr-str %))
31
+ touched #(visible (de/touch %))]
32
+
33
+ (testing "touch"
34
+ (is (= (touched (d/entity db 1))
35
+ {:db/id 1
36
+ :name "Ivan"
37
+ :profile {:db/id 3
38
+ :email "@3"}}))
39
+ (is (= (touched (d/entity (d/db-with db [[:db/add 3 :profile 4]]) 1))
40
+ {:db/id 1
41
+ :name "Ivan"
42
+ :profile {:db/id 3
43
+ :email "@3"
44
+ :profile {:db/id 4
45
+ :email "@4"}}})))
46
+ (testing "retractEntity"
47
+ (let [db (d/db-with db [[:db.fn/retractEntity 1]])]
48
+ (is (= (d/q '[:find ?a ?v :where [1 ?a ?v]] db)
49
+ #{}))
50
+ (is (= (d/q '[:find ?a ?v :where [3 ?a ?v]] db)
51
+ #{}))))
52
+
53
+ (testing "retractAttribute"
54
+ (let [db (d/db-with db [[:db.fn/retractAttribute 1 :profile]])]
55
+ (is (= (d/q '[:find ?a ?v :where [3 ?a ?v]] db)
56
+ #{}))))
57
+
58
+ (testing "reverse navigation"
59
+ (is (= (visible (:_profile (d/entity db 3)))
60
+ {:db/id 1})))))
61
+
62
+ (deftest test-components-multival
63
+ (let [db (d/db-with
64
+ (db/empty-db {:profile {:db/valueType :db.type/ref
65
+ :db/cardinality :db.cardinality/many
66
+ :db/isComponent true}})
67
+ [{:db/id 1 :name "Ivan" :profile [3 4]}
68
+ {:db/id 3 :email "@3"}
69
+ {:db/id 4 :email "@4"}])
70
+ visible #(edn/read-string (pr-str %))
71
+ touched #(visible (de/touch %))]
72
+
73
+ (testing "touch"
74
+ (is (= (touched (d/entity db 1))
75
+ {:db/id 1
76
+ :name "Ivan"
77
+ :profile #{{:db/id 3 :email "@3"}
78
+ {:db/id 4 :email "@4"}}})))
79
+
80
+ (testing "retractEntity"
81
+ (let [db (d/db-with db [[:db.fn/retractEntity 1]])]
82
+ (is (= (d/q '[:find ?a ?v :in $ [?e ...] :where [?e ?a ?v]] db [1 3 4])
83
+ #{}))))
84
+
85
+ (testing "retractAttribute"
86
+ (let [db (d/db-with db [[:db.fn/retractAttribute 1 :profile]])]
87
+ (is (= (d/q '[:find ?a ?v :in $ [?e ...] :where [?e ?a ?v]] db [3 4])
88
+ #{}))))
89
+
90
+ (testing "reverse navigation"
91
+ (is (= (visible (:_profile (d/entity db 3)))
92
+ {:db/id 1})))))
@@ -0,0 +1,158 @@
1
+ (ns datahike.test.config-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
4
+ :clj [clojure.test :as t :refer [is are deftest testing]])
5
+ [datahike.config :as c]
6
+ [datahike.db :as db]
7
+ [datahike.api :as d]
8
+ [datahike.index :as di]
9
+ [datahike.index.hitchhiker-tree :as dih]
10
+ [datahike.connector :as conn]))
11
+
12
+ #?(:cljs (def Throwable js/Error))
13
+
14
+ (deftest int-from-env-test
15
+ (is (= 1000
16
+ (c/int-from-env :foo 1000))))
17
+
18
+ (deftest bool-from-env-test
19
+ (is (c/bool-from-env :foo true)))
20
+
21
+ (deftest uri-test
22
+ (let [mem-uri "datahike:mem://config-test"
23
+ file-uri "datahike:file:///tmp/config-test"]
24
+
25
+ (are [x y] (= x (c/uri->config y))
26
+ {:backend :memory :host "config-test" :uri mem-uri}
27
+ mem-uri
28
+
29
+ {:backend :file :path "/tmp/config-test" :uri file-uri}
30
+ file-uri)))
31
+
32
+ (deftest deprecated-test
33
+ (let [mem-cfg {:backend :memory
34
+ :host "deprecated-test"}
35
+ file-cfg {:backend :file
36
+ :path "/deprecated/test"}
37
+ default-new-cfg {:attribute-refs? false
38
+ :keep-history? true
39
+ :initial-tx nil
40
+ :index :datahike.index/persistent-set
41
+ :index-config {}
42
+ :schema-flexibility :write
43
+ :crypto-hash? false
44
+ :branch :db
45
+ :writer c/self-writer
46
+ :search-cache-size c/*default-search-cache-size*
47
+ :store-cache-size c/*default-store-cache-size*}]
48
+ (is (= (merge default-new-cfg
49
+ {:store {:backend :memory :id #uuid "ec3537bd-3f0d-3719-acd5-40751bbb1012"}})
50
+ (c/from-deprecated mem-cfg)))
51
+ (is (= (merge default-new-cfg
52
+ {:store {:backend :file
53
+ :path "/deprecated/test"
54
+ :id #uuid "908d33ed-b562-3301-9a9f-94b961e56f05"}})
55
+ (c/from-deprecated file-cfg)))))
56
+
57
+ (deftest load-config-test
58
+ (testing "configuration defaults"
59
+ (let [config (c/load-config)]
60
+ (is (= (merge {:store {:backend :memory}
61
+ :attribute-refs? c/*default-attribute-refs?*
62
+ :keep-history? c/*default-keep-history?*
63
+ :schema-flexibility c/*default-schema-flexibility*
64
+ :index c/*default-index*
65
+ :crypto-hash? c/*default-crypto-hash?*
66
+ :branch c/*default-db-branch*
67
+ :writer c/self-writer
68
+ :search-cache-size c/*default-search-cache-size*
69
+ :store-cache-size c/*default-store-cache-size*}
70
+ (when (seq (di/default-index-config c/*default-index*))
71
+ {:index-config (di/default-index-config c/*default-index*)}))
72
+ (update config :store dissoc :id :scope))))))
73
+
74
+ (deftest core-config-test
75
+ (testing "Schema on write in core empty database"
76
+ (is (thrown-with-msg? Throwable
77
+ #"Bad entity attribute :name at \{:db/id 1, :name \"Ivan\"\}, not defined in current schema"
78
+ (d/db-with (db/empty-db nil {:schema-flexibility :write})
79
+ [{:db/id 1 :name "Ivan" :aka ["IV" "Terrible"]}
80
+ {:db/id 2 :name "Petr" :age 37 :huh? false}])))
81
+ (is (thrown-with-msg? Throwable
82
+ #"Incomplete schema attributes, expected at least :db/valueType, :db/cardinality"
83
+ (db/empty-db {:name {:db/cardinality :db.cardinality/one}} {:schema-flexibility :write})))
84
+ (is (= #{["Alice"]}
85
+ (let [db (-> (db/empty-db {:name {:db/cardinality :db.cardinality/one :db/valueType :db.type/string}} {:schema-flexibility :write})
86
+ (d/db-with [{:name "Alice"}]))]
87
+ (d/q '[:find ?n :where [_ :name ?n]] db))))
88
+ (is (= #{["Alice"]}
89
+ (let [db (-> (db/empty-db [{:db/ident :name :db/cardinality :db.cardinality/one :db/valueType :db.type/string}]
90
+ {:schema-flexibility :write})
91
+ (d/db-with [{:name "Alice"}]))]
92
+ (d/q '[:find ?n :where [_ :name ?n]] db))))))
93
+
94
+ (deftest store-identity-config-test
95
+ (testing "different configs with equal identities"
96
+ (let [mem-start {:store {:backend :memory
97
+ :id #uuid "51de0715-1000-0000-0000-000000000001"}}
98
+ mem-other {:store {:backend :memory
99
+ :id #uuid "a107be12-1de0-7157-0000-000000000001"}}
100
+ file-start {:store {:backend :file
101
+ :path "/tmp/store-identity-test"
102
+ :id #uuid "1de07157-0000-0000-0000-000000000001"}}
103
+ file-index {:index :datahike.index/hitchhiker-tree
104
+ :store {:backend :file
105
+ :path "/tmp/store-identity-test"
106
+ :id #uuid "1de07157-0000-0000-0000-000000000001"}}
107
+ mem-named {:name "has-name"
108
+ :store {:backend :memory
109
+ :id #uuid "51de0715-1000-0000-0000-000000000001"}}
110
+ mem-same {:store {:backend :memory
111
+ :id #uuid "51de0715-1000-0000-0000-000000000001"
112
+ :irrelevant-property true}}]
113
+ (is (thrown-with-msg? Throwable
114
+ #"Store identity mismatch"
115
+ (conn/ensure-stored-config-consistency mem-start mem-other)))
116
+ (is (not= mem-start mem-other))
117
+ (is (thrown-with-msg? Throwable
118
+ #"Configuration does not match stored configuration."
119
+ (conn/ensure-stored-config-consistency file-start file-index)))
120
+ (is (not= file-start file-index))
121
+ (is (thrown-with-msg? Throwable
122
+ #"Store identity mismatch"
123
+ (conn/ensure-stored-config-consistency mem-start file-start)))
124
+ (is (not= mem-start file-start))
125
+ (is (nil? (conn/ensure-stored-config-consistency mem-start mem-named)))
126
+ (is (not= mem-start mem-named))
127
+ (is (nil? (conn/ensure-stored-config-consistency mem-start mem-same)))
128
+ (is (not= mem-start mem-same))
129
+ (is (nil? (conn/ensure-stored-config-consistency mem-named mem-same)))
130
+ (is (not= mem-named mem-same)))))
131
+
132
+ (deftest store-identity-connection-test
133
+ (testing "different connections with equal identities"
134
+ (let [mem-start {:store {:backend :memory
135
+ :id #uuid "51dec000-ec71-0000-0000-000000000001"}}
136
+ mem-other {:store {:backend :memory
137
+ :id #uuid "a107be12-c000-ec71-0000-000000000001"}}
138
+ file-start {:store {:backend :file
139
+ :path "/tmp/store-connection-test"
140
+ :id #uuid "c000ec71-0000-0000-0000-000000000001"}}
141
+ file-index {:index :datahike.index/hitchhiker-tree
142
+ :store {:backend :file
143
+ :path "/tmp/store-connection-test"
144
+ :id #uuid "c000ec71-0000-0000-0000-000000000001"}}
145
+ mem-named {:name "has-name"
146
+ :store {:backend :memory
147
+ :id #uuid "51dec000-ec71-0000-0000-000000000001"}}
148
+ mem-same {:store {:backend :memory
149
+ :id #uuid "51dec000-ec71-0000-0000-000000000001"
150
+ :irrelevant-property true}}
151
+ _ (doall (map d/delete-database [mem-start mem-other file-start file-index mem-named mem-same]))]
152
+ (d/create-database mem-start)
153
+ (is (= (d/connect mem-start) (d/connect mem-named) (d/connect mem-same)))
154
+ (d/create-database file-start)
155
+ (d/connect file-start)
156
+ (is (thrown-with-msg? Throwable
157
+ #"Configuration does not match existing connections."
158
+ (d/connect file-index))))))
@@ -0,0 +1,105 @@
1
+ (ns datahike.test.core-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest]]
4
+ :clj [clojure.test :as t :refer [is deftest]])
5
+ [clojure.walk]
6
+ [clojure.data]
7
+ #?(:clj [kaocha.stacktrace])
8
+ [datahike.core :as dc]
9
+ [datahike.constants :as const]
10
+ [datahike.impl.entity :as de]
11
+ #?(:cljs [datahike.test.cljs])))
12
+
13
+ #?(:cljs
14
+ (enable-console-print!))
15
+
16
+ ;; Added special case for printing ex-data of ExceptionInfo
17
+ #?(:cljs
18
+ (defmethod t/report [::t/default :error] [m]
19
+ (t/inc-report-counter! :error)
20
+ (println "\nERROR in" (t/testing-vars-str m))
21
+ (when (seq (:testing-contexts (t/get-current-env)))
22
+ (println (t/testing-contexts-str)))
23
+ (when-let [message (:message m)] (println message))
24
+ (println "expected:" (pr-str (:expected m)))
25
+ (print " actual: ")
26
+ (let [actual (:actual m)]
27
+ (cond
28
+ (instance? ExceptionInfo actual)
29
+ (println (.-stack actual) "\n" (pr-str (ex-data actual)))
30
+ (instance? js/Error actual)
31
+ (println (.-stack actual))
32
+ :else
33
+ (prn actual)))))
34
+
35
+ #?(:cljs (def test-summary (atom nil)))
36
+ #?(:cljs (defmethod t/report [::t/default :end-run-tests] [m]
37
+ (reset! test-summary (dissoc m :type))))
38
+
39
+ (defn wrap-res [f]
40
+ #?(:cljs (do (f) (clj->js @test-summary))
41
+ :clj (let [res (f)]
42
+ (when (pos? (+ (:fail res) (:error res)))
43
+ (System/exit 1)))))
44
+
45
+ (defn entity-map [db e]
46
+ (when-let [entity (dc/entity db e)]
47
+ (->> (assoc (into {} entity) :db/id (:db/id entity))
48
+ (clojure.walk/prewalk #(if (de/entity? %)
49
+ {:db/id (:db/id %)}
50
+ %)))))
51
+
52
+ (defn all-datoms [db]
53
+ (into #{} (map (juxt :e :a :v)) (dc/datoms db :eavt)))
54
+
55
+ (defn no-namespace-maps [t]
56
+ (binding [*print-namespace-maps* false]
57
+ (t)))
58
+
59
+ ;; Filter Kaocha frames from exceptions
60
+
61
+ #?(:clj
62
+ (alter-var-root #'kaocha.stacktrace/*stacktrace-filters* (constantly ["java." "clojure." "kaocha." "orchestra."])))
63
+
64
+ ;; Core tests
65
+
66
+ (deftest test-protocols
67
+ (let [schema {:aka {:db/cardinality :db.cardinality/many}}
68
+ db (dc/db-with (dc/empty-db schema)
69
+ [{:db/id 1 :name "Ivan" :aka ["IV" "Terrible"]}
70
+ {:db/id 2 :name "Petr" :age 37 :huh? false}])]
71
+ (is (= (dc/empty-db schema)
72
+ (empty db)))
73
+ (is (= 6 (count db)))
74
+ (is (= (set (seq db))
75
+ #{(dc/datom 1 :aka "IV")
76
+ (dc/datom 1 :aka "Terrible")
77
+ (dc/datom 1 :name "Ivan")
78
+ (dc/datom 2 :age 37)
79
+ (dc/datom 2 :name "Petr")
80
+ (dc/datom 2 :huh? false)}))))
81
+
82
+ (defn- now []
83
+ #?(:clj (System/currentTimeMillis)
84
+ :cljs (.getTime (js/Date.))))
85
+
86
+ (deftest test-uuid
87
+ (let [now-ms (loop []
88
+ (let [ts (now)]
89
+ (if (> (mod ts 1000) 900) ;; sleeping over end of a second
90
+ (recur)
91
+ ts)))
92
+ now (int (/ now-ms 1000))]
93
+ (is (= (* 1000 now) (dc/squuid-time-millis (dc/squuid))))
94
+ (is (not= (dc/squuid) (dc/squuid)))
95
+ (is (= (subs (str (dc/squuid)) 0 8)
96
+ (subs (str (dc/squuid)) 0 8)))))
97
+
98
+ (deftest test-diff
99
+ (is (= [[(dc/datom 1 :b 2) (dc/datom 1 :c 4) (dc/datom 2 :a 1)]
100
+ [(dc/datom 1 :b 3) (dc/datom 1 :d 5)]
101
+ [(dc/datom 1 :a 1)]]
102
+ (clojure.data/diff
103
+ (dc/db-with (dc/empty-db) [{:a 1 :b 2 :c 4} {:a 1}])
104
+ (dc/db-with (dc/empty-db) [{:a 1 :b 3 :d 5}])))))
105
+
@@ -0,0 +1,44 @@
1
+ (ns datahike.test.datom-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
4
+ :clj [clojure.test :as t :refer [is deftest testing]])
5
+ [datahike.datom :as d :refer [datom]]))
6
+
7
+ (deftest datom-impl
8
+ (let [d (datom 123 :foo/bar "foobar")]
9
+ (is (= [:e 123]
10
+ (find d :e)))
11
+ (is (= {:e 123
12
+ :a :foo/bar
13
+ :v "foobar"}
14
+ (select-keys d [:e :a :v])))
15
+ (is (= 123 (d :e)))))
16
+
17
+ (deftest prefix-comparators
18
+ (testing "Prefix comparators match on e,a,v ignoring tx"
19
+ (let [d1 (datom 1 :name "Alice" 100)
20
+ d2 (datom 1 :name "Alice" 200) ; same e,a,v but different tx
21
+ d3 (datom 1 :name "Bob" 100)] ; different v
22
+
23
+ (testing "eavt prefix"
24
+ (is (= 0 (d/cmp-datoms-eavt-prefix d1 d2))
25
+ "Should match datoms with same e,a,v but different tx")
26
+ (is (not= 0 (d/cmp-datoms-eavt-prefix d1 d3))
27
+ "Should not match datoms with different v"))
28
+
29
+ (testing "aevt prefix"
30
+ (is (= 0 (d/cmp-datoms-aevt-prefix d1 d2))
31
+ "Should match datoms with same a,e,v but different tx")
32
+ (is (not= 0 (d/cmp-datoms-aevt-prefix d1 d3))
33
+ "Should not match datoms with different v"))
34
+
35
+ (testing "avet prefix"
36
+ (is (= 0 (d/cmp-datoms-avet-prefix d1 d2))
37
+ "Should match datoms with same a,v,e but different tx")
38
+ (is (not= 0 (d/cmp-datoms-avet-prefix d1 d3))
39
+ "Should not match datoms with different v"))))
40
+
41
+ (testing "index-type->cmp-prefix returns correct comparator"
42
+ (is (= d/cmp-datoms-eavt-prefix (d/index-type->cmp-prefix :eavt)))
43
+ (is (= d/cmp-datoms-aevt-prefix (d/index-type->cmp-prefix :aevt)))
44
+ (is (= d/cmp-datoms-avet-prefix (d/index-type->cmp-prefix :avet)))))
@@ -0,0 +1,54 @@
1
+ (ns datahike.test.db-test
2
+ (:require
3
+ [clojure.data]
4
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
5
+ :clj [clojure.test :as t :refer [is deftest testing]])
6
+ [datahike.api :as d]
7
+ [datahike.constants :as const]
8
+ [datahike.test.core-test]
9
+ [datahike.db :as db #?@(:cljs [:refer-macros [defrecord-updatable]]
10
+ :clj [:refer [defrecord-updatable]])]))
11
+
12
+ #?(:cljs (def Throwable js/Error))
13
+
14
+ ;; verify that defrecord-updatable works with compiler/core macro configuration
15
+ ;; define dummy class which redefines hash, could produce either
16
+ ;; compiler or runtime error
17
+ ;;
18
+ (defrecord-updatable HashBeef [x]
19
+ #?@(:cljs [IHash (-hash [hb] 0xBEEF)]
20
+ :clj [clojure.lang.IHashEq (hasheq [hb] 0xBEEF)]))
21
+
22
+ (deftest test-defrecord-updatable
23
+ (is (= 0xBEEF (-> (map->HashBeef {:x :ignored}) hash))))
24
+
25
+ (deftest test-fn-hash-changes
26
+ (let [db (d/db-with (db/empty-db)
27
+ [{:db/id 1 :name "Konrad"}])
28
+ r1 (d/db-with db [[:db.fn/retractEntity 1]])
29
+ r2 (d/db-with db [[:db.fn/retractEntity 1]])]
30
+ (is (= (hash r1) (hash r2)))))
31
+
32
+ (deftest test-equiv-db-hash
33
+ (let [db (d/db-with (db/empty-db)
34
+ [{:db/id 1 :name "Konrad"}])
35
+ r1 (d/db-with db [[:db.fn/retractEntity 1]])]
36
+ (is (= (hash (db/empty-db)) (hash r1)))))
37
+
38
+ (deftest empty-db-with-schema
39
+ (testing "Test old write schema"
40
+ (is (thrown-with-msg? Throwable
41
+ #"Incomplete schema attributes, expected at least :db/valueType, :db/cardinality"
42
+ (db/empty-db {:name {:db/cardinality :db.cardinality/many}} {:schema-flexibility :write})))
43
+ (is (= (merge const/non-ref-implicit-schema
44
+ {:name {:db/cardinality :db.cardinality/one :db/valueType :db.type/string}})
45
+ (:schema (db/empty-db {:name {:db/cardinality :db.cardinality/one
46
+ :db/valueType :db.type/string}}
47
+ {:schema-flexibility :write}))))
48
+
49
+ (is (= (merge const/non-ref-implicit-schema
50
+ {:name {:db/ident :name :db/cardinality :db.cardinality/one :db/valueType :db.type/string}})
51
+ (:schema (db/empty-db [{:db/ident :name
52
+ :db/cardinality :db.cardinality/one
53
+ :db/valueType :db.type/string}]
54
+ {:schema-flexibility :write}))))))
@@ -0,0 +1,159 @@
1
+ (ns datahike.test.entity-spec-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
4
+ :clj [clojure.test :as t :refer [is deftest testing]])
5
+ [datahike.test.core-test]
6
+ [datahike.api :as d]))
7
+
8
+ #?(:cljs (def Throwable js/Error))
9
+
10
+ (def cfg-template {:store {:backend :memory
11
+ :id #uuid "001c0000-0000-0000-0000-00000000001c"}
12
+ :keep-history? false
13
+ :schema-flexibility :write})
14
+
15
+ (def schema-template
16
+ [{:db/ident :account/email
17
+ :db/valueType :db.type/string
18
+ :db/unique :db.unique/identity
19
+ :db/cardinality :db.cardinality/one}
20
+ {:db/ident :account/balance
21
+ :db/valueType :db.type/long
22
+ :db/cardinality :db.cardinality/one}])
23
+
24
+ (defn setup-db [cfg]
25
+ (d/delete-database cfg)
26
+ (d/create-database cfg)
27
+ (d/connect cfg))
28
+
29
+ (deftest test-attribute-assertion
30
+ (let [schema (conj schema-template
31
+ {:db/ident :account/guard
32
+ :db.entity/attrs [:account/email :account/balance]})
33
+ valid-account {:account/email "antonia@a.corp"
34
+ :account/balance 1000}
35
+ invalid-account {:account/email "arthur@b.corp"}
36
+ empty-account {}]
37
+ (letfn [(tx-with-ensure [conn account]
38
+ (d/transact conn [(assoc account :db/ensure :account/guard)]))]
39
+ (testing "with write schema flexibility"
40
+ (let [cfg (-> cfg-template
41
+ (assoc-in [:store :id] #uuid "a77e0000-0000-0000-0000-000000000001")
42
+ (assoc :initial-tx schema))
43
+ conn (setup-db cfg)]
44
+ (testing "assert valid account"
45
+ (let [{:keys [db-after]} (tx-with-ensure conn valid-account)]
46
+ (is (= valid-account (d/pull db-after '[:account/email :account/balance] [:account/email (:account/email valid-account)])))))
47
+ (testing "assert invalid account"
48
+ (is (thrown-with-msg? Throwable
49
+ #"Entity 5 missing attributes #\{:account/balance\} of spec :account/guard"
50
+ (tx-with-ensure conn invalid-account))))
51
+ (testing "assert empty entity"
52
+ (is (thrown-with-msg? Throwable
53
+ #"Entity 5 missing attributes #\{:account/balance :account/email\} of spec :account/guard"
54
+ (tx-with-ensure conn empty-account))))
55
+ (d/release conn)))
56
+ (testing "with read schema flexibility"
57
+ (let [cfg (-> cfg-template
58
+ (assoc :schema-flexibility :read)
59
+ (assoc-in [:store :id] #uuid "a77e0000-0000-0000-0000-000000000002")
60
+ (assoc :initial-tx schema))
61
+ conn (setup-db cfg)]
62
+ (testing "assert valid account"
63
+ (let [{:keys [db-after]} (tx-with-ensure conn valid-account)]
64
+ (is (= valid-account (d/pull db-after '[:account/email :account/balance] [:account/email (:account/email valid-account)])))))
65
+ (testing "assert invalid account"
66
+ (is (thrown-with-msg? Throwable
67
+ #"Entity 5 missing attributes #\{:account/balance\} of spec :account/guard"
68
+ (tx-with-ensure conn invalid-account))))
69
+ (testing "assert empty entity"
70
+ (is (thrown-with-msg? Throwable
71
+ #"Entity 5 missing attributes #\{:account/balance :account/email\} of spec :account/guard"
72
+ (tx-with-ensure conn empty-account))))
73
+ (d/release conn))))))
74
+
75
+ (defn is-email? [db eid]
76
+ ;; email could not exist
77
+ (if-let [email (:account/email (d/entity db eid))]
78
+ (seq (re-find #"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" email))
79
+ false))
80
+
81
+ (defn positive-balance? [db eid]
82
+ ;; balance could not exist
83
+ (if-let [balance (-> (d/entity db eid) :account/balance)]
84
+ (< 0 balance)
85
+ false))
86
+
87
+ (deftest test-predicate-assertion
88
+ (let [schema (conj schema-template
89
+ {:db/ident :account/guard
90
+ :db.entity/preds ['datahike.test.entity-spec-test/is-email? 'datahike.test.entity-spec-test/positive-balance?]})
91
+ valid-account {:account/email "greta@a.corp"
92
+ :account/balance 1000}
93
+ invalid-account {:account/email "georg"
94
+ :account/balance 500}
95
+ invalid-account-multiple {:account/email "gustav"
96
+ :account/balance -500}
97
+ empty-account {}
98
+ cfg (-> cfg-template
99
+ (assoc-in [:store :id] #uuid "a77e0000-0000-0000-0000-000000000003")
100
+ (assoc :initial-tx schema))
101
+ conn (setup-db cfg)]
102
+ (letfn [(tx-with-ensure [account]
103
+ (d/transact conn {:tx-data [(assoc account :db/ensure :account/guard)]}))]
104
+ (testing "assert valid account"
105
+ (let [{:keys [db-after]} (tx-with-ensure valid-account)]
106
+ (is (= valid-account (d/pull db-after '[:account/email :account/balance] [:account/email (:account/email valid-account)])))))
107
+ (testing "assert invalid account with one invalid predicate"
108
+ (is (thrown-with-msg? Throwable
109
+ #"Entity 5 failed predicates #\{datahike.test.entity-spec-test/is-email\?\} of spec :account/guard"
110
+ (tx-with-ensure invalid-account))))
111
+ (testing "assert invalid account with mulitple invalid predicates"
112
+ (is (thrown-with-msg? Throwable
113
+ #"Entity 5 failed predicates #\{datahike.test.entity-spec-test/positive-balance\? datahike.test.entity-spec-test/is-email\?\} of spec :account/guard"
114
+ (tx-with-ensure invalid-account-multiple))))
115
+ (testing "assert empty account"
116
+ (is (thrown-with-msg? Throwable
117
+ #"Entity 5 failed predicates #\{datahike.test.entity-spec-test/positive-balance\? datahike.test.entity-spec-test/is-email\?\} of spec :account/guard"
118
+ (tx-with-ensure empty-account)))))
119
+ (d/release conn)))
120
+
121
+ (deftest test-attribute-and-predicate-assertion
122
+ (let [schema (conj schema-template
123
+ {:db/ident :account/guard
124
+ :db.entity/attrs [:account/email :account/balance]
125
+ :db.entity/preds ['datahike.test.entity-spec-test/is-email? 'datahike.test.entity-spec-test/positive-balance?]})
126
+ valid-account {:account/email "karla@a.corp"
127
+ :account/balance 1000}
128
+ invalid-account-attr {:account/email "konstantin@b.corp"}
129
+ invalid-account-pred {:account/email "kaspar"
130
+ :account/balance 500}
131
+ invalid-account-pred-multiple {:account/email "katharina"
132
+ :account/balance -500}
133
+ empty-account {}
134
+ cfg (-> cfg-template
135
+ (assoc-in [:store :id] #uuid "a77e0000-0000-0000-0000-000000000004")
136
+ (assoc :initial-tx schema))
137
+ conn (setup-db cfg)]
138
+ (letfn [(tx-with-ensure [account]
139
+ (d/transact conn {:tx-data [(assoc account :db/ensure :account/guard)]}))]
140
+ (testing "assert valid account"
141
+ (let [{:keys [db-after]} (tx-with-ensure valid-account)]
142
+ (is (= valid-account (d/pull db-after '[:account/email :account/balance] [:account/email (:account/email valid-account)])))))
143
+ (testing "assert invalid account with missing attributes"
144
+ (is (thrown-with-msg? Throwable
145
+ #"Entity 5 missing attributes #\{:account/balance\} of spec :account/guard"
146
+ (tx-with-ensure invalid-account-attr))))
147
+ (testing "assert invalid account with one invalid predicate"
148
+ (is (thrown-with-msg? Throwable
149
+ #"Entity 5 failed predicates #\{datahike.test.entity-spec-test/is-email\?\} of spec :account/guard"
150
+ (tx-with-ensure invalid-account-pred))))
151
+ (testing "assert invalid account with mulitple invalid predicates"
152
+ (is (thrown-with-msg? Throwable
153
+ #"Entity 5 failed predicates #\{datahike.test.entity-spec-test/positive-balance\? datahike.test.entity-spec-test/is-email\?\} of spec :account/guard"
154
+ (tx-with-ensure invalid-account-pred-multiple))))
155
+ (testing "assert empty account with required attributes precidenting over predicates"
156
+ (is (thrown-with-msg? Throwable
157
+ #"Entity 5 missing attributes #\{:account/balance :account/email\} of spec :account/guard"
158
+ (tx-with-ensure empty-account)))))
159
+ (d/release conn)))