(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