Liking cljdoc? Tell your friends :D

hyper.test

Testing utilities for hyper page handlers.

Provides test-page and test-action for rendering pages and simulating user interactions in an isolated test context.

Example: (require '[hyper.test :as ht]) (require '[hyper.core :as h])

(defn my-page [req] (let [count* (h/tab-cursor :count 0)] [:div [:h1 "Count: " @count*] [:button {:data-on:click (h/action {:as "increment"} (swap! (h/tab-cursor :count) inc))} "Increment"]]))

(let [result (ht/test-page my-page)] ;; Assert on rendered output (assert (str/includes? (:body-html result) "Count: 0")) ;; Simulate button click and check cursors (let [after (ht/test-action result "increment")] (assert (= 1 (get-in after [:cursors :tab :count])))) ;; Re-render and verify (let [result2 (ht/test-page my-page {:app-state (:app-state result)})] (assert (str/includes? (:body-html result2) "Count: 1"))))

Testing utilities for hyper page handlers.

Provides `test-page` and `test-action` for rendering pages and
simulating user interactions in an isolated test context.

Example:
  (require '[hyper.test :as ht])
  (require '[hyper.core :as h])

  (defn my-page [req]
    (let [count* (h/tab-cursor :count 0)]
      [:div
       [:h1 "Count: " @count*]
       [:button {:data-on:click (h/action {:as "increment"}
                                 (swap! (h/tab-cursor :count) inc))}
        "Increment"]]))

  (let [result (ht/test-page my-page)]
    ;; Assert on rendered output
    (assert (str/includes? (:body-html result) "Count: 0"))
    ;; Simulate button click and check cursors
    (let [after (ht/test-action result "increment")]
      (assert (= 1 (get-in after [:cursors :tab :count]))))
    ;; Re-render and verify
    (let [result2 (ht/test-page my-page {:app-state (:app-state result)})]
      (assert (str/includes? (:body-html result2) "Count: 1"))))
raw docstring

test-actionclj

(test-action result action-name)
(test-action result action-name client-params)

Execute a named action from a test-page result and return a state snapshot.

Looks up the action by its :as name (or raw action-id) in the result's :actions map, executes it with proper request context bindings, and returns a map describing the cursor values after execution.

result: The map returned by test-page. action-name: The :as name (or action-id) of the action to execute. client-params: Optional map of client params (e.g. {:value "hello"}). Simulates $value, $checked, $key, $form-data, etc.

Returns a map:

  • :cursors — Cursor values after the action executed: :global, :session, :tab, :route
  • :effects — Effects accumulated during execution. A map with: :cookies — map of cookie-name to cookie opts :scripts — vector of JS strings to execute Effects are collected but NOT applied — this lets tests assert on what effects would happen without actually setting cookies or sending SSE events.
  • :app-state — The app-state atom, for threading into test-page.

Throws if the action name is not found in the result.

Example: (let [result (ht/test-page my-page) after (ht/test-action result "increment")] (is (= 1 (get-in after [:cursors :tab :count]))))

;; With client params (simulating $value) (let [result (ht/test-page search-page) after (ht/test-action result "search" {:value "clojure"})] (is (= "clojure" (get-in after [:cursors :tab :query]))))

;; Assert on effects (let [result (ht/test-page my-page) after (ht/test-action result "publish")] (is (seq (get-in after [:effects :scripts]))))

;; Chain into another render (let [r1 (ht/test-page my-page) _ (ht/test-action r1 "increment") r2 (ht/test-page my-page {:app-state (:app-state r1)})] (is (str/includes? (:body-html r2) "Count: 1")))

Execute a named action from a test-page result and return a state snapshot.

Looks up the action by its :as name (or raw action-id) in the result's
:actions map, executes it with proper request context bindings, and
returns a map describing the cursor values after execution.

result:        The map returned by test-page.
action-name:   The :as name (or action-id) of the action to execute.
client-params: Optional map of client params (e.g. {:value "hello"}).
                Simulates $value, $checked, $key, $form-data, etc.

Returns a map:
- :cursors    — Cursor values after the action executed:
                   :global, :session, :tab, :route
- :effects    — Effects accumulated during execution. A map with:
                   :cookies — map of cookie-name to cookie opts
                   :scripts — vector of JS strings to execute
                Effects are collected but NOT applied — this lets tests
                assert on what effects *would* happen without actually
                setting cookies or sending SSE events.
- :app-state  — The app-state atom, for threading into test-page.

Throws if the action name is not found in the result.

Example:
  (let [result (ht/test-page my-page)
        after  (ht/test-action result "increment")]
    (is (= 1 (get-in after [:cursors :tab :count]))))

  ;; With client params (simulating $value)
  (let [result (ht/test-page search-page)
        after  (ht/test-action result "search" {:value "clojure"})]
    (is (= "clojure" (get-in after [:cursors :tab :query]))))

  ;; Assert on effects
  (let [result (ht/test-page my-page)
        after  (ht/test-action result "publish")]
    (is (seq (get-in after [:effects :scripts]))))

  ;; Chain into another render
  (let [r1 (ht/test-page my-page)
        _  (ht/test-action r1 "increment")
        r2 (ht/test-page my-page {:app-state (:app-state r1)})]
    (is (str/includes? (:body-html r2) "Count: 1")))
sourceraw docstring

test-pageclj

(test-page handler)
(test-page handler opts)

Render a page handler in an isolated test context and return a result map.

handler: A page render function (fn [req] -> hiccup).

opts (optional map):

  • :app-state — Atom for application state. Pass the :app-state from a previous test-page call to preserve state across renders. Default: fresh atom with init-state.
  • :cursors — Initial cursor values to seed before rendering. A map with optional keys :global, :session, :tab, each a map of data that is merged into the corresponding cursor scope. Example: {:tab {:count 5} :session {:user "alice"}}
  • :session-id — Session ID string. Default: "test-session".
  • :tab-id — Tab ID string. Default: "test-tab".
  • :route — Route info map {:name :path :path-params :query-params}. Default: {:name :test-page :path "/" :path-params {} :query-params {}}.
  • :routes — A reitit routes vector (or a Var holding one) used to build a bound router so that h/navigate (during render) and effects/navigate! (during actions, via test-action) resolve named routes reliably — no need to spin up a full create-handler. The router and flattened routes are stored in app-state and threaded into the request as :hyper/router, and they persist across re-renders that share :app-state. Example: {:routes [["/" {:name :home :get home-fn}] ["/about" {:name :about :get about-fn}]]}.
  • :router — A pre-built reitit router, used as-is for name matching. Escape hatch for advanced cases; prefer :routes. When both are given, :router matches and :routes provides metadata.
  • :req — Extra keys to merge into the request map passed to handler.
  • :render-middleware — Vector of middleware fns to wrap the handler. Each is (fn [handler] (fn [req] ...)), identical to Ring middleware. Applied in order (first = outermost).

Returns a map:

  • :body — Raw hiccup returned by the handler (before HTML serialization).
  • :body-html — Serialized HTML string of the body.
  • :title — Resolved page title string, or nil.
  • :url — Current route URL string.
  • :signals — Map of signal declarations from the render, keyed by the path used to create the signal (e.g. :user-name, [:user :name]). Each value has :default-val and :local?.
  • :actions — Map of actions registered during render. Actions with an :as name are keyed by that name; others by their action-id. Each value has :fn which can be called as ((:fn action) client-params).
  • :cursors — Snapshot of cursor values after render: :global — global cursor state map :session — this session's cursor data map :tab — this tab's cursor data map :route — this tab's route info
  • :watches — Vector of external sources registered via h/watch!.
  • :app-state — The app-state atom, for threading into subsequent calls.

If the handler returns a Ring response map (a map with :status), it is returned as-is without wrapping.

Render a page handler in an isolated test context and return a result map.

handler: A page render function (fn [req] -> hiccup).

opts (optional map):
- :app-state   — Atom for application state. Pass the :app-state from a
                  previous test-page call to preserve state across renders.
                  Default: fresh atom with init-state.
- :cursors     — Initial cursor values to seed before rendering. A map with
                  optional keys :global, :session, :tab, each a map of data
                  that is merged into the corresponding cursor scope.
                  Example: {:tab {:count 5} :session {:user "alice"}}
- :session-id  — Session ID string. Default: "test-session".
- :tab-id      — Tab ID string. Default: "test-tab".
- :route       — Route info map {:name :path :path-params :query-params}.
                  Default: {:name :test-page :path "/" :path-params {} :query-params {}}.
- :routes      — A reitit routes vector (or a Var holding one) used to build
                  a bound router so that `h/navigate` (during render) and
                  `effects/navigate!` (during actions, via `test-action`)
                  resolve named routes reliably — no need to spin up a full
                  `create-handler`. The router and flattened routes are stored
                  in app-state and threaded into the request as :hyper/router,
                  and they persist across re-renders that share :app-state.
                  Example: {:routes [["/" {:name :home :get home-fn}]
                                     ["/about" {:name :about :get about-fn}]]}.
- :router      — A pre-built reitit router, used as-is for name matching.
                  Escape hatch for advanced cases; prefer :routes. When both
                  are given, :router matches and :routes provides metadata.
- :req         — Extra keys to merge into the request map passed to handler.
- :render-middleware — Vector of middleware fns to wrap the handler.
                  Each is (fn [handler] (fn [req] ...)), identical to Ring
                  middleware.  Applied in order (first = outermost).

Returns a map:
- :body          — Raw hiccup returned by the handler (before HTML serialization).
- :body-html     — Serialized HTML string of the body.
- :title         — Resolved page title string, or nil.
- :url           — Current route URL string.
- :signals       — Map of signal declarations from the render, keyed by
                    the path used to create the signal (e.g. :user-name,
                    [:user :name]). Each value has :default-val and :local?.
- :actions       — Map of actions registered during render. Actions with an
                    :as name are keyed by that name; others by their action-id.
                    Each value has :fn which can be called as ((:fn action) client-params).
- :cursors       — Snapshot of cursor values after render:
                      :global  — global cursor state map
                      :session — this session's cursor data map
                      :tab     — this tab's cursor data map
                      :route   — this tab's route info
- :watches       — Vector of external sources registered via h/watch!.
- :app-state     — The app-state atom, for threading into subsequent calls.

If the handler returns a Ring response map (a map with :status), it is
returned as-is without wrapping.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close