   (reductions (fn [state {:keys [transform-fn value]}]
                 (transform-fn state value))
               {:master-field nil
-               :field-value nil
+               :field-value  nil
                :slave-fields #{}}
               (map (fn [[behaviour-name value :as behaviour]]
                      {:transform-fn (:transform (behaviour->action behaviour-name))
                       :value        value})
                    behaviours)))
 
+
+(defn dummy-behaviour [ticket-fields]
+  (let [master-field (rand-nth ticket-fields)
+        field-value (rand-nth (:possible-values master-field))
+        slave-field (rand-nth (fields-without-field ticket-fields
+                                                    master-field))]
+    [[:select-master-field master-field],
+     [:select-field-value field-value],
+     [:select-slave-field slave-field]]))
+
+(defn setup-app [ticket-fields]
+  (.appendChild (.-body js/document)
+                (let [element (.createElement js/document "div")
+                      _ (set! (.-id element) "app")]
+                  element))
+  (om/root app
+           app-state
+           {:target (. js/document (getElementById "app"))
+            :shared {:pick-channel  (chan)
+                     :ticket-fields ticket-fields}}))
+
 (deftest ^:async declarative
   ; TODO: replace these dummy fields with generators
-  (let [master-field (rand-nth dummy-ticket-fields)
-        field-value (rand-nth (:possible-values master-field))
-        slave-field (rand-nth (fields-without-field dummy-ticket-fields
-                                                    master-field))
-        behaviours [[:select-master-field master-field],
-                    [:select-field-value field-value],
-                    [:select-slave-field slave-field]]
-        states (get-states-for-behaviors behaviours)
-        behaviours-with-state-afterwards (map vector behaviours (rest states))]
+  (let [ticket-fields (first (gen/sample ticket-fields-gen))
+        behaviour (dummy-behaviour ticket-fields)
+        states (get-states-for-behaviors behaviour)
+        behaviours-with-state-afterwards (map vector behaviour (rest states))]
 
+    (setup-app ticket-fields)
     (go
       (doseq [[behaviour after-state] behaviours-with-state-afterwards]
         (behave behaviour)
         (wait-a-bit)
 
+
         (is (selection-state-matches? after-state))
         (is (state-matches-dom? after-state)))
+      (dommy/set-html! (.-body js/document) "")
       (done))))
+
 
 
 
 (set! (.-onload js/window)
       (fn []
-        (.appendChild (.-body js/document)
-                      (let [element (.createElement js/document "div")
-                            _ (set! (.-id element) "app")]
-                        element))
-        ; instantiate app component with dummy data
-        ; click on some of the things
-        ; test some stuff =)
-        (om/root app
-                 app-state
-                 {:target (. js/document (getElementById "app"))
-                  :shared {:pick-channel  (chan)
-                           :ticket-fields dummy-ticket-fields}})
         (t/run-all-tests)
         (js/setTimeout
           (fn []
             (.callPhantom js/window "exit"))
           3000)))
-
-;
-;(deftest ^:async can-make-condition
-;  (let [element->value-as-number #(-> %
-;                                      (dommy/attr :value)
-;                                      string->int)
-;        master-field-el (first (sel "div.field-list a.field"))
-;        master-field-id (element->value-as-number master-field-el)]
-;    (go
-;      (click master-field-el)
-;      (println "just clicked master field")
-;      (wait-a-bit)
-;
-;      (is (= "active" (dommy/class (dommy/parent master-field-el))))
-;
-;      (let [value-element (first (sel :a.value))
-;            value-element-value (dommy/attr value-element :value)
-;            _ (do (click value-element)
-;                  (println "just clicked value element")
-;                  (wait-a-bit)
-;                  (is (= "active" (dommy/class (dommy/parent value-element)))))
-;            slave-field-elements (take 2 (sel :.selectedField))
-;
-;            _ (do (is (not (empty? slave-field-elements)))
-;                  (doseq [slave-field slave-field-elements]
-;                    (click slave-field)
-;                    (println "just clicked a slave field")
-;                    (wait-a-bit))
-;                  (wait-a-bit)
-;                  (doseq [slave-field slave-field-elements]
-;                    (is (.contains (dommy/class slave-field) "assigned"))))
-;
-;            _ (println (:conditions @app-state))
-;
-;            ; just to make sure it doesn't add new conditions
-;            second-value-element (second (sel :a.value))
-;            _ (do
-;                (click second-value-element)
-;                (wait-a-bit))
-;
-;
-;            slave-field-element-ids (->> slave-field-elements
-;                                         (map element->value-as-number)
-;                                         set)
-;
-;            condition (first (:conditions @app-state))]
-;        (is (and (= master-field-id (:id (:master-field condition)))
-;                 (= value-element-value (:value (:field-value condition)))
-;                 (= slave-field-element-ids (set (map :id (:slave-fields condition)))))))
-;      (done))))
-;




; what does it do to state? what should app-state be after a given action?
; for each action, there should be a function that takes app-state and
; the action (incl arg) and returns the new app-state

; e.g. select-master-field will change selections to reset the others and
;

(defn behave [[behaviour-name arg]]
  (when-let [action (:element-getter (behaviour->action behaviour-name))]
    (action arg)))

(def p println)




(defn get-master-field-element [field]
  (sel1 (str "a.master-field[data-id='" (:id field) "']")))
