Clojurescript+React Hooks testing tool

I thought I’d share the React testing tool I’ve been building this past week: rehook-test.

Personally, testing front end apps has been a pain point for me (in any language). However, I think Clojurescript has a pretty nice story here, where you are able to test the data layer easily.

But I often find that over time the view goes out of sync with the data layer.

So this is the initial cut of a library aimed to solve the above problem. It is built on top of the rehook library.

Basically, you write tests using a DSL on top of cljs.test and get both headless nodejs tests + an interactive test report. The end result is something between devcards and Kafka’s TestTopologyDriver, I guess.

Tests comprise of two basic primitives: io and is:

  • io - some side-effect that will produce another render (eg HTTP call, DOM event)
  • is - like cljs.test/is – an assertion about the current state of the mounted component

An example test looks like this:

(ns todo-test
  (:require [rehook.test :refer-macros [defuitest is io initial-render next-render]
            [todomvc.core :as todo]])

(defuitest todo-app--add-new-item
  [[scenes {:keys [dispatch subscribe]}] (test-ctx todo/todo-app)]
  (-> (initial-render scenes
        (let [items (subscribe [:todos])]
          (is "Subscription should contain 5 items"
            (= items todo/initial-items)))
        
        (io "Dispatch :add-todo"
          (dispatch [:add-todo "Write more tests"])))

      (next-render
       (let [items (subscribe [:todos])]
         (is "After adding item, there should be 6 TODOs"
           (= 6 (count items)))))))

We use the initial-render and next-render macros to scope our test body to a particular snapshot in time.

I made a video demonstrating the features of the library:

You can view the unit tests for the todomvc example here

The above unit tests generated this demo report. And you can see the same unit tests running in a CI environment here

All source code is available here

The test DSL + report UI is still a WIP, but I’m keen for any feedback!

A few notes on where I’d like to take this project:

  • I want Git-like diffs between the previous scene and the next scene’s hiccup. react-diff-viewer?
  • How can we use property based testing to put this thing on steroids? Eg render shrunk result
  • This tool could be used to instrument running app. Eg, something similar to reframe10x
  • This tool could lint/detect various problems with React use. Eg, when a :key on a component is required, when state/effects are setup incorrectly, etc.
  • It should be possible to test async effects (js/setTimeout, core.async etc) - explore and document.
1 Like