@@ -2,8 +2,9 @@ import { beforeEach, expect, jest, test } from "@jest/globals";
22import { Component , Suspense , use , useEffect , useId } from "react" ;
33
44import { createRoot } from "../renderer" ;
5- import { act , renderWithAct } from "../test-utils/render" ;
5+ import { act , getRootInstance , renderWithAct } from "../test-utils/render" ;
66import type { JsonElement , JsonNode } from "../to-json" ;
7+ import { Props } from "../reconciler" ;
78
89beforeEach ( ( ) => {
910 global . IS_REACT_ACT_ENVIRONMENT = true ;
@@ -99,148 +100,115 @@ test("onCaughtError is called when error is caught by Error Boundary", async ()
99100 expect ( ( onCaughtError . mock . calls [ 0 ] ?. [ 0 ] as Error ) . message ) . toBe ( "Test caught error" ) ;
100101} ) ;
101102
102- test ( "transformHiddenInstanceProps keeps hidden instances in children and JSON output" , async ( ) => {
103- let resolvePromise : ( value : string ) => void ;
104- const pendingPromise = new Promise < string > ( ( resolve ) => {
105- resolvePromise = resolve ;
106- } ) ;
103+ function AsyncStatus ( { promise } : { promise : Promise < void > } ) {
104+ use ( promise ) ;
105+ return < div > Content</ div > ;
106+ }
107107
108- function AsyncContent ( { valuePromise } : { valuePromise : Promise < string > } ) {
109- const value = use ( valuePromise ) ;
110- return (
111- < div data-testid = "content" style = { { opacity : 1 } } >
112- Content: { value }
113- </ div >
114- ) ;
115- }
108+ const transformHiddenInstanceProps = ( { props } : { props : Props } ) => ( {
109+ ...props ,
110+ "data-is-hidden" : true ,
111+ } ) ;
116112
117- const renderer = createRoot ( {
118- transformHiddenInstanceProps : ( { props, type } ) => ( {
119- ...props ,
120- style : withHiddenStyle ( props . style ) ,
121- "data-hidden-instance-type" : type ,
122- } ) ,
113+ test ( "without transformHiddenInstanceProps it hides instances in JSON output" , async ( ) => {
114+ let resolvePromise : ( ) => void ;
115+ const pendingPromise = new Promise < void > ( ( resolve ) => {
116+ resolvePromise = resolve ;
123117 } ) ;
124118
119+ const renderer = createRoot ( ) ;
125120 await renderWithAct (
126121 renderer ,
127- < Suspense fallback = { < div data-testid = "fallback" > Loading... </ div > } >
128- < AsyncContent valuePromise = { Promise . resolve ( "Visible" ) } />
122+ < Suspense fallback = { < div > Fallback </ div > } >
123+ < AsyncStatus promise = { Promise . resolve ( ) } />
129124 </ Suspense > ,
130125 ) ;
131126
127+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
128+ <>
129+ <div>
130+ Content
131+ </div>
132+ </>
133+ ` ) ;
134+
132135 await renderWithAct (
133136 renderer ,
134- < Suspense fallback = { < div data-testid = "fallback" > Loading... </ div > } >
135- < AsyncContent valuePromise = { pendingPromise } />
137+ < Suspense fallback = { < div > Fallback </ div > } >
138+ < AsyncStatus promise = { pendingPromise } />
136139 </ Suspense > ,
137140 ) ;
138141
139- const contentInstances = renderer . container . queryAll (
140- ( instance ) => instance . props [ "data-testid" ] === "content" ,
141- ) ;
142- expect ( contentInstances ) . toHaveLength ( 1 ) ;
143- expect ( contentInstances [ 0 ] ?. props . style ) . toEqual ( [ { opacity : 1 } , { display : "none" } ] ) ;
144- expect ( contentInstances [ 0 ] ?. props [ "data-hidden-instance-type" ] ) . toBe ( "div" ) ;
145-
146- const fallbackInstances = renderer . container . queryAll (
147- ( instance ) => instance . props [ "data-testid" ] === "fallback" ,
148- ) ;
149- expect ( fallbackInstances ) . toHaveLength ( 1 ) ;
150-
151- const json = renderer . container . toJSON ( ) ;
152- expect ( json ) . not . toBeNull ( ) ;
153- expect ( findJsonByTestId ( json ! , "content" ) ) . not . toBeNull ( ) ;
154- expect ( findJsonByTestId ( json ! , "fallback" ) ) . not . toBeNull ( ) ;
142+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
143+ <>
144+ <div>
145+ Fallback
146+ </div>
147+ </>
148+ ` ) ;
155149
156150 await act ( ( ) => {
157- resolvePromise ! ( "Done" ) ;
151+ resolvePromise ! ( ) ;
158152 } ) ;
153+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
154+ <>
155+ <div>
156+ Content
157+ </div>
158+ </>
159+ ` ) ;
159160} ) ;
160161
161- test ( "transformHiddenInstanceProps restores original props when instance becomes visible " , async ( ) => {
162- let resolvePromise : ( value : string ) => void ;
163- const pendingPromise = new Promise < string > ( ( resolve ) => {
162+ test ( "transformHiddenInstanceProps keeps hidden instances in JSON output " , async ( ) => {
163+ let resolvePromise : ( ) => void ;
164+ const pendingPromise = new Promise < void > ( ( resolve ) => {
164165 resolvePromise = resolve ;
165166 } ) ;
166167
167- function AsyncContent ( { valuePromise } : { valuePromise : Promise < string > } ) {
168- const value = use ( valuePromise ) ;
169- return (
170- < div data-testid = "content" style = { { opacity : 1 } } >
171- Content: { value }
172- </ div >
173- ) ;
174- }
175-
176- const renderer = createRoot ( {
177- transformHiddenInstanceProps : ( { props, type } ) => ( {
178- ...props ,
179- style : withHiddenStyle ( props . style ) ,
180- "data-hidden-instance-type" : type ,
181- } ) ,
182- } ) ;
183-
168+ const renderer = createRoot ( { transformHiddenInstanceProps } ) ;
184169 await renderWithAct (
185170 renderer ,
186- < Suspense fallback = { < div > Loading... </ div > } >
187- < AsyncContent valuePromise = { Promise . resolve ( "Visible" ) } />
171+ < Suspense fallback = { < div > Fallback </ div > } >
172+ < AsyncStatus promise = { Promise . resolve ( ) } />
188173 </ Suspense > ,
189174 ) ;
190175
176+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
177+ <>
178+ <div>
179+ Content
180+ </div>
181+ </>
182+ ` ) ;
183+
191184 await renderWithAct (
192185 renderer ,
193- < Suspense fallback = { < div > Loading... </ div > } >
194- < AsyncContent valuePromise = { pendingPromise } />
186+ < Suspense fallback = { < div > Fallback </ div > } >
187+ < AsyncStatus promise = { pendingPromise } />
195188 </ Suspense > ,
196189 ) ;
197190
198- const hiddenContent = renderer . container . queryAll (
199- ( instance ) => instance . props [ "data-testid" ] === "content" ,
200- ) ;
201- expect ( hiddenContent ) . toHaveLength ( 1 ) ;
202- expect ( hiddenContent [ 0 ] ?. props . style ) . toEqual ( [ { opacity : 1 } , { display : "none" } ] ) ;
203- expect ( hiddenContent [ 0 ] ?. props [ "data-hidden-instance-type" ] ) . toBe ( "div" ) ;
191+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
192+ <>
193+ <div
194+ data-is-hidden={true}
195+ >
196+ Content
197+ </div>
198+ <div>
199+ Fallback
200+ </div>
201+ </>
202+ ` ) ;
204203
205204 await act ( ( ) => {
206- resolvePromise ! ( "Done" ) ;
205+ resolvePromise ! ( ) ;
207206 } ) ;
208-
209- const visibleContent = renderer . container . queryAll (
210- ( instance ) => instance . props [ "data-testid" ] === "content" ,
211- ) ;
212- expect ( visibleContent ) . toHaveLength ( 1 ) ;
213- expect ( visibleContent [ 0 ] ?. props . style ) . toEqual ( { opacity : 1 } ) ;
214- expect ( visibleContent [ 0 ] ?. props [ "data-hidden-instance-type" ] ) . toBeUndefined ( ) ;
207+ expect ( renderer . container ) . toMatchInlineSnapshot ( `
208+ <>
209+ <div>
210+ Content
211+ </div>
212+ </>
213+ ` ) ;
215214} ) ;
216-
217- function withHiddenStyle ( style : unknown ) : unknown [ ] {
218- if ( Array . isArray ( style ) ) {
219- return [ ...style , { display : "none" } ] ;
220- }
221-
222- if ( style == null ) {
223- return [ { display : "none" } ] ;
224- }
225-
226- return [ style , { display : "none" } ] ;
227- }
228-
229- function findJsonByTestId ( node : JsonNode , testId : string ) : JsonElement | null {
230- if ( typeof node === "string" ) {
231- return null ;
232- }
233-
234- if ( node . props [ "data-testid" ] === testId ) {
235- return node ;
236- }
237-
238- for ( const child of node . children ) {
239- const match = findJsonByTestId ( child , testId ) ;
240- if ( match != null ) {
241- return match ;
242- }
243- }
244-
245- return null ;
246- }
0 commit comments