diff --git a/integration/grub/integration_test.clj b/integration/grub/integration_test.clj index fff6b5e..ca0db73 100644 --- a/integration/grub/integration_test.clj +++ b/integration/grub/integration_test.clj @@ -1,5 +1,6 @@ (ns grub.integration-test - (:require [clj-webdriver.taxi :as taxi] + (:require [grub.db :as db] + [clj-webdriver.taxi :as taxi] [clj-webdriver.core :as webdriver] [clojure.test :as test])) @@ -23,20 +24,25 @@ (add-grub driver1 grub)) (doseq [grub grubs] (test/is (taxi/find-element driver2 {:text grub}) - "Added grubs should appear in other browser")))) + "Added grubs should appear in other browser"))) + (db/clear-grubs)) (defn test-grubs-are-stored-on-server [url driver] (taxi/to driver url) (let [grubs (repeatedly 4 get-rand-grub)] (doseq [grub grubs] (add-grub driver grub)) + (Thread/sleep 200) (taxi/refresh driver) + (Thread/sleep 200) (doseq [grub grubs] (test/is (taxi/find-element driver {:text grub}) - "Previously added grubs should be loaded on refresh")))) + "Previously added grubs should be loaded on refresh"))) + (db/clear-grubs)) (defn run [port] + (db/connect-and-handle-events "grub-integration-test") (let [site-url (str "http://localhost:" port)] (println "Starting integration test") (let [driver1 (get-driver site-url) @@ -44,4 +50,5 @@ (test-adding-grubs site-url driver1 driver2) (test-grubs-are-stored-on-server site-url driver1) (taxi/quit driver1) - (taxi/quit driver2)))) + (taxi/quit driver2))) + (db/clear-grubs)) diff --git a/spec/clj/grub/db_spec.clj b/spec/clj/grub/db_spec.clj index 0545ddb..40458af 100644 --- a/spec/clj/grub/db_spec.clj +++ b/spec/clj/grub/db_spec.clj @@ -17,18 +17,21 @@ (describe "grub.db" (before-all (db/connect-and-handle-events test-db)) - (before (mc/drop db/grub-collection)) - (describe "Create grub" - (it "should create a grub when a create event comes" + (before (db/clear-grubs)) + (describe "Add" + (it "should add a grub when an add event comes" (let [test-grub "testgrub" test-id 12345] - (>!! @db/incoming-events {:event :create :_id test-id :grub test-grub}) + (>!! @db/incoming-events {:event :add + :_id test-id + :grub test-grub + :completed false}) (short-delay) (should= {:_id test-id :grub test-grub :completed false} (mc/find-one-as-map db/grub-collection {:_id test-id}))))) - (describe "Complete grub" + (describe "Complete" (it "should complete a grub when a complete event comes" (let [test-grub {:_id 123456 :completed false}] (mc/insert db/grub-collection test-grub) @@ -38,7 +41,7 @@ {:_id (:_id test-grub) :completed true} (mc/find-one-as-map db/grub-collection {:_id (:_id test-grub)}))))) - (describe "Uncomplete grub" + (describe "Uncomplete" (it "should uncomplete a grub when an uncomplete event comes" (let [test-grub {:_id 123456 :completed true}] (mc/insert db/grub-collection test-grub) @@ -48,7 +51,7 @@ {:_id (:_id test-grub) :completed false} (mc/find-one-as-map db/grub-collection {:_id (:_id test-grub)}))))) - (describe "Delete grub" + (describe "Delete" (it "should delete a grub when a delete event comes" (let [test-grub {:_id 123456 :completed true}] (mc/insert db/grub-collection test-grub) diff --git a/spec/cljs/state_spec.cljs b/spec/cljs/state_spec.cljs index dcf63da..b568cab 100644 --- a/spec/cljs/state_spec.cljs +++ b/spec/cljs/state_spec.cljs @@ -7,56 +7,61 @@ [grub.macros :refer [log logs]])) (describe - "grub state" - (before (reset! state/grubs [])) + "State" - (describe "Add grub" - (it "should add a grub to the state when an add event comes" - (let [test-grub {:_id 12345 :grub "testgrub" :completed true} - add-event (assoc test-grub :event :add)] - (state/handle-event add-event) - (should-contain test-grub @state/grubs)))) + (describe + "event handling:" + (before (reset! state/grubs [])) - (describe "Create grub" - (it "should add a new grub to the state when a create event comes" - (let [test-grub {:grub "testgrub"} - expected-grub (assoc test-grub :completed false) - create-event (assoc test-grub :event :create)] - (state/handle-event create-event) - (let [created-grub (first @state/grubs)] - (should= (:grub created-grub) (:grub test-grub))))) - (it "should generate an _id for the new grub" - (let [test-grub {:grub "testgrub"} - create-event (assoc test-grub :event :create)] - (state/handle-event create-event) - (let [added-grub (first (filter #(= (:grub %) (:grub test-grub)) - @state/grubs))] - (should-not-be-nil (:_id added-grub)))))) + (describe "Add" + (it "should add a grub to the state when an add event comes" + (let [test-grub {:_id 12345 :grub "testgrub" :completed true} + add-event (assoc test-grub :event :add)] + (state/handle-event add-event) + (should-contain test-grub @state/grubs)))) + + (describe "Complete" + (it "should complete a grub in the state when a complete event comes" + (let [test-grub {:_id 234243 :grub "testgrub" :completed false} + expected-grub (assoc test-grub :completed true) + complete-event (-> (select-keys [:_id]) + (assoc :event :complete))] + (reset! state/grubs [test-grub]) + (state/handle-event complete-event) + (should-contain expected-grub @state/grubs)))) + + (describe "Uncomplete" + (it "should uncomplete a grub in the state when an uncomplete event comes" + (let [test-grub {:_id 234243 :grub "testgrub" :completed true} + expected-grub (assoc test-grub :completed false) + complete-event (-> (select-keys [:_id]) + (assoc :event :uncomplete))] + (reset! state/grubs [test-grub]) + (state/handle-event complete-event) + (should-contain expected-grub @state/grubs)))) + + (describe "Delete" + (it "should delete a grub from the state when a delete event comes" + (let [test-grub {:_id 234243 :grub "testgrub" :completed true} + delete-event {:_id (:_id test-grub) :event :delete}] + (reset! state/grubs [test-grub]) + (state/handle-event delete-event) + (should= [] @state/grubs))))) - (describe "Complete grub" - (it "should complete a grub in the state when a complete event comes" - (let [test-grub {:_id 234243 :grub "testgrub" :completed false} - expected-grub (assoc test-grub :completed true) - complete-event (-> (select-keys [:_id]) - (assoc :event :complete))] - (reset! state/grubs [test-grub]) - (state/handle-event complete-event) - (should-contain expected-grub @state/grubs)))) - - (describe "Uncomplete grub" - (it "should uncomplete a grub in the state when an uncomplete event comes" - (let [test-grub {:_id 234243 :grub "testgrub" :completed true} - expected-grub (assoc test-grub :completed false) - complete-event (-> (select-keys [:_id]) - (assoc :event :uncomplete))] - (reset! state/grubs [test-grub]) - (state/handle-event complete-event) - (should-contain expected-grub @state/grubs)))) - - (describe "Delete grub" - (it "should delete a grub from the state when a delete event comes" - (let [test-grub {:_id 234243 :grub "testgrub" :completed true} - delete-event {:_id (:_id test-grub) :event :delete}] - (reset! state/grubs [test-grub]) - (state/handle-event delete-event) - (should= [] @state/grubs))))) + (describe + "view event handling" + (describe "Create" + (it "should add a new grub to the state when a create event comes" + (let [test-grub {:grub "testgrub"} + create-event (assoc test-grub :event :create)] + (state/handle-view-event create-event) + (js/setTimeout (fn [] (let [created-grub (first @state/grubs)] + (should= (:grub test-grub) (:grub created-grub))))))) + (it "should generate an _id for the new grub" + (let [test-grub {:grub "testgrub"} + create-event (assoc test-grub :event :create)] + (state/handle-event create-event) + (js/setTimeout (fn [] + (let [added-grub (first (filter #(= (:grub %) (:grub test-grub)) + @state/grubs))] + (should-not-be-nil (:_id added-grub)))))))))) diff --git a/src/clj/grub/core.clj b/src/clj/grub/core.clj index 604b43e..bc607b5 100644 --- a/src/clj/grub/core.clj +++ b/src/clj/grub/core.clj @@ -35,10 +35,19 @@ (reload/wrap-reload (handler/site #'routes) {:dirs ["src/clj"]}) (handler/site routes)))) +(def default-port 3000) +(def integration-test-port 3456) + +(defn start-server [port] + (println (str "Starting server on localhost:" port)) + (httpkit/run-server app {:port port})) + +(defn run-integration-test [] + (let [stop-server (start-server integration-test-port)] + (integration-test/run integration-test-port) + (stop-server))) + (defn -main [& args] - (let [port 3000] - (println (str "Starting server on localhost:" port)) - (defonce stop-server (httpkit/run-server app {:port port})) - (when (some #(= % "integration") args) - (integration-test/run port) - (stop-server)))) + (if (some #(= % "integration") args) + (run-integration-test) + (start-server default-port))) diff --git a/src/clj/grub/db.clj b/src/clj/grub/db.clj index 0f427c8..5af7efa 100644 --- a/src/clj/grub/db.clj +++ b/src/clj/grub/db.clj @@ -11,10 +11,9 @@ (defmulti handle-event :event :default :unknown-event) -(defmethod handle-event :create [event] +(defmethod handle-event :add [event] (let [grub (-> event - (select-keys [:_id :grub]) - (assoc :completed false))] + (select-keys [:_id :grub :completed]))] (mc/insert grub-collection grub))) (defmethod handle-event :complete [event] @@ -49,6 +48,9 @@ (>! out grub-event)))) out)) +(defn clear-grubs [] + (mc/drop grub-collection)) + (def default-db "grub") (defn connect-and-handle-events diff --git a/src/cljs/grub/core.cljs b/src/cljs/grub/core.cljs index f840ea0..ab4ca66 100644 --- a/src/cljs/grub/core.cljs +++ b/src/cljs/grub/core.cljs @@ -9,15 +9,12 @@ [cljs.core.async.macros :refer [go]])) (defn handle-grub-events [] - (let [local-events (view/get-local-events) - [local-events' local-events''] (a/fan-out local-events 2) - remote-events (ws/get-remote-events) - events (a/fan-in [local-events' remote-events])] - (a/do-chan! ws/send-to-server local-events'') - (a/copy-chan state/incoming-events events))) + (a/copy-chan state/incoming-view-events view/outgoing-events) + (a/copy-chan state/incoming-events ws/outgoing-events) + (a/copy-chan ws/incoming-events state/outgoing-events)) (defn init [] - (view/render-body) + (view/init) (ws/connect-to-server) (handle-grub-events)) diff --git a/src/cljs/grub/state.cljs b/src/cljs/grub/state.cljs index ed06514..4c3dbc3 100644 --- a/src/cljs/grub/state.cljs +++ b/src/cljs/grub/state.cljs @@ -4,6 +4,8 @@ [cljs.core.async.macros :refer [go]])) (def incoming-events (chan)) +(def incoming-view-events (chan)) +(def outgoing-events (chan)) (def grubs (atom [])) @@ -22,13 +24,6 @@ (let [grub (select-keys event [:_id :grub :completed])] (swap! grubs (fn [current] (conj current grub))))) -(defmethod handle-event :create [event] - (let [grub (-> event - (select-keys [:_id :grub]) - (assoc :_id (str "grub-" (.now js/Date))) - (assoc :completed false))] - (swap! grubs (fn [current] (conj current grub))))) - (defmethod handle-event :complete [event] (swap! grubs (fn [current] @@ -51,7 +46,33 @@ (defmethod handle-event :unknown-event [event] (logs "Cannot handle unknown event:" event)) + + +(defn pass-on-view-event [event] + (go (>! incoming-events event)) + (go (>! outgoing-events event))) + +(defmulti handle-view-event :event :default :unknown-event) + +(defmethod handle-view-event :create [event] + (let [create-event (-> event + (assoc :event :add) + (assoc :_id (str "grub-" (.now js/Date))) + (assoc :completed false))] + (pass-on-view-event create-event))) + +(defmethod handle-view-event :unknown-event [event] + (pass-on-view-event event)) + + (defn handle-incoming-events [] (go-loop (handle-event (! outgoing-events grub-event)))))) + (defn connect-to-server [] - (reset! websocket* (js/WebSocket. "ws://localhost:3000/ws"))) - -(defn get-remote-events [] - (let [out (chan)] - (aset @websocket* "onmessage" (fn [event] - (let [grub-event (cljs.reader/read-string (.-data event))] - (logs "Received:" grub-event) - (go (>! out grub-event))))) - out)) - -(defn send-to-server [event] - (.send @websocket* event)) + (reset! websocket* (js/WebSocket. "ws://localhost:3000/ws")) + (handle-incoming-events) + (handle-outgoing-events))