Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Day8/re-frame-test
Cross platform (cljs and clj) utilities for testing re-frame applications
https://github.com/Day8/re-frame-test
re-frame test
Last synced: about 1 month ago
JSON representation
Cross platform (cljs and clj) utilities for testing re-frame applications
- Host: GitHub
- URL: https://github.com/Day8/re-frame-test
- Owner: day8
- License: mit
- Created: 2016-07-25T03:56:26.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2021-11-04T23:04:46.000Z (about 3 years ago)
- Last Synced: 2024-11-13T00:11:31.306Z (about 1 month ago)
- Topics: re-frame, test
- Language: Clojure
- Homepage:
- Size: 190 KB
- Stars: 109
- Watchers: 13
- Forks: 12
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
- awesome-re-frame - re-frame-test - frame applications (Tools / Testing)
README
[![Clojars Project](https://img.shields.io/clojars/v/day8.re-frame/test?style=for-the-badge&logo=clojure&logoColor=fff)](https://clojars.org/day8.re-frame/test)
[![GitHub issues](https://img.shields.io/github/issues-raw/day8/re-frame-test?style=for-the-badge&logo=github)](https://github.com/day8/re-frame-test/issues)
[![License](https://img.shields.io/github/license/day8/re-frame-test?style=for-the-badge)](LICENSE)# re-frame-test
This library provides utilities
for testing [re-frame applications](https://github.com/day8/re-frame).These utilities:
- allow you to use `subscribe` in your tests
- allow you to use `dispatch` in your tests
- allow you to run tests on both the JVM and JS platforms
- allow you to create "end to end" integration tests, involving backend serversFor context, please be sure to read the
[basic testing tutorial](https://github.com/day8/re-frame/blob/master/docs/Testing.md)
in the main re-frame docs before going any further.This library primarily supports the testing of Event Handlers, but Subscription Handlers
get to come along for the ride.## Quick Start Guide
### Step 1. Add Dependency
Add the following project dependency:
[![Clojars Project](https://img.shields.io/clojars/v/day8.re-frame/test.svg)](https://clojars.org/day8.re-frame/test)Requires re-frame >= "1.1.1"
### Step 2. Registration And Use
In the namespace where you register your tests, perhaps called `tests.cljs`, you have 2 things to do.
**First**, add this require to the `ns`:
```clj
(ns app.tests
(:require
...
[day8.re-frame.test :as rf-test] ;; <-- add this
...))
```**Second**, Define or Modify some tests.
```Clojure
(deftest init
(rf-test/run-test-sync ;; <-- add this
;; with the above macro this becomes a dispatch-sync
;; and app-db is isolated between tests
(rf/dispatch [:initialise-db])
;; Define subscriptions to the app state
(let [showing (rf/subscribe [:showing])]
;;Assert the initial state
(is (= :all @showing)))))
```## How It Works
`re-frame-test` provides two macros which dovetail with `cljs.test`.
### run-test-syncExecute `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 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.This macro is applicable for most events that do not run async behaviour within the
event.From the todomvc example:
```Clojure
(defn test-fixtures
[]
;; change this coeffect to make tests start with nothing
(rf/reg-cofx
:local-store-todos
(fn [cofx _]
"Read in todos from localstore, and process into a map we can merge into app-db."
(assoc cofx :local-store-todos
(sorted-map)))))
```Define some test-fixtures. In this case we have to ignore the localstore
in the tests.```Clojure
(deftest basic--sync
(rf-test/run-test-sync
(test-fixtures)
(rf/dispatch [:initialise-db])
```Use the `run-test-sync` macro to construct the tests and initialise the app state.
Note that, the `dispatch` will be handled before the following code is executed,
effectively turning it into a `dispatch-sync`. Also any changes to the database
and registrations will be rolled back at the termination of the test, therefore
our fixtures are run within the `run-test-sync` macro.```Clojure
;; Define subscriptions to the app state
(let [showing (rf/subscribe [:showing])
sorted-todos (rf/subscribe [:sorted-todos])
todos (rf/subscribe [:todos])
visible-todos (rf/subscribe [:visible-todos])
all-complete? (rf/subscribe [:all-complete?])
completed-count (rf/subscribe [:completed-count])
footer-counts (rf/subscribe [:footer-counts])]
;;Assert the initial state
(is (= :all @showing))
(is (empty? @sorted-todos))
(is (empty? @todos))
(is (empty? @visible-todos))
(is (= false (boolean @all-complete?)))
(is (= 0 @completed-count))
(is (= [0 0] @footer-counts))
;;Dispatch the event that you want to test, remember that `re-frame-test`
;;will process this event immediately.
(rf/dispatch [:add-todo "write first test"])
;;Test that the dispatch has mutated the state in the way that we expect.
(is (= 1 (count @todos) (count @visible-todos) (count @sorted-todos)))
(is (= 0 @completed-count))
(is (= [1 0] @footer-counts))
(is (= {:id 1, :title "write first test", :done false}
(first @todos)))
```
### run-test-asyncThis macro is applicable for events that do run some async behaviour
(usually outside or re-frame, e.g. an http request) within the event.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.From the todomvc example:
```Clojure
(deftest basic--async
(rf-test/run-test-async
(test-fixtures)
(rf/dispatch-sync [:initialise-db])
```Use the `run-test-async` macro to construct the tests and initialise the app state
note that the `dispatch-sync` must be used as this macro does not run the dispatch
immediately like `run-test-sync`. Also any changes to the database
and registrations will be rolled back at the termination of the test, therefore
our fixtures are run within the `run-test-async` macro.```Clojure
;;Define subscriptions to the app state
(let [showing (rf/subscribe [:showing])
sorted-todos (rf/subscribe [:sorted-todos])
todos (rf/subscribe [:todos])
visible-todos (rf/subscribe [:visible-todos])
all-complete? (rf/subscribe [:all-complete?])
completed-count (rf/subscribe [:completed-count])
footer-counts (rf/subscribe [:footer-counts])]
;;Assert the initial state
(is (= :all @showing))
(is (empty? @sorted-todos))
(is (empty? @todos))
(is (empty? @visible-todos))
(is (= 0 @completed-count))
;;Dispatch the event that you want to test, remember
;;that re-frame will not process this event immediately,
;;and need to use the `wait-for` macro to continue the tests.
(rf/dispatch [:add-todo "write first test"])
;;Wait for the `:add-todo` event to be dispatched
;;(note, in the use of this macro we would typically wait for
;;an event that had been triggered by the successful return of
;;the async event).
(rf-test/wait-for [:add-todo-finished]
;;Test that the dispatch has mutated the state in the way
;;that we expect.
(is (= [{:id 1, :title "write first test", :done false}] @todos))
```Here we have assumed that the `:add-todo` event will make some sort of async
call which will in turn generate an `add-todo-finished` event when it has finished.
This is not actually the case in the example code.## Running the CLJS tests with Karma
You will need `npm`, with:
```console
$ npm install -g karma karma-cli karma-cljs-test karma-junit-reporter karma-chrome-launcher
```And you will need Chrome.
## License
Copyright (c) 2016 Mike Thompson
Distributed under the The MIT License (MIT).