Skip to content

Commit

Permalink
Try testing with concurrent-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Deraen committed Feb 14, 2025
1 parent 6211ef9 commit 34d6abd
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 50 deletions.
9 changes: 2 additions & 7 deletions demo/reagentdemo/intro.cljs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
(ns reagentdemo.intro
(:require [reagent.core :as r]
[reagent.dom :as rdom]
[reagentdemo.syntax :as s]
[reagent.dom.client :as rdomc]
[reagentdemo.common :as common :refer [demo-component]]
[reagentdemo.syntax :as s]
[simpleexample.core :as simple]
[todomvc.core :as todo]))

Expand Down Expand Up @@ -62,11 +62,6 @@
[:div
"Seconds Elapsed: " @seconds-elapsed])))

(defn render-simple []
(rdom/render
[simple-component]
(.-body js/document)))

(defn calc-bmi [{:keys [height weight bmi] :as data}]
(let [h (/ height 100)]
(if (nil? bmi)
Expand Down
7 changes: 3 additions & 4 deletions examples/geometry/src/geometry/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[geometry.components :as c]
[geometry.geometry :as g]
[reagent.core :as r]
[reagent.dom :as rdom]))
[reagent.dom.client :as rdomc]))

(enable-console-print!)

Expand Down Expand Up @@ -90,8 +90,7 @@
[props]
[:f> main* props])

(defn by-id [id]
(.getElementById js/document id))
(defonce root (delay (rdomc/create-root (.getElementById js/document "app"))))

(defn ^:export run []
(rdom/render [main] (by-id "app")))
(rdomc/render @root [main]))
10 changes: 6 additions & 4 deletions examples/simple/src/simpleexample/core.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns simpleexample.core
(:require [reagent.core :as r]
[reagent.dom :as rdom]
[clojure.string :as str]))
(:require [clojure.string :as str]
[reagent.core :as r]
[reagent.dom.client :as rdomc]))

(defonce timer (r/atom (js/Date.)))

Expand Down Expand Up @@ -32,5 +32,7 @@
[clock]
[color-input]])

(defonce root (delay (rdomc/create-root (.getElementById js/document "app"))))

(defn ^:export run []
(rdom/render [simple-example] (js/document.getElementById "app")))
(rdomc/render @root [simple-example]))
12 changes: 7 additions & 5 deletions examples/todomvc/src/todomvc/core.cljs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
(ns todomvc.core
(:require [reagent.core :as r]
[reagent.dom :as rdom]
["react" :as react]
[clojure.string :as str]))
(:require ["react" :as react]
[clojure.string :as str]
[reagent.core :as r]
[reagent.dom.client :as rdomc]))

(defonce todos (r/atom (sorted-map)))

Expand Down Expand Up @@ -126,5 +126,7 @@
[:footer#info
[:p "Double-click to edit a todo"]]]))))

(defonce root (delay (rdomc/create-root (.getElementById js/document "app"))))

(defn ^:export run []
(rdom/render [todo-app] (js/document.getElementById "app")))
(rdomc/render @root [todo-app]))
90 changes: 60 additions & 30 deletions test/reagenttest/utils.cljs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
(ns reagenttest.utils
(:require-macros reagenttest.utils)
(:require [promesa.core :as p]
(:require [react :as react]
[promesa.core :as p]
[reagent.core :as r]
[reagent.debug :as debug]
[reagent.dom :as rdom]
[reagent.debug :as debug :refer [dev?]]
[reagent.dom.server :as server]
[reagent.dom.client :as rdomc]
[reagent.impl.template :as tmpl]))

;; Should be only set for tests....
;; (set! (.-IS_REACT_ACT_ENVIRONMENT js/window) true)

;; Silence ReactDOM.render warning
(defonce original-console-error (.-error js/console))

(set! (.-error js/console)
(fn [& [first-arg :as args]]
(cond
(and (string? first-arg) (.startsWith first-arg "Warning: ReactDOM.render is no longer supported in React 18."))
nil

(and (string? first-arg) (.startsWith first-arg "Warning: The current testing environment is not configured to support"))
nil

Expand Down Expand Up @@ -80,23 +77,48 @@
(defn act*
"Run f to trigger Reagent updates,
will return Promise which will resolve after
Reagent and React render."
Reagent and React render.
In production builds, the React.act isn't available,
so just mock with 17ms timeout... Hopefully that usually
is enough time for React to flush the queue?"
[f]
(let [p (p/deferred)]
(f)
(r/flush)
(r/after-render (fn []
(p/resolve! p)))
p))
;; async act doesn't return a real promise (with chainable then),
;; so wrap it.
(if (dev?)
(js/Promise.
(fn [resolve reject]
(try
(.then (react/act (fn []
(js/Promise. (fn [resolve reject]
(try
(f)
(r/after-render (fn [] (resolve)))
(catch :default e
(reject e)))))))
resolve
reject)
(catch :default e
(reject e)))))
(js/Promise.
(fn [resolve reject]
(try
(f)
(js/setTimeout (fn []
(resolve))
;; 16.6ms is one animation frame @ 60hz
17)
(catch :default e
(reject e)))))))

(def ^:dynamic *render-error* nil)

(defn with-render*
"Render the given component to a DOM node,
after the the component is mounted to DOM,
run the given function and wait for the Promise
returned from the function to be resolved
before unmounting the component from DOM."
"Run initial render with React/act and then run
given function to check the results. If the function
also returns a Promise or thenable, this function
waits until that is resolved, before unmounting the
root and resolving the Promise this function returns."
([comp f]
(with-render* comp *test-compiler* f))
([comp options f]
Expand All @@ -107,18 +129,23 @@
compiler (:compiler options)
restore-error-handlers (when (:capture-errors options)
(init-capture))
root (rdomc/create-root div)
;; Magic setup to make exception from render available to the
;; with-render body.
render-error (atom nil)]
(try
(if compiler
(rdom/render comp div {:compiler compiler
:callback callback})
(rdom/render comp div callback))
(catch :default e
(reset! render-error e)
nil))
(-> first-render
(-> (act* (fn []
(try
(if compiler
(rdomc/render root comp compiler)
(rdomc/render root comp))
(catch :default e
(js/console.log "CATCH RENDER CALL" e)
(reset! render-error e)
nil))))
(p/catch (fn [e]
(js/console.log "CATCH RENDER?" e)
(reset! render-error e)
(p/resolved nil)))
;; The callback is called even if render throws an error,
;; so this is always resolved.
(p/then (fn []
Expand All @@ -128,9 +155,12 @@
(set! *render-error* nil))))
;; If f throws more errors, just ignore them?
;; Not sure if this makes sense.
(p/catch (fn [] nil))
;; TODO: Might need to catch the errors here? Maybe
(p/catch (fn [e]
(js/console.log "CATCH2 RENDER?" e)
nil))
(p/then (fn []
(rdom/unmount-component-at-node div)
(.unmount root)
;; Need to wait for reagent tick after unmount
;; for the ratom watches to be removed?
(let [ratoms-cleaned (p/deferred)]
Expand Down

0 comments on commit 34d6abd

Please sign in to comment.