I'm modelling a many-to-many user
to team
relationship with specmonstah and wondering if I'm missing a trick or engaging in any bad practice wrt. to the generation of test fixture data:
(s/def ::user (s/keys :req-un [::id
::email
::password]))
(s/def ::team (s/keys :req-un [::id]))
(s/def ::empty-map (s/with-gen map? #(gen/fmap (fn [_] {}) (s/gen integer?))))
(s/def ::team-user ::empty-map)
(def schema
{:user {:prefix :u
:spec ::user
:relations {:industry-id [:industry :id]}}
:team {:prefix :tm
:spec ::team
:relations {:primary-user-id [:user :id]}}
:team-user {:prefix :tmu
:spec ::team-user
:relations {:team-id [:team :id]
:user-id [:user :id]}}})
;; Note: using Honey SQL
(defmulti insert-record (fn [db ent-type spec-gen] ent-type))
(defmethod insert-record :user
[db ent-type spec-gen]
(let [encrypted-password (hash-password db (:password spec-gen))
attrs (-> spec-gen
(assoc :password encrypted-password))]
{:insert-into :users
:values [attrs]}))
(defn ent-type->table-name [ent-type]
(keyword (inflections/plural (name ent-type))))
(defmethod insert-record :default [db ent-type spec-gen]
{:insert-into (ent-type->table-name ent-type)
:values [spec-gen]})
(defn insert
([db] (insert db {}))
([db options]
(fn [_ {:keys [spec-gen ent-type]}]
(database/execute! db (insert-record db ent-type spec-gen) options))))
;; Fixture helper
(defn fixture-data! [db specmonstah-query]
(-> (sg/ent-db-spec-gen {:schema schema} specmonstah-query)
(sm/visit-ents :insert (insert db))
(sm/attr-map :spec-gen)))
;; Test driver
(deftest ^:system team-setup-test
(st/system-test
(fn [{:keys [database]}]
(let [spec-data (tu/fixture-data!
database
{:team-user [[1]]})]
;; Creates a team of one user, who is also the team owner (primary)
;; Assertions etc...
))))
I'm including outline code for driver/fixture generation side of things, but my question relates to the schema
definition in particularHere's the physical model:
I don't feel great about generating team_users
test data via (s/def ::team-user ::empty-map)
and
:team-user {:prefix :tmu
:spec ::team-user
:relations {:team-id [:team :id]
:user-id [:user :id]}}
but can't think of any other way to represent this atm, would welcome suggestionsYou're looking for something like this?
(s/def ::user (s/keys :req-un [:user/id
:user/email
:user/password]))
(s/def :team/id ::id)
(s/def :team/owner ::id)
(s/def ::team (s/keys :req-un [:team/id
:team/owner]))
(s/def :team-user/team-id ::id)
(s/def :team-user/user-id ::id)
(s/def ::team-user (s/keys :req-un [:team-user/team-id
:team-user/user-id]))
(def schema
{:user {:prefix :u
:spec ::user}
:team {:prefix :tm
:spec ::team
:relations {:owner [:user :id]}}
:team-user {:prefix :tmu
:spec ::team-user
:relations {:team-id [:team :id]
:user-id [:user :id]}}})
(sg/ent-db-spec-gen-attr {:schema schema} {:team-user [[1]]})