Skip to content

Commit

Permalink
The :impl parameter can now be a function that returns the impl, fixes
Browse files Browse the repository at this point in the history
regression of #13 and works towards #72
  • Loading branch information
oliyh committed Aug 10, 2020
1 parent fb6d589 commit a29d104
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 95 deletions.
43 changes: 35 additions & 8 deletions src/re_graph/internals.cljc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns re-graph.internals
(:require [re-frame.core :as re-frame]
[re-frame.interceptor :refer [->interceptor get-coeffect assoc-coeffect update-coeffect enqueue]]
[re-frame.interceptor :refer [->interceptor get-coeffect assoc-coeffect update-coeffect get-effect assoc-effect enqueue]]
[re-frame.std-interceptors :as rfi]
[re-frame.interop :refer [empty-queue]]
[re-graph.logging :as log]
Expand Down Expand Up @@ -38,6 +38,33 @@
trimmed-event)
trimmed-event))

(defn- build-impl [impl]
(if (fn? impl)
(impl)
impl))

(def instantiate-impl
(->interceptor
:id ::instantiate-impl
:before (fn [ctx]
(let [db (get-coeffect ctx :db)
http-impl (get-in db [:http :impl])
ws-impl (get-in db [:ws :impl])]
(-> (assoc ctx
::http-impl http-impl
::ws-impl ws-impl)
(update-coeffect :db (fn [db]
(cond-> db
http-impl (update-in [:http :impl] build-impl)
ws-impl (update-in [:ws :impl] build-impl)))))))
:after (fn [ctx]
(let [{::keys [http-impl ws-impl]} ctx
db-effect (get-effect ctx :db)]
(cond-> (dissoc ctx ::http-impl ::ws-impl)
db-effect (assoc-effect :db (cond-> db-effect
http-impl (assoc-in [:http :impl] http-impl)
ws-impl (assoc-in [:ws :impl] ws-impl))))))))

(def re-graph-instance
(->interceptor
:id ::instance
Expand All @@ -59,7 +86,6 @@

instance
(-> ctx
(assoc-coeffect :instance instance)
(assoc-coeffect :instance-name instance-name)
(assoc-coeffect :dispatchable-event (into [event-name instance-name] trimmed-event))
(cons-interceptor (rfi/path :re-graph instance-name))
Expand All @@ -72,7 +98,7 @@
ctx))))))

(def interceptors
[re-frame/trim-v re-graph-instance])
[re-frame/trim-v re-graph-instance instantiate-impl])

(defn- valid-graphql-errors?
"Validates that response has a valid GraphQL errors map"
Expand Down Expand Up @@ -279,11 +305,12 @@
(aset ws "onopen" (on-open instance-name ws))
(aset ws "onclose" (on-close instance-name))
(aset ws "onerror" (on-error instance-name)))
:clj (interop/create-ws url (merge impl {:on-open (on-open instance-name)
:on-message (on-ws-message instance-name)
:on-close (on-close instance-name)
:on-error (on-error instance-name)
:subprotocols [sub-protocol]})))))
:clj (interop/create-ws url (merge (build-impl impl)
{:on-open (on-open instance-name)
:on-message (on-ws-message instance-name)
:on-close (on-close instance-name)
:on-error (on-error instance-name)
:subprotocols [sub-protocol]})))))

