@@ -182,6 +182,140 @@ describe('suspense hydration', () => {
182
182
} ) ;
183
183
} ) ;
184
184
185
+ it ( 'should allow parents to update around suspense boundary and unmount' , async ( ) => {
186
+ scratch . innerHTML = '<div>Count: 0</div><div>Hello</div>' ;
187
+ clearLog ( ) ;
188
+
189
+ const [ Lazy , resolve ] = createLazy ( ) ;
190
+
191
+ /** @type {() => void } */
192
+ let increment ;
193
+ function Counter ( ) {
194
+ const [ count , setCount ] = useState ( 0 ) ;
195
+ increment = ( ) => setCount ( c => c + 1 ) ;
196
+ return (
197
+ < Fragment >
198
+ < div > Count: { count } </ div >
199
+ < Suspense >
200
+ < Lazy />
201
+ </ Suspense >
202
+ </ Fragment >
203
+ ) ;
204
+ }
205
+
206
+ let hide ;
207
+ function Component ( ) {
208
+ const [ show , setShow ] = useState ( true ) ;
209
+ hide = ( ) => setShow ( false ) ;
210
+
211
+ return show ? < Counter /> : null ;
212
+ }
213
+
214
+ hydrate ( < Component /> , scratch ) ;
215
+ rerender ( ) ; // Flush rerender queue to mimic what preact will really do
216
+ expect ( scratch . innerHTML ) . to . equal ( '<div>Count: 0</div><div>Hello</div>' ) ;
217
+ // Re: DOM OP below - Known issue with hydrating merged text nodes
218
+ expect ( getLog ( ) ) . to . deep . equal ( [ '<div>Count: .appendChild(#text)' ] ) ;
219
+ clearLog ( ) ;
220
+
221
+ increment ( ) ;
222
+ rerender ( ) ;
223
+
224
+ expect ( scratch . innerHTML ) . to . equal ( '<div>Count: 1</div><div>Hello</div>' ) ;
225
+ expect ( getLog ( ) ) . to . deep . equal ( [ ] ) ;
226
+ clearLog ( ) ;
227
+
228
+ await resolve ( ( ) => < div > Hello</ div > ) ;
229
+ rerender ( ) ;
230
+ expect ( scratch . innerHTML ) . to . equal ( '<div>Count: 1</div><div>Hello</div>' ) ;
231
+ expect ( getLog ( ) ) . to . deep . equal ( [ ] ) ;
232
+ clearLog ( ) ;
233
+
234
+ hide ( ) ;
235
+ rerender ( ) ;
236
+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
237
+ } ) ;
238
+
239
+ it ( 'should allow parents to update around suspense boundary and unmount before resolves' , async ( ) => {
240
+ scratch . innerHTML = '<div>Count: 0</div><div>Hello</div>' ;
241
+ clearLog ( ) ;
242
+
243
+ const [ Lazy ] = createLazy ( ) ;
244
+
245
+ /** @type {() => void } */
246
+ let increment ;
247
+ function Counter ( ) {
248
+ const [ count , setCount ] = useState ( 0 ) ;
249
+ increment = ( ) => setCount ( c => c + 1 ) ;
250
+ return (
251
+ < Fragment >
252
+ < div > Count: { count } </ div >
253
+ < Suspense >
254
+ < Lazy />
255
+ </ Suspense >
256
+ </ Fragment >
257
+ ) ;
258
+ }
259
+
260
+ let hide ;
261
+ function Component ( ) {
262
+ const [ show , setShow ] = useState ( true ) ;
263
+ hide = ( ) => setShow ( false ) ;
264
+
265
+ return show ? < Counter /> : null ;
266
+ }
267
+
268
+ hydrate ( < Component /> , scratch ) ;
269
+ rerender ( ) ; // Flush rerender queue to mimic what preact will really do
270
+ expect ( scratch . innerHTML ) . to . equal ( '<div>Count: 0</div><div>Hello</div>' ) ;
271
+ // Re: DOM OP below - Known issue with hydrating merged text nodes
272
+ expect ( getLog ( ) ) . to . deep . equal ( [ '<div>Count: .appendChild(#text)' ] ) ;
273
+ clearLog ( ) ;
274
+
275
+ increment ( ) ;
276
+ rerender ( ) ;
277
+
278
+ expect ( scratch . innerHTML ) . to . equal ( '<div>Count: 1</div><div>Hello</div>' ) ;
279
+ expect ( getLog ( ) ) . to . deep . equal ( [ ] ) ;
280
+ clearLog ( ) ;
281
+
282
+ hide ( ) ;
283
+ rerender ( ) ;
284
+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
285
+ } ) ;
286
+
287
+ it ( 'should allow parents to unmount before resolves' , async ( ) => {
288
+ scratch . innerHTML = '<div>Count: 0</div><div>Hello</div>' ;
289
+
290
+ const [ Lazy ] = createLazy ( ) ;
291
+
292
+ function Counter ( ) {
293
+ return (
294
+ < Fragment >
295
+ < div > Count: 0</ div >
296
+ < Suspense >
297
+ < Lazy />
298
+ </ Suspense >
299
+ </ Fragment >
300
+ ) ;
301
+ }
302
+
303
+ let hide ;
304
+ function Component ( ) {
305
+ const [ show , setShow ] = useState ( true ) ;
306
+ hide = ( ) => setShow ( false ) ;
307
+
308
+ return show ? < Counter /> : null ;
309
+ }
310
+
311
+ hydrate ( < Component /> , scratch ) ;
312
+ rerender ( ) ; // Flush rerender queue to mimic what preact will really do
313
+
314
+ hide ( ) ;
315
+ rerender ( ) ;
316
+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
317
+ } ) ;
318
+
185
319
it ( 'should properly hydrate when there is DOM and Components between Suspense and suspender' , ( ) => {
186
320
scratch . innerHTML = '<div><div>Hello</div></div>' ;
187
321
clearLog ( ) ;
0 commit comments