@@ -252,12 +252,6 @@ describe('ReactDOMServerPartialHydration', () => {
252252 } ) ;
253253
254254 it ( 'falls back to client rendering boundary on mismatch' , async ( ) => {
255- // We can't use the toErrorDev helper here because this is async.
256- const originalConsoleError = console . error ;
257- const mockError = jest . fn ( ) ;
258- console . error = ( ...args ) => {
259- mockError ( ...args . map ( normalizeCodeLocInfo ) ) ;
260- } ;
261255 let client = false ;
262256 let suspend = false ;
263257 let resolve ;
@@ -294,77 +288,58 @@ describe('ReactDOMServerPartialHydration', () => {
294288 </ Suspense >
295289 ) ;
296290 }
297- try {
298- const finalHTML = ReactDOMServer . renderToString ( < App /> ) ;
299- const container = document . createElement ( 'section' ) ;
300- container . innerHTML = finalHTML ;
301- assertLog ( [ 'Hello' , 'Component' , 'Component' , 'Component' , 'Component' ] ) ;
302-
303- expect ( container . innerHTML ) . toBe (
304- '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->' ,
305- ) ;
291+ const finalHTML = ReactDOMServer . renderToString ( < App /> ) ;
292+ const container = document . createElement ( 'section' ) ;
293+ container . innerHTML = finalHTML ;
294+ assertLog ( [ 'Hello' , 'Component' , 'Component' , 'Component' , 'Component' ] ) ;
306295
307- suspend = true ;
308- client = true ;
296+ expect ( container . innerHTML ) . toBe (
297+ '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->' ,
298+ ) ;
309299
310- ReactDOMClient . hydrateRoot ( container , < App /> , {
311- onRecoverableError ( error ) {
312- Scheduler . log ( normalizeError ( error . message ) ) ;
313- } ,
314- } ) ;
315- await waitForAll ( [ 'Suspend' ] ) ;
316- jest . runAllTimers ( ) ;
300+ suspend = true ;
301+ client = true ;
317302
318- // Unchanged
319- expect ( container . innerHTML ) . toBe (
320- '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->' ,
321- ) ;
303+ ReactDOMClient . hydrateRoot ( container , < App /> , {
304+ onRecoverableError ( error ) {
305+ Scheduler . log ( normalizeError ( error . message ) ) ;
306+ } ,
307+ } ) ;
308+ await waitForAll ( [ 'Suspend' ] ) ;
309+ jest . runAllTimers ( ) ;
322310
323- suspend = false ;
324- resolve ( ) ;
325- await promise ;
326- await waitForAll ( [
327- // first pass, mismatches at end
328- 'Hello' ,
329- 'Component' ,
330- 'Component' ,
331- 'Component' ,
332- 'Component' ,
333-
334- // second pass as client render
335- 'Hello' ,
336- 'Component' ,
337- 'Component' ,
338- 'Component' ,
339- 'Component' ,
340-
341- // Hydration mismatch is logged
342- "Hydration failed because the server rendered HTML didn't match the client." ,
343- 'There was an error while hydrating this Suspense boundary.' ,
344- ] ) ;
311+ // Unchanged
312+ expect ( container . innerHTML ) . toBe (
313+ '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->' ,
314+ ) ;
345315
346- // Client rendered - suspense comment nodes removed
347- expect ( container . innerHTML ) . toBe (
348- 'Hello<div>Component</div><div>Component</div><div>Component</div><article>Mismatch</article>' ,
349- ) ;
316+ suspend = false ;
317+ resolve ( ) ;
318+ await promise ;
319+ await waitForAll ( [
320+ // first pass, mismatches at end
321+ 'Hello' ,
322+ 'Component' ,
323+ 'Component' ,
324+ 'Component' ,
325+ 'Component' ,
326+
327+ // second pass as client render
328+ 'Hello' ,
329+ 'Component' ,
330+ 'Component' ,
331+ 'Component' ,
332+ 'Component' ,
333+
334+ // Hydration mismatch is logged
335+ "Hydration failed because the server rendered HTML didn't match the client." ,
336+ 'There was an error while hydrating this Suspense boundary.' ,
337+ ] ) ;
350338
351- if ( __DEV__ ) {
352- const secondToLastCall =
353- mockError . mock . calls [ mockError . mock . calls . length - 2 ] ;
354- expect ( secondToLastCall ) . toEqual ( [
355- 'Warning: Expected server HTML to contain a matching <%s> in <%s>.%s' ,
356- 'article' ,
357- 'Suspense' ,
358- '\n' +
359- ' in article (at **)\n' +
360- ' in Component (at **)\n' +
361- ' in Suspense (at **)\n' +
362- ' in App (at **)' ,
363- ] ) ;
364- }
365- } finally {
366- console . error = originalConsoleError ;
367- }
339+ // Client rendered - suspense comment nodes removed
340+ expect ( container . innerHTML ) . toBe (
341+ 'Hello<div>Component</div><div>Component</div><div>Component</div><article>Mismatch</article>' ,
342+ ) ;
368343 } ) ;
369344
370345 it ( 'calls the hydration callbacks after hydration or deletion' , async ( ) => {
@@ -522,38 +497,27 @@ describe('ReactDOMServerPartialHydration', () => {
522497 expect ( container . innerHTML ) . toContain ( '<span>B</span>' ) ;
523498 expect ( ref . current ) . toBe ( null ) ;
524499
525- await expect ( async ( ) => {
526- await act ( ( ) => {
527- ReactDOMClient . hydrateRoot ( container , < App hasB = { false } /> , {
528- onRecoverableError ( error ) {
529- Scheduler . log ( normalizeError ( error . message ) ) ;
530- } ,
531- } ) ;
500+ await act ( ( ) => {
501+ ReactDOMClient . hydrateRoot ( container , < App hasB = { false } /> , {
502+ onRecoverableError ( error ) {
503+ Scheduler . log ( normalizeError ( error . message ) ) ;
504+ } ,
532505 } ) ;
533- } ) . toErrorDev (
534- 'Did not expect server HTML to contain a <span> in <Suspense>' ,
535- ) ;
506+ } ) ;
536507
537508 expect ( container . innerHTML ) . toContain ( '<span>A</span>' ) ;
538509 expect ( container . innerHTML ) . not . toContain ( '<span>B</span>' ) ;
539510
540511 assertLog ( [
541512 'Server rendered' ,
542513 'Client rendered' ,
543- ' Hydration failed because the initial UI does not match what was rendered on the server.' ,
514+ " Hydration failed because the server rendered HTML didn't match the client." ,
544515 'There was an error while hydrating this Suspense boundary.' ,
545516 ] ) ;
546517 expect ( ref . current ) . not . toBe ( span ) ;
547518 } ) ;
548519
549520 it ( 'recovers with client render when server rendered additional nodes at suspense root after unsuspending' , async ( ) => {
550- // We can't use the toErrorDev helper here because this is async.
551- const originalConsoleError = console . error ;
552- const mockError = jest . fn ( ) ;
553- console . error = ( ...args ) => {
554- mockError ( ...args . map ( normalizeCodeLocInfo ) ) ;
555- } ;
556-
557521 const ref = React . createRef ( ) ;
558522 let shouldSuspend = false ;
559523 let resolve ;
@@ -581,44 +545,34 @@ describe('ReactDOMServerPartialHydration', () => {
581545 </ div >
582546 ) ;
583547 }
584- try {
585- const finalHTML = ReactDOMServer . renderToString ( < App hasB = { true } /> ) ;
548+ const finalHTML = ReactDOMServer . renderToString ( < App hasB = { true } /> ) ;
586549
587- const container = document . createElement ( 'div' ) ;
588- container . innerHTML = finalHTML ;
550+ const container = document . createElement ( 'div' ) ;
551+ container . innerHTML = finalHTML ;
589552
590- const span = container . getElementsByTagName ( 'span' ) [ 0 ] ;
553+ const span = container . getElementsByTagName ( 'span' ) [ 0 ] ;
591554
592- expect ( container . innerHTML ) . toContain ( '<span>A</span>' ) ;
593- expect ( container . innerHTML ) . toContain ( '<span>B</span>' ) ;
594- expect ( ref . current ) . toBe ( null ) ;
555+ expect ( container . innerHTML ) . toContain ( '<span>A</span>' ) ;
556+ expect ( container . innerHTML ) . toContain ( '<span>B</span>' ) ;
557+ expect ( ref . current ) . toBe ( null ) ;
595558
596- shouldSuspend = true ;
597- await act ( ( ) => {
598- ReactDOMClient . hydrateRoot ( container , < App hasB = { false } /> ) ;
599- } ) ;
559+ shouldSuspend = true ;
560+ await act ( ( ) => {
561+ ReactDOMClient . hydrateRoot ( container , < App hasB = { false } /> ) ;
562+ } ) ;
600563
564+ await expect ( async ( ) => {
601565 await act ( ( ) => {
602566 resolve ( ) ;
603567 } ) ;
568+ } ) . toErrorDev ( [
569+ "Hydration failed because the server rendered HTML didn't match the client." ,
570+ 'There was an error while hydrating this Suspense boundary. Switched to client rendering.' ,
571+ ] ) ;
604572
605- expect ( container . innerHTML ) . toContain ( '<span>A</span>' ) ;
606- expect ( container . innerHTML ) . not . toContain ( '<span>B</span>' ) ;
607- expect ( ref . current ) . not . toBe ( span ) ;
608- if ( __DEV__ ) {
609- expect ( mockError ) . toHaveBeenCalledWith (
610- 'Warning: Did not expect server HTML to contain a <%s> in <%s>.%s' ,
611- 'span' ,
612- 'Suspense' ,
613- '\n' +
614- ' in Suspense (at **)\n' +
615- ' in div (at **)\n' +
616- ' in App (at **)' ,
617- ) ;
618- }
619- } finally {
620- console . error = originalConsoleError ;
621- }
573+ expect ( container . innerHTML ) . toContain ( '<span>A</span>' ) ;
574+ expect ( container . innerHTML ) . not . toContain ( '<span>B</span>' ) ;
575+ expect ( ref . current ) . not . toBe ( span ) ;
622576 } ) ;
623577
624578 it ( 'recovers with client render when server rendered additional nodes deep inside suspense root' , async ( ) => {
0 commit comments