(re-frame/reg-fx
::disconnect-ws
Expand Down
174 changes: 87 additions & 87 deletions test/re_graph/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@
(let [expected-http-url "http://foo.bar/graph-ql"
expected-request {:with-credentials? false}]
(init instance-name {:http {:url expected-http-url
:impl expected-request}
:impl (constantly expected-request)}
:ws nil})
(testing "Request can be specified"
(re-frame/reg-fx
Expand All @@ -597,115 +597,115 @@
query (if instance-name (partial re-graph/query instance-name) re-graph/query)
mutate (if instance-name (partial re-graph/mutate instance-name) re-graph/mutate)]

(testing "can call normal functions instead of needing re-frame")
(testing "can call normal functions instead of needing re-frame"

(testing "using a websocket"
(run-test-sync
(install-websocket-stub!)

(init {:ws {:url "ws://socket.rocket"
:connection-init-payload nil}})
(let [expected-subscription-payload {:id "my-sub"
:type "start"
:payload {:query "subscription { things { id } }"
:variables {:some "variable"}}}
expected-unsubscription-payload {:id "my-sub"
:type "stop"}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]

(re-frame/reg-fx
::internals/send-ws
(fn [[ws payload]]
(is (= ::websocket-connection ws))
(is (= expected-subscription-payload
payload))))

(subscribe :my-sub "{ things { id } }" {:some "variable"} callback-fn)

(is (= [::internals/callback callback-fn]
(get-in (db-instance) [:subscriptions "my-sub" :callback])))

(testing "messages from the WS are sent to the callback-fn"
(on-ws-message (data->message {:type "data"
:id "my-sub"
:payload expected-response-payload}))

(is @callback-called?))
(testing "using a websocket"
(run-test-sync
(install-websocket-stub!)

(init {:ws {:url "ws://socket.rocket"
:connection-init-payload nil}})
(let [expected-subscription-payload {:id "my-sub"
:type "start"
:payload {:query "subscription { things { id } }"
:variables {:some "variable"}}}
expected-unsubscription-payload {:id "my-sub"
:type "stop"}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]

(testing "and unregistered"
(re-frame/reg-fx
::internals/send-ws
(fn [[ws payload]]
(is (= ::websocket-connection ws))
(is (= expected-unsubscription-payload
(is (= expected-subscription-payload
payload))))

(unsubscribe :my-sub)
(subscribe :my-sub "{ things { id } }" {:some "variable"} callback-fn)

(is (nil? (get-in (db-instance) [:subscriptions "my-sub"])))))))
(is (= [::internals/callback callback-fn]
(get-in (db-instance) [:subscriptions "my-sub" :callback])))

(testing "using http"
(testing "queries"
(run-test-sync
(let [expected-http-url "http://foo.bar/graph-ql"
expected-query-payload {:query "query { things { id } }"
:variables {:some "variable"}}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]
(testing "messages from the WS are sent to the callback-fn"
(on-ws-message (data->message {:type "data"
:id "my-sub"
:payload expected-response-payload}))

(init {:http {:url expected-http-url}
:ws nil})
(is @callback-called?))

(re-frame/reg-fx
::internals/send-http
(fn [[_ _ http-url {:keys [payload]} :as fx-args]]
(is (= expected-query-payload
payload))
(testing "and unregistered"
(re-frame/reg-fx
::internals/send-ws
(fn [[ws payload]]
(is (= ::websocket-connection ws))
(is (= expected-unsubscription-payload
payload))))

(is (= expected-http-url http-url))
(unsubscribe :my-sub)

(dispatch-response fx-args expected-response-payload)))
(is (nil? (get-in (db-instance) [:subscriptions "my-sub"])))))))

(query "{ things { id } }" {:some "variable"} callback-fn)
(testing "using http"
(testing "queries"
(run-test-sync
(let [expected-http-url "http://foo.bar/graph-ql"
expected-query-payload {:query "query { things { id } }"
:variables {:some "variable"}}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]

(testing "responses are sent to the callback"
(is @callback-called?)))))
(init {:http {:url expected-http-url}
:ws nil})

(testing "mutations"
(run-test-sync
(let [expected-http-url "http://foo.bar/graph-ql"
expected-query-payload {:query "mutation { things { id } }"
:variables {:some "variable"}}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]
(re-frame/reg-fx
::internals/send-http
(fn [[_ _ http-url {:keys [payload]} :as fx-args]]
(is (= expected-query-payload
payload))

(init {:http {:url expected-http-url}
:ws nil})
(is (= expected-http-url http-url))

(re-frame/reg-fx
::internals/send-http
(fn [[_ _ http-url {:keys [payload]} :as fx-args]]
(is (= expected-query-payload
payload))
(dispatch-response fx-args expected-response-payload)))

(is (= expected-http-url http-url))
(query "{ things { id } }" {:some "variable"} callback-fn)

(dispatch-response fx-args expected-response-payload)))
(testing "responses are sent to the callback"
(is @callback-called?)))))

(mutate "{ things { id } }" {:some "variable"} callback-fn)
(testing "mutations"
(run-test-sync
(let [expected-http-url "http://foo.bar/graph-ql"
expected-query-payload {:query "mutation { things { id } }"
:variables {:some "variable"}}
expected-response-payload {:data {:things [{:id 1} {:id 2}]}}
callback-called? (atom false)
callback-fn (fn [payload]
(reset! callback-called? true)
(is (= expected-response-payload payload)))]

(testing "responses are sent to the callback"
(is @callback-called?))))))))
(init {:http {:url expected-http-url}
:ws nil})

(re-frame/reg-fx
::internals/send-http
(fn [[_ _ http-url {:keys [payload]} :as fx-args]]
(is (= expected-query-payload
payload))

(is (= expected-http-url http-url))

(dispatch-response fx-args expected-response-payload)))

(mutate "{ things { id } }" {:some "variable"} callback-fn)

(testing "responses are sent to the callback"
(is @callback-called?)))))))))

(deftest non-re-frame-test
(run-non-re-frame-test nil))
Expand Down

0 comments on commit a29d104

Please sign in to comment.