10
10
'use strict' ;
11
11
12
12
let React ;
13
- let ReactDOM ;
13
+ let ReactDOMClient ;
14
14
let ReactTestUtils ;
15
+ let act ;
15
16
16
17
describe ( 'ReactIdentity' , ( ) => {
17
18
beforeEach ( ( ) => {
18
19
jest . resetModules ( ) ;
19
20
React = require ( 'react' ) ;
20
- ReactDOM = require ( 'react-dom' ) ;
21
+ ReactDOMClient = require ( 'react-dom/client ' ) ;
21
22
ReactTestUtils = require ( 'react-dom/test-utils' ) ;
23
+ act = require ( 'internal-test-utils' ) . act ;
22
24
} ) ;
23
25
24
- it ( 'should allow key property to express identity' , ( ) => {
26
+ it ( 'should allow key property to express identity' , async ( ) => {
25
27
let node ;
26
28
const Component = props => (
27
29
< div ref = { c => ( node = c ) } >
@@ -31,41 +33,48 @@ describe('ReactIdentity', () => {
31
33
) ;
32
34
33
35
const container = document . createElement ( 'div' ) ;
34
- ReactDOM . render ( < Component /> , container ) ;
36
+ const root = ReactDOMClient . createRoot ( container ) ;
37
+ await act ( async ( ) => {
38
+ root . render ( < Component /> ) ;
39
+ } ) ;
35
40
const origChildren = Array . from ( node . childNodes ) ;
36
- ReactDOM . render ( < Component swap = { true } /> , container ) ;
41
+ await act ( async ( ) => {
42
+ root . render ( < Component swap = { true } /> ) ;
43
+ } ) ;
37
44
const newChildren = Array . from ( node . childNodes ) ;
38
45
expect ( origChildren [ 0 ] ) . toBe ( newChildren [ 1 ] ) ;
39
46
expect ( origChildren [ 1 ] ) . toBe ( newChildren [ 0 ] ) ;
40
47
} ) ;
41
48
42
- it ( 'should use composite identity' , ( ) => {
49
+ it ( 'should use composite identity' , async ( ) => {
43
50
class Wrapper extends React . Component {
44
51
render ( ) {
45
52
return < a > { this . props . children } </ a > ;
46
53
}
47
54
}
48
55
49
56
const container = document . createElement ( 'div' ) ;
57
+ const root = ReactDOMClient . createRoot ( container ) ;
50
58
let node1 ;
51
59
let node2 ;
52
- ReactDOM . render (
53
- < Wrapper key = "wrap1" >
54
- < span ref = { c => ( node1 = c ) } />
55
- </ Wrapper > ,
56
- container ,
57
- ) ;
58
- ReactDOM . render (
59
- < Wrapper key = "wrap2" >
60
- < span ref = { c => ( node2 = c ) } />
61
- </ Wrapper > ,
62
- container ,
63
- ) ;
64
-
60
+ await act ( async ( ) => {
61
+ root . render (
62
+ < Wrapper key = "wrap1" >
63
+ < span ref = { c => ( node1 = c ) } />
64
+ </ Wrapper > ,
65
+ ) ;
66
+ } ) ;
67
+ await act ( async ( ) => {
68
+ root . render (
69
+ < Wrapper key = "wrap2" >
70
+ < span ref = { c => ( node2 = c ) } />
71
+ </ Wrapper > ,
72
+ ) ;
73
+ } ) ;
65
74
expect ( node1 ) . not . toBe ( node2 ) ;
66
75
} ) ;
67
76
68
- function renderAComponentWithKeyIntoContainer ( key , container ) {
77
+ async function renderAComponentWithKeyIntoContainer ( key , root ) {
69
78
class Wrapper extends React . Component {
70
79
spanRef = React . createRef ( ) ;
71
80
render ( ) {
@@ -76,36 +85,41 @@ describe('ReactIdentity', () => {
76
85
) ;
77
86
}
78
87
}
79
-
80
- const instance = ReactDOM . render ( < Wrapper /> , container ) ;
81
- const span = instance . spanRef . current ;
88
+ const wrapperRef = React . createRef ( ) ;
89
+ await act ( async ( ) => {
90
+ root . render ( < Wrapper ref = { wrapperRef } /> ) ;
91
+ } ) ;
92
+ const span = wrapperRef . current . spanRef . current ;
82
93
expect ( span ) . not . toBe ( null ) ;
83
94
}
84
95
85
- it ( 'should allow any character as a key, in a detached parent' , ( ) => {
96
+ it ( 'should allow any character as a key, in a detached parent' , async ( ) => {
86
97
const detachedContainer = document . createElement ( 'div' ) ;
87
- renderAComponentWithKeyIntoContainer ( "<'WEIRD/&\\key'>" , detachedContainer ) ;
98
+ const root = ReactDOMClient . createRoot ( detachedContainer ) ;
99
+ await renderAComponentWithKeyIntoContainer ( "<'WEIRD/&\\key'>" , root ) ;
88
100
} ) ;
89
101
90
- it ( 'should allow any character as a key, in an attached parent' , ( ) => {
102
+ it ( 'should allow any character as a key, in an attached parent' , async ( ) => {
91
103
// This test exists to protect against implementation details that
92
104
// incorrectly query escaped IDs using DOM tools like getElementById.
93
105
const attachedContainer = document . createElement ( 'div' ) ;
106
+ const root = ReactDOMClient . createRoot ( attachedContainer ) ;
94
107
document . body . appendChild ( attachedContainer ) ;
95
108
96
- renderAComponentWithKeyIntoContainer ( "<'WEIRD/&\\key'>" , attachedContainer ) ;
109
+ await renderAComponentWithKeyIntoContainer ( "<'WEIRD/&\\key'>" , root ) ;
97
110
98
111
document . body . removeChild ( attachedContainer ) ;
99
112
} ) ;
100
113
101
- it ( 'should not allow scripts in keys to execute' , ( ) => {
114
+ it ( 'should not allow scripts in keys to execute' , async ( ) => {
102
115
const h4x0rKey =
103
116
'"><script>window[\'YOUVEBEENH4X0RED\']=true;</script><div id="' ;
104
117
105
118
const attachedContainer = document . createElement ( 'div' ) ;
119
+ const root = ReactDOMClient . createRoot ( attachedContainer ) ;
106
120
document . body . appendChild ( attachedContainer ) ;
107
121
108
- renderAComponentWithKeyIntoContainer ( h4x0rKey , attachedContainer ) ;
122
+ await renderAComponentWithKeyIntoContainer ( h4x0rKey , root ) ;
109
123
110
124
document . body . removeChild ( attachedContainer ) ;
111
125
@@ -209,7 +223,7 @@ describe('ReactIdentity', () => {
209
223
} ) . not . toThrow ( ) ;
210
224
} ) ;
211
225
212
- it ( 'should retain key during updates in composite components' , ( ) => {
226
+ it ( 'should retain key during updates in composite components' , async ( ) => {
213
227
class TestComponent extends React . Component {
214
228
render ( ) {
215
229
return < div > { this . props . children } </ div > ;
@@ -236,16 +250,23 @@ describe('ReactIdentity', () => {
236
250
const instance0 = < span key = "A" /> ;
237
251
const instance1 = < span key = "B" /> ;
238
252
239
- let wrapped = < TestContainer first = { instance0 } second = { instance1 } /> ;
240
-
241
- wrapped = ReactDOM . render ( wrapped , document . createElement ( 'div' ) ) ;
242
- const div = ReactDOM . findDOMNode ( wrapped ) ;
253
+ const container = document . createElement ( 'div' ) ;
254
+ const root = ReactDOMClient . createRoot ( container ) ;
255
+ const wrappedRef = React . createRef ( ) ;
256
+ await act ( async ( ) => {
257
+ root . render (
258
+ < TestContainer first = { instance0 } second = { instance1 } ref = { wrappedRef } /> ,
259
+ ) ;
260
+ } ) ;
261
+ const div = container . firstChild ;
243
262
244
- const beforeA = div . childNodes [ 0 ] ;
245
- const beforeB = div . childNodes [ 1 ] ;
246
- wrapped . swap ( ) ;
247
- const afterA = div . childNodes [ 1 ] ;
248
- const afterB = div . childNodes [ 0 ] ;
263
+ const beforeA = div . firstChild ;
264
+ const beforeB = div . lastChild ;
265
+ await act ( async ( ) => {
266
+ wrappedRef . current . swap ( ) ;
267
+ } ) ;
268
+ const afterA = div . lastChild ;
269
+ const afterB = div . firstChild ;
249
270
250
271
expect ( beforeA ) . toBe ( afterA ) ;
251
272
expect ( beforeB ) . toBe ( afterB ) ;
@@ -264,7 +285,7 @@ describe('ReactIdentity', () => {
264
285
} ) . not . toThrow ( ) ;
265
286
} ) ;
266
287
267
- it ( 'should throw if key is a Temporal-like object' , ( ) => {
288
+ it ( 'should throw if key is a Temporal-like object' , async ( ) => {
268
289
class TemporalLike {
269
290
valueOf ( ) {
270
291
// Throwing here is the behavior of ECMAScript "Temporal" date/time API.
@@ -277,15 +298,15 @@ describe('ReactIdentity', () => {
277
298
}
278
299
279
300
const el = document . createElement ( 'div' ) ;
280
- const test = ( ) =>
281
- ReactDOM . render (
282
- < div >
283
- < span key = { new TemporalLike ( ) } />
284
- </ div > ,
285
- el ,
286
- ) ;
287
- expect ( ( ) =>
288
- expect ( test ) . toThrowError ( new TypeError ( 'prod message' ) ) ,
301
+ const root = ReactDOMClient . createRoot ( el ) ;
302
+ await expect ( ( ) =>
303
+ expect ( ( ) => {
304
+ root . render (
305
+ < div >
306
+ < span key = { new TemporalLike ( ) } />
307
+ </ div > ,
308
+ ) ;
309
+ } ) . toThrowError ( new TypeError ( 'prod message' ) ) ,
289
310
) . toErrorDev (
290
311
'The provided key is an unsupported type TemporalLike.' +
291
312
' This value must be coerced to a string before using it here.' ,
0 commit comments