11
11
12
12
let React ;
13
13
let ReactDOM ;
14
- let ReactTestUtils ;
14
+ let ReactDOMClient ;
15
15
let PropTypes ;
16
+ let act ;
16
17
17
18
describe ( 'ReactLegacyCompositeComponent' , ( ) => {
18
19
beforeEach ( ( ) => {
19
20
jest . resetModules ( ) ;
20
21
React = require ( 'react' ) ;
21
22
ReactDOM = require ( 'react-dom' ) ;
22
- ReactTestUtils = require ( 'react-dom/test-utils ' ) ;
23
+ ReactDOMClient = require ( 'react-dom/client ' ) ;
23
24
PropTypes = require ( 'prop-types' ) ;
25
+ act = require ( 'internal-test-utils' ) . act ;
24
26
} ) ;
25
27
26
28
it ( 'should warn about `setState` in render in legacy mode' , ( ) => {
@@ -70,7 +72,7 @@ describe('ReactLegacyCompositeComponent', () => {
70
72
} ) ;
71
73
72
74
// @gate !disableLegacyContext
73
- it ( 'should pass context to children when not owner' , ( ) => {
75
+ it ( 'should pass context to children when not owner' , async ( ) => {
74
76
class Parent extends React . Component {
75
77
render ( ) {
76
78
return (
@@ -106,13 +108,17 @@ describe('ReactLegacyCompositeComponent', () => {
106
108
return < div > { this . context . foo } </ div > ;
107
109
}
108
110
}
109
-
110
- const component = ReactTestUtils . renderIntoDocument ( < Parent /> ) ;
111
+ const container = document . createElement ( 'div' ) ;
112
+ const root = ReactDOMClient . createRoot ( container ) ;
113
+ let component ;
114
+ await act ( ( ) => {
115
+ root . render ( < Parent ref = { current => ( component = current ) } /> ) ;
116
+ } ) ;
111
117
expect ( ReactDOM . findDOMNode ( component ) . innerHTML ) . toBe ( 'bar' ) ;
112
118
} ) ;
113
119
114
120
// @gate !disableLegacyContext
115
- it ( 'should pass context when re-rendered for static child' , ( ) => {
121
+ it ( 'should pass context when re-rendered for static child' , async ( ) => {
116
122
let parentInstance = null ;
117
123
let childInstance = null ;
118
124
@@ -156,24 +162,31 @@ describe('ReactLegacyCompositeComponent', () => {
156
162
}
157
163
}
158
164
159
- parentInstance = ReactTestUtils . renderIntoDocument (
160
- < Parent >
161
- < Middle >
162
- < Child />
163
- </ Middle >
164
- </ Parent > ,
165
- ) ;
165
+ const container = document . createElement ( 'div' ) ;
166
+ const root = ReactDOMClient . createRoot ( container ) ;
167
+
168
+ await act ( ( ) => {
169
+ root . render (
170
+ < Parent ref = { current => ( parentInstance = current ) } >
171
+ < Middle >
172
+ < Child />
173
+ </ Middle >
174
+ </ Parent > ,
175
+ ) ;
176
+ } ) ;
166
177
167
178
expect ( parentInstance . state . flag ) . toBe ( false ) ;
168
179
expect ( childInstance . context ) . toEqual ( { foo : 'bar' , flag : false } ) ;
169
180
170
- parentInstance . setState ( { flag : true } ) ;
181
+ await act ( ( ) => {
182
+ parentInstance . setState ( { flag : true } ) ;
183
+ } ) ;
171
184
expect ( parentInstance . state . flag ) . toBe ( true ) ;
172
185
expect ( childInstance . context ) . toEqual ( { foo : 'bar' , flag : true } ) ;
173
186
} ) ;
174
187
175
188
// @gate !disableLegacyContext
176
- it ( 'should pass context when re-rendered for static child within a composite component' , ( ) => {
189
+ it ( 'should pass context when re-rendered for static child within a composite component' , async ( ) => {
177
190
class Parent extends React . Component {
178
191
static childContextTypes = {
179
192
flag : PropTypes . bool ,
@@ -217,20 +230,27 @@ describe('ReactLegacyCompositeComponent', () => {
217
230
}
218
231
}
219
232
220
- const wrapper = ReactTestUtils . renderIntoDocument ( < Wrapper /> ) ;
233
+ const container = document . createElement ( 'div' ) ;
234
+ const root = ReactDOMClient . createRoot ( container ) ;
235
+ let wrapper ;
236
+ await act ( ( ) => {
237
+ root . render ( < Wrapper ref = { current => ( wrapper = current ) } /> ) ;
238
+ } ) ;
221
239
222
240
expect ( wrapper . parentRef . current . state . flag ) . toEqual ( true ) ;
223
241
expect ( wrapper . childRef . current . context ) . toEqual ( { flag : true } ) ;
224
242
225
243
// We update <Parent /> while <Child /> is still a static prop relative to this update
226
- wrapper . parentRef . current . setState ( { flag : false } ) ;
244
+ await act ( ( ) => {
245
+ wrapper . parentRef . current . setState ( { flag : false } ) ;
246
+ } ) ;
227
247
228
248
expect ( wrapper . parentRef . current . state . flag ) . toEqual ( false ) ;
229
249
expect ( wrapper . childRef . current . context ) . toEqual ( { flag : false } ) ;
230
250
} ) ;
231
251
232
252
// @gate !disableLegacyContext
233
- it ( 'should pass context transitively' , ( ) => {
253
+ it ( 'should pass context transitively' , async ( ) => {
234
254
let childInstance = null ;
235
255
let grandchildInstance = null ;
236
256
@@ -286,13 +306,18 @@ describe('ReactLegacyCompositeComponent', () => {
286
306
}
287
307
}
288
308
289
- ReactTestUtils . renderIntoDocument ( < Parent /> ) ;
309
+ const container = document . createElement ( 'div' ) ;
310
+ const root = ReactDOMClient . createRoot ( container ) ;
311
+ await act ( ( ) => {
312
+ root . render ( < Parent /> ) ;
313
+ } ) ;
314
+
290
315
expect ( childInstance . context ) . toEqual ( { foo : 'bar' , depth : 0 } ) ;
291
316
expect ( grandchildInstance . context ) . toEqual ( { foo : 'bar' , depth : 1 } ) ;
292
317
} ) ;
293
318
294
319
// @gate !disableLegacyContext
295
- it ( 'should pass context when re-rendered' , ( ) => {
320
+ it ( 'should pass context when re-rendered' , async ( ) => {
296
321
let parentInstance = null ;
297
322
let childInstance = null ;
298
323
@@ -334,11 +359,16 @@ describe('ReactLegacyCompositeComponent', () => {
334
359
}
335
360
}
336
361
337
- parentInstance = ReactTestUtils . renderIntoDocument ( < Parent /> ) ;
362
+ const container = document . createElement ( 'div' ) ;
363
+ const root = ReactDOMClient . createRoot ( container ) ;
364
+ await act ( ( ) => {
365
+ root . render ( < Parent ref = { current => ( parentInstance = current ) } /> ) ;
366
+ } ) ;
367
+
338
368
expect ( childInstance ) . toBeNull ( ) ;
339
369
340
370
expect ( parentInstance . state . flag ) . toBe ( false ) ;
341
- ReactDOM . unstable_batchedUpdates ( function ( ) {
371
+ await act ( ( ) => {
342
372
parentInstance . setState ( { flag : true } ) ;
343
373
} ) ;
344
374
expect ( parentInstance . state . flag ) . toBe ( true ) ;
@@ -699,23 +729,31 @@ describe('ReactLegacyCompositeComponent', () => {
699
729
) ;
700
730
} ) ;
701
731
702
- it ( 'should replace state in legacy mode' , ( ) => {
732
+ it ( 'should replace state in legacy mode' , async ( ) => {
703
733
class Moo extends React . Component {
704
734
state = { x : 1 } ;
705
735
render ( ) {
706
736
return < div /> ;
707
737
}
708
738
}
709
739
710
- const moo = ReactTestUtils . renderIntoDocument ( < Moo /> ) ;
740
+ const container = document . createElement ( 'div' ) ;
741
+ const root = ReactDOMClient . createRoot ( container ) ;
742
+ let moo ;
743
+ await act ( ( ) => {
744
+ root . render ( < Moo ref = { current => ( moo = current ) } /> ) ;
745
+ } ) ;
746
+
711
747
// No longer a public API, but we can test that it works internally by
712
748
// reaching into the updater.
713
- moo . updater . enqueueReplaceState ( moo , { y : 2 } ) ;
749
+ await act ( ( ) => {
750
+ moo . updater . enqueueReplaceState ( moo , { y : 2 } ) ;
751
+ } ) ;
714
752
expect ( 'x' in moo . state ) . toBe ( false ) ;
715
753
expect ( moo . state . y ) . toBe ( 2 ) ;
716
754
} ) ;
717
755
718
- it ( 'should support objects with prototypes as state in legacy mode' , ( ) => {
756
+ it ( 'should support objects with prototypes as state in legacy mode' , async ( ) => {
719
757
const NotActuallyImmutable = function ( str ) {
720
758
this . str = str ;
721
759
} ;
@@ -732,32 +770,42 @@ describe('ReactLegacyCompositeComponent', () => {
732
770
}
733
771
}
734
772
735
- const moo = ReactTestUtils . renderIntoDocument ( < Moo /> ) ;
773
+ const container = document . createElement ( 'div' ) ;
774
+ const root = ReactDOMClient . createRoot ( container ) ;
775
+ let moo ;
776
+ await act ( ( ) => {
777
+ root . render ( < Moo ref = { current => ( moo = current ) } /> ) ;
778
+ } ) ;
779
+
736
780
expect ( moo . state . str ) . toBe ( 'first' ) ;
737
781
expect ( moo . state . amIImmutable ( ) ) . toBe ( true ) ;
738
782
739
783
const secondState = new NotActuallyImmutable ( 'second' ) ;
740
- moo . _replaceState ( secondState ) ;
784
+ await act ( ( ) => {
785
+ moo . _replaceState ( secondState ) ;
786
+ } ) ;
741
787
expect ( moo . state . str ) . toBe ( 'second' ) ;
742
788
expect ( moo . state . amIImmutable ( ) ) . toBe ( true ) ;
743
789
expect ( moo . state ) . toBe ( secondState ) ;
744
790
745
- moo . setState ( { str : 'third' } ) ;
791
+ await act ( ( ) => {
792
+ moo . setState ( { str : 'third' } ) ;
793
+ } ) ;
746
794
expect ( moo . state . str ) . toBe ( 'third' ) ;
747
795
// Here we lose the prototype.
748
796
expect ( moo . state . amIImmutable ) . toBe ( undefined ) ;
749
797
750
798
// When more than one state update is enqueued, we have the same behavior
751
799
const fifthState = new NotActuallyImmutable ( 'fifth' ) ;
752
- ReactDOM . unstable_batchedUpdates ( function ( ) {
800
+ await act ( ( ) => {
753
801
moo . setState ( { str : 'fourth' } ) ;
754
802
moo . _replaceState ( fifthState ) ;
755
803
} ) ;
756
804
expect ( moo . state ) . toBe ( fifthState ) ;
757
805
758
806
// When more than one state update is enqueued, we have the same behavior
759
807
const sixthState = new NotActuallyImmutable ( 'sixth' ) ;
760
- ReactDOM . unstable_batchedUpdates ( function ( ) {
808
+ await act ( ( ) => {
761
809
moo . _replaceState ( sixthState ) ;
762
810
moo . setState ( { str : 'seventh' } ) ;
763
811
} ) ;
0 commit comments