|
1 | 1 | (ns reagenttest.utils |
2 | 2 | (:require-macros reagenttest.utils) |
3 | | - (:require [promesa.core :as p] |
| 3 | + (:require ["react" :as react] |
| 4 | + [promesa.core :as p] |
4 | 5 | [reagent.core :as r] |
5 | 6 | [reagent.debug :as debug] |
6 | | - [reagent.dom.server :as server] |
7 | 7 | [reagent.dom.client :as rdomc] |
8 | | - [reagent.impl.template :as tmpl])) |
| 8 | + [reagent.dom.server :as server] |
| 9 | + [reagent.impl.template :as tmpl] |
| 10 | + [reagent.dom :as rdom])) |
9 | 11 |
|
10 | | -;; Should be only set for tests.... |
11 | | -;; (set! (.-IS_REACT_ACT_ENVIRONMENT js/window) true) |
| 12 | +(def OLD-REACT (<= (js/parseInt react/version) 18)) |
12 | 13 |
|
13 | 14 | (when-not (.-wrapped (.-error js/console)) |
14 | 15 | (let [original-console-error (.-error js/console)] |
15 | 16 | (set! (.-error js/console) |
16 | 17 | (fn [& [first-arg :as args]] |
17 | 18 | (cond |
| 19 | + (and OLD-REACT (string? first-arg) (.startsWith first-arg "Warning: ReactDOM.render is no longer supported in React 18.")) |
| 20 | + nil |
| 21 | + |
18 | 22 | (and (string? first-arg) (.startsWith first-arg "Warning: The current testing environment is not configured to support")) |
19 | 23 | nil |
20 | 24 |
|
|
113 | 117 | (catch :default e |
114 | 118 | (reject e)))))) |
115 | 119 |
|
116 | | -(defn with-render* |
| 120 | +(def ^:dynamic *render-error* nil) |
| 121 | + |
| 122 | +(defn old-with-render* |
117 | 123 | "Run initial render and wait for the component to be mounted on the dom and then run |
118 | 124 | given function to check the results. If the function |
119 | 125 | also returns a Promise or thenable, this function |
120 | 126 | waits until that is resolved, before unmounting the |
121 | 127 | root and resolving the Promise this function returns." |
122 | 128 | ([comp f] |
123 | | - (with-render* comp *test-compiler* f)) |
| 129 | + (old-with-render* comp *test-compiler* f)) |
124 | 130 | ([comp options f] |
125 | 131 | (let [div (.createElement js/document "div") |
126 | 132 | first-render (p/deferred) |
127 | 133 | callback (fn [] |
128 | 134 | (p/resolve! first-render)) |
129 | 135 | compiler (:compiler options) |
130 | | - strict? (:strict? options) |
131 | 136 | restore-error-handlers (when (:capture-errors options) |
132 | 137 | (init-capture)) |
133 | | - root (rdomc/create-root div) |
134 | 138 | ;; Magic setup to make exception from render available to the |
135 | 139 | ;; with-render body. |
136 | 140 | render-error (atom nil)] |
| 141 | + (try |
| 142 | + (if compiler |
| 143 | + (rdom/render comp div {:compiler compiler |
| 144 | + :callback callback}) |
| 145 | + (rdom/render comp div callback)) |
| 146 | + (catch :default e |
| 147 | + (reset! render-error e) |
| 148 | + nil)) |
| 149 | + (-> (act* (fn [] first-render)) |
| 150 | + ;; The callback is called even if render throws an error, |
| 151 | + ;; so this is always resolved. |
| 152 | + (p/then (fn [] |
| 153 | + (p/do |
| 154 | + (set! *render-error* @render-error) |
| 155 | + (f div) |
| 156 | + (set! *render-error* nil)))) |
| 157 | + ;; If f throws more errors, just ignore them? |
| 158 | + ;; Not sure if this makes sense. |
| 159 | + (p/catch (fn [] nil)) |
| 160 | + (p/then (fn [] |
| 161 | + (rdom/unmount-component-at-node div) |
| 162 | + ;; Need to wait for reagent tick after unmount |
| 163 | + ;; for the ratom watches to be removed? |
| 164 | + (let [ratoms-cleaned (p/deferred)] |
| 165 | + (r/next-tick (fn [] |
| 166 | + (p/resolve! ratoms-cleaned))) |
| 167 | + ratoms-cleaned))) |
| 168 | + (p/finally (fn [] |
| 169 | + (when restore-error-handlers |
| 170 | + (restore-error-handlers)))))))) |
| 171 | + |
| 172 | +(defn new-with-render* |
| 173 | + "Run initial render and wait for the component to be mounted on the dom and then run |
| 174 | + given function to check the results. If the function |
| 175 | + also returns a Promise or thenable, this function |
| 176 | + waits until that is resolved, before unmounting the |
| 177 | + root and resolving the Promise this function returns." |
| 178 | + ([comp f] |
| 179 | + (new-with-render* comp *test-compiler* f)) |
| 180 | + ([comp options f] |
| 181 | + (let [div (.createElement js/document "div") |
| 182 | + compiler (:compiler options) |
| 183 | + strict? (:strict? options) |
| 184 | + restore-error-handlers (when (:capture-errors options) |
| 185 | + (init-capture)) |
| 186 | + root (rdomc/create-root div)] |
137 | 187 | (-> (act* (fn [] |
138 | 188 | (rdomc/render root comp compiler strict?))) |
139 | 189 | ;; The callback is called even if render throws an error, |
|
151 | 201 | (p/finally (fn [] |
152 | 202 | (when restore-error-handlers |
153 | 203 | (restore-error-handlers)))))))) |
| 204 | + |
| 205 | +(def with-render* (if OLD-REACT old-with-render* new-with-render*)) |
0 commit comments