Skip to content

Instantly share code, notes, and snippets.

@trikitrok
Last active October 9, 2017 22:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trikitrok/a39f5fbec6ab0ee0c6f8db68e87a552c to your computer and use it in GitHub Desktop.
Save trikitrok/a39f5fbec6ab0ee0c6f8db68e87a552c to your computer and use it in GitHub Desktop.
(ns horizon.test-helpers.async-test-tools
(:require
[cljs.test :refer-macros [is]]
[cljs.core.async :as core.async])
(:require-macros
[cljs.core.async.macros :refer [go go-loop]]))
(def ^:private timeout-in-ms 2000)
(defn- channel-timed-out-error [received-messages]
(ex-info
"Channel timed out!!!"
{:cause :channel-timeout
:received-messages received-messages}))
(defn- maybe-exclude-keys [x ks]
(if (and (map? x) ks)
(apply dissoc x ks)
x))
(defn- invoke! [f]
{:pre [(if f (ifn? f) true)]}
(when f
(f)))
(defn- check-result
[& {:keys [expected result done-fn excluding-keys] :as options}]
{:pre [(every? #{:expected :result :done-fn :excluding-keys}
(keys options))
(if done-fn (ifn? done-fn) true)]}
(let [expected (maybe-exclude-keys expected excluding-keys)
result (maybe-exclude-keys result excluding-keys)]
(try
(is (= expected result))
(finally
(invoke! done-fn)))))
(defn check-results
[& {:keys [expected result done-fn excluding-keys] :as options}]
{:pre [(every? #{:expected :result :done-fn :excluding-keys}
(keys options))
(if done-fn (ifn? done-fn) true)]}
(try
(mapv #(check-result :expected %1
:result %2
:excluding-keys excluding-keys)
expected
result)
(finally
(invoke! done-fn))))
(defn- fail-because-of-timeout
[expected-message received-messages done-fn]
(check-result :expected expected-message
:result (channel-timed-out-error received-messages)
:done-fn done-fn))
(defn expect-async-message
[channel & {:keys [expected-message done-fn excluding-keys]}]
{:pre [expected-message (if done-fn (ifn? done-fn) true)]}
(go
(let [[message ch] (core.async/alts!
[channel (core.async/timeout timeout-in-ms)])]
(if (= ch channel)
(check-result :expected expected-message
:result message
:done-fn done-fn
:excluding-keys excluding-keys)
(fail-because-of-timeout expected-message [] done-fn)))))
(defn expect-async-message-with-specific-type
[channel & {:keys [expected-message-type expected-message done-fn excluding-keys]}]
{:pre [expected-message expected-message-type (if done-fn (ifn? done-fn) true)]}
(go-loop [received-messages []]
(let [[message ch] (core.async/alts!
[channel (core.async/timeout timeout-in-ms)])]
(if (= ch channel)
(if (= expected-message-type (:type message))
(check-result :expected expected-message
:result message
:done-fn done-fn
:excluding-keys excluding-keys)
(recur (conj received-messages message)))
(fail-because-of-timeout expected-message received-messages done-fn)))))
(defn expect-n-async-messages
[channel & {:keys [expected-messages done-fn excluding-keys]}]
{:pre [(sequential? expected-messages) (if done-fn (ifn? done-fn) true)]}
(go-loop [received-messages []]
(let [[message ch] (core.async/alts!
[channel (core.async/timeout timeout-in-ms)])
total (count expected-messages)]
(if (= ch channel)
(let [received-messages (conj received-messages message)]
(if (= total (count received-messages))
(check-results :expected expected-messages
:result received-messages
:done-fn done-fn
:excluding-keys excluding-keys)
(recur received-messages)))
(fail-because-of-timeout expected-messages received-messages done-fn)))))
(defn async-used-fn [channel func-kw]
(fn [& args]
(go
(core.async/>! channel {:used func-kw :with-args (vec args)}))))
(defn send-fake-msg! [channel msg]
(go
(core.async/>! channel msg)))
(defn expect-event-handler-receives-args
[& {:keys [event channel expected-args done-fn close-fn]}]
{:pre [event
channel
expected-args
(if done-fn (ifn? done-fn) true)
(if close-fn (ifn? close-fn) true)]}
(let [events-channel (core.async/chan)
close-and-done-fn (fn []
(when close-fn (close-fn channel))
(when done-fn (done-fn channel)))]
(event
channel
(fn [& args]
(go
(core.async/>! events-channel args))))
(go
(let [[args ch] (core.async/alts!
[events-channel (core.async/timeout timeout-in-ms)])]
(if (= ch events-channel)
(check-result
:expected expected-args :result args :done-fn close-and-done-fn)
(fail-because-of-timeout
expected-args :never-called close-and-done-fn))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment