(run-test-async & body)
Run body
as an async re-frame test. The async nature means you'll need to
use wait-for
any time you want to make any assertions that should be true
after an event has been handled. It's assumed that there will be at least
one wait-for
in the body of your test (otherwise you don't need this macro
at all).
Note: unlike regular ClojureScript cljs.test/async
tests, wait-for
takes
care of calling (done)
for you: you don't need to do anything specific to
handle the fact that your test is asynchronous, other than make sure that all
your assertions happen with wait-for
blocks.
This macro will automatically clean up any changes to re-frame state made
within the test body, as per with-temp-re-frame-state
(except that the way
it's done here does work for async tests, whereas that macro used by itself
doesn't).
Run `body` as an async re-frame test. The async nature means you'll need to use `wait-for` any time you want to make any assertions that should be true *after* an event has been handled. It's assumed that there will be at least one `wait-for` in the body of your test (otherwise you don't need this macro at all). Note: unlike regular ClojureScript `cljs.test/async` tests, `wait-for` takes care of calling `(done)` for you: you don't need to do anything specific to handle the fact that your test is asynchronous, other than make sure that all your assertions happen with `wait-for` blocks. This macro will automatically clean up any changes to re-frame state made within the test body, as per `with-temp-re-frame-state` (except that the way it's done here *does* work for async tests, whereas that macro used by itself doesn't).
(run-test-sync & body)
Execute body
as a test, where each dispatch
call is executed
synchronously (via dispatch-sync
), and any subsequent dispatches which are
caused by that dispatch are also fully handled/executed prior to control flow
returning to your test.
Think of it kind of as though every dispatch
in your app had been magically
turned into dispatch-sync
, and re-frame had lifted the restriction that says
you can't call dispatch-sync
from within an event handler.
Note that this is not achieved with blocking. It relies on you not doing
anything asynchronous (such as an actual AJAX call or js/setTimeout
)
directly in your event handlers. In a real app running in the real browser,
of course that won't apply, so this might seem useless at first. But if
you're a well-behaved re-framer, all of your asynchronous stuff (which is by
definition side-effecty) will happen in effectful event handlers installed
with reg-fx
. Which works very nicely: in your tests, install an alternative
version of those effectful event handlers which behaves synchronously. For
maximum coolness, you might want to consider running your tests on the JVM and
installing a reg-fx
handler which actually invokes your JVM Clojure
server-side Ring handler where your in-browser code would make an AJAX call.
Execute `body` as a test, where each `dispatch` call is executed synchronously (via `dispatch-sync`), and any subsequent dispatches which are caused by that dispatch are also fully handled/executed prior to control flow returning to your test. Think of it kind of as though every `dispatch` in your app had been magically turned into `dispatch-sync`, and re-frame had lifted the restriction that says you can't call `dispatch-sync` from within an event handler. Note that this is *not* achieved with blocking. It relies on you not doing anything asynchronous (such as an actual AJAX call or `js/setTimeout`) directly in your event handlers. In a real app running in the real browser, of course that won't apply, so this might seem useless at first. But if you're a well-behaved re-framer, all of your asynchronous stuff (which is by definition side-effecty) will happen in effectful event handlers installed with `reg-fx`. Which works very nicely: in your tests, install an alternative version of those effectful event handlers which behaves synchronously. For maximum coolness, you might want to consider running your tests on the JVM and installing a `reg-fx` handler which actually invokes your JVM Clojure server-side Ring handler where your in-browser code would make an AJAX call.
(wait-for [ids failure-ids event-sym :as argv] & body)
Execute body
once an event identified by the predicate(s) ids
has been handled.
ids
and failure-ids
are means to identify an event. Normally, each would
be a simple keyword or a set of keywords. If an event with event-id of (or
in) ids
is handled, the test will continue by executing the body. If an
event with an event-id of (or in) failure-ids
is handled, the test will
abort and fail.
IMPORTANT NOTE: due to the way async tests in re-frame work, code you want
executed after the event you're waiting for has to happen in the body
of the
wait-for
(in an implicit callback), not just lexically after the the
wait-for
call. In practice, this means wait-for
must always be in a tail
position.
Eg: (run-test-async (dispatch [:get-user 2]) (wait-for [#{:got-user} #{:no-such-user :system-unavailable} event] (is (= (:username @(subscribe [:user])) "johnny"))) ;; Don't put code here, it will run before the event you're waiting ;; for. )
Acceptable inputs for ids
and failure-ids
are:
:some-event-id
=> matches an event with that ID
#{:some-event-id :other-event-id}
=> matches an event with any of the
given IDs
[:some-event-id :other-event-id]
=> ditto (checks in order)
`(fn [event] ,,,) => uses the function as a predicate
[(fn [event] ,,,) (fn [event] ,,,)]
=> tries each predicate in turn,
matching an event which matches
at least one predicate
#{:some-event-id (fn [event] ,,,)}
=> tries each
Note that because we're liberal about whether you supply failure-ids
and/or
event-sym
, if you do choose to supply only one, and you want that one to be
event-sym
, you can't supply it as a destructuring form (because we can't
disambiguate that from a vector of failure-ids
). You can just supply nil
as failure-ids
in this case, and then you'll be able to destructure.
Execute `body` once an event identified by the predicate(s) `ids` has been handled. `ids` and `failure-ids` are means to identify an event. Normally, each would be a simple keyword or a set of keywords. If an event with event-id of (or in) `ids` is handled, the test will continue by executing the body. If an event with an event-id of (or in) `failure-ids` is handled, the test will abort and fail. IMPORTANT NOTE: due to the way async tests in re-frame work, code you want executed after the event you're waiting for has to happen in the `body` of the `wait-for` (in an implicit callback), not just lexically after the the `wait-for` call. In practice, this means `wait-for` must always be in a tail position. Eg: (run-test-async (dispatch [:get-user 2]) (wait-for [#{:got-user} #{:no-such-user :system-unavailable} event] (is (= (:username @(subscribe [:user])) "johnny"))) ;; Don't put code here, it will run *before* the event you're waiting ;; for. ) Acceptable inputs for `ids` and `failure-ids` are: - `:some-event-id` => matches an event with that ID - `#{:some-event-id :other-event-id}` => matches an event with any of the given IDs - `[:some-event-id :other-event-id]` => ditto (checks in order) - `(fn [event] ,,,) => uses the function as a predicate - `[(fn [event] ,,,) (fn [event] ,,,)]` => tries each predicate in turn, matching an event which matches at least one predicate - `#{:some-event-id (fn [event] ,,,)}` => tries each Note that because we're liberal about whether you supply `failure-ids` and/or `event-sym`, if you do choose to supply only one, and you want that one to be `event-sym`, you can't supply it as a destructuring form (because we can't disambiguate that from a vector of `failure-ids`). You can just supply `nil` as `failure-ids` in this case, and then you'll be able to destructure.
(wait-for* ok-ids failure-ids callback)
This function is an implementation detail: in your async tests (within a
run-test-async
), you should use the wait-for
macro instead. (For
synchronous tests within run-test-sync
, you don't need this capability at
all.)
Installs callback
as a re-frame post-event callback handler, called as soon
as any event matching ok-ids
is handled. Aborts the test as a failure if
any event matching failure-ids
is handled.
Since this is intended for use in asynchronous tests: it will return immediately after installing the callback -- it doesn't actually wait.
Note that wait-for*
tracks whether, during your callback, you call
wait-for*
again. If you don't, then, given the way asynchronous tests
work, your test must necessarily be finished. So wait-for*
will
call (done)
for you.
This function is an implementation detail: in your async tests (within a `run-test-async`), you should use the `wait-for` macro instead. (For synchronous tests within `run-test-sync`, you don't need this capability at all.) Installs `callback` as a re-frame post-event callback handler, called as soon as any event matching `ok-ids` is handled. Aborts the test as a failure if any event matching `failure-ids` is handled. Since this is intended for use in asynchronous tests: it will return immediately after installing the callback -- it doesn't *actually* wait. Note that `wait-for*` tracks whether, during your callback, you call `wait-for*` again. If you *don't*, then, given the way asynchronous tests work, your test must necessarily be finished. So `wait-for*` will call `(done)` for you.
(with-temp-re-frame-state & body)
Run body
, but discard whatever effects it may have on re-frame's internal
state (by resetting app-db
and re-frame's various different types of
handlers after body
has run).
Note: you can't use this macro to clean up a JS async test, since the macro
will perform the cleanup before your async code actually has a chance to run.
run-test-async
will automatically do this cleanup for you.
Run `body`, but discard whatever effects it may have on re-frame's internal state (by resetting `app-db` and re-frame's various different types of handlers after `body` has run). Note: you *can't* use this macro to clean up a JS async test, since the macro will perform the cleanup before your async code actually has a chance to run. `run-test-async` will automatically do this cleanup for you.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close