re-frame.test-helpers¶
re-frame.test-helpers is the view-tree assertion axis of the testing surface. A view is a function that returns hiccup. These helpers walk that returned data structure: they locate nodes by :data-testid (or any attribute), read their text, and pluck or invoke an attached event handler. The walk helpers are pure functions over hiccup data. The whole surface, single-frame fixture trio included, runs on the JVM with no JSDOM, no React, and no act().
This namespace pairs with render-to-string in re-frame.ssr.md, the HTML-string view-test path. Use the hiccup walkers when asserting on structure or handlers. Use render-to-string when asserting on rendered markup. The runtime-state axis (registrar fixtures, assert-path-equals, poll-until) lives in re-frame.test-support.md. A test that needs both axes :requires both namespaces.
Tree expansion¶
expand-tree¶
- Kind: function
- Signature:
-
Description: Recursively expand the components inside a hiccup tree, invoking each with its args just as Reagent's renderer would. This covers function components, Form-2 fn-returning-fn components, and Form-3 class components. After expansion, every vector's first element is a keyword tag or a non-component value.
-
Form-3 classes expand by calling the stashed
:reagent-renderfn directly. No React is instantiated and no lifecycle methods run. (On the JVM, class detection is a no-op.) - The
find-*andtext-contentwalkers already expand internally. Callexpand-treedirectly only to re-expand a sub-tree mid-walk. - Example:
Reading hiccup nodes¶
attrs¶
- Kind: function
- Signature:
- Description: Return the attrs map of a hiccup node, or
nil. - Example:
children¶
- Kind: function
- Signature:
- Description: Return everything after the tag and the optional attrs map. The result is always a vector, and it is empty when the node has no children. Non-vector input returns
nil. - Example:
text-content¶
- Kind: function
- Signature:
- Description: Recursively collect the string leaves under
node, expanding nested components along the way, and join them into one string. Numbers coerce to strings and nils are skipped. When nothing matches, the result is"". - Example:
extract-handler¶
- Kind: function
- Signature:
- Description: Return the value under
event-keyinnode's attrs map, ornil. Equivalent to(get (attrs node) event-key). - Example:
Finding nodes by attribute¶
find-by-attr¶
- Kind: function
- Signature:
- Description: Return the first hiccup node whose attrs map carries
attr == val, ornilwhen nothing matches. It is generic over the attribute keyword::data-testid,:id,:data-test, or anything custom. - Example:
find-all-by-attr¶
- Kind: function
- Signature:
- Description: Return every matching node, in depth-first order.
- Example:
find-by-attr-prefix¶
- Kind: function
- Signature:
- Description: Return every node whose
attrvalue is a string starting withprefix. Non-string attr values never match. - Example:
Finding nodes by testid¶
find-by-testid¶
- Kind: function
- Signature:
- Description:
find-by-attrkeyed on:data-testid. - Example:
find-all-by-testid¶
- Kind: function
- Signature:
- Description:
find-all-by-attrkeyed on:data-testid. - Example:
find-by-testid-prefix¶
- Kind: function
- Signature:
- Description:
find-by-attr-prefixkeyed on:data-testid. - Example:
Driving handlers¶
invoke-handler¶
- Kind: function
- Signature:
-
Description: Find the handler under
event-keyonnode, call it withargs, and return its value. A missing handler is treated as a test bug, so this throws: -
:rf.error/invoke-handler-bad-node—nodeis not a hiccup vector. :rf.error/invoke-handler-missing— no handler fn exists underevent-key(including when the node has no attrs map at all).- Example:
Authoring testids¶
testid¶
- Kind: function
- Signature:
- Description: Build an attrs map carrying
:data-testid id. The 2-arity mergesextrainto that map, and:data-testidalways wins on collision. Use it at the view call site. Pair it withfind-by-testidat the assertion site. - Example:
Single-frame view test — composition recipe¶
A connected view (one that subscribes / dispatches) needs a frame in scope. There is no bespoke single-frame fixture macro — the single-frame view test composes from primitives that already exist and are adopted at scale:
re-frame.test-support/make-reset-runtime-fixture— an:adapter(and an optional:init-fnthat holds thereg-event/reg-sub/reg-viewcalls the test relies on) seats the ambient:rf/defaultframe and rolls the registrar back between tests.- The hiccup walkers above — call the root view fn directly and walk the returned tree.
re-frame.test-support/poll-until— for the async case (a plaindispatchthat queues, an HTTP reply, a machine:after) whose settled outcome is observable in the re-rendered view.
(ns my-app.views-test
(:require [clojure.test :refer [deftest is use-fixtures]]
[re-frame.core :as rf]
[re-frame.test-support :as ts]
[re-frame.test-helpers :as th]
[my-app.counter :as counter]))
(use-fixtures :each
(ts/make-reset-runtime-fixture {:adapter counter/test-adapter ;; your substrate adapter
:init-fn counter/install!})) ;; reg-event / reg-sub
;; Synchronous — dispatch-sync drains before the assertion, so walk the
;; re-rendered view directly.
(deftest counter-increments
(rf/dispatch-sync [:counter/inc])
(rf/dispatch-sync [:counter/inc])
(is (= "2" (th/text-content
(th/find-by-testid (counter/main) "counter-display")))))
;; Async — an invoked :on-click fires a plain dispatch that queues, so poll
;; the re-rendered view until it settles (JVM shown; CLJS returns a Promise —
;; compose with cljs.test/async, exactly as poll-until does).
(deftest inc-button-is-wired
(let [btn (th/find-by-testid (th/expand-tree (counter/main)) "counter-inc")]
(th/invoke-handler btn :on-click))
(is (ts/poll-until
#(= "1" (th/text-content
(th/find-by-testid (counter/main) "counter-display")))
{:label "counter reached 1"})))
See docs/core/testing/views.md for the worked walkthrough.
See also¶
- re-frame.test-support.md — the runtime-state assertion axis: registrar fixtures,
assert-path-equals,poll-until. - re-frame.core.md —
dispatch-sync,with-new-frame,make-frame,app-db-value,compute-sub— the production primitives these view tests drive. - re-frame.ssr.md —
render-to-string, the HTML-string view-test path that complements hiccup-walk. - Test an event handler and Test a pipeline run — the practical how-to guides for the testing surface.