Convert ReactIdentity-test.js to createRoot (#28106)
Matt Carroll committed
Jan 26, 2024 at 13:18 UTC
37bdff675c28e247333ffe35055534ad94941e8c
1 file changed
+70
-49
packages/react-dom/src/__tests__/ReactIdentity-test.js
+70
-49
@@ -10,18 +10,20 @@
10
'use strict';
11
12
let React;
13
-let ReactDOM;
13
+let ReactDOMClient;
14
let ReactTestUtils;
15
+let act;
16
17
describe('ReactIdentity', () => {
18
beforeEach(() => {
19
jest.resetModules();
20
React = require('react');
20
- ReactDOM = require('react-dom');
21
+ ReactDOMClient = require('react-dom/client');
22
ReactTestUtils = require('react-dom/test-utils');
23
+ act = require('internal-test-utils').act;
24
});
25
24
- it('should allow key property to express identity', () => {
26
+ it('should allow key property to express identity', async () => {
27
let node;
28
const Component = props => (
29
<div ref={c => (node = c)}>
@@ -31,15 +33,20 @@ describe('ReactIdentity', () => {
33
);
34
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
+ });
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
+ });
44
const newChildren = Array.from(node.childNodes);
45
expect(origChildren[0]).toBe(newChildren[1]);
46
expect(origChildren[1]).toBe(newChildren[0]);
47
});
48
42
- it('should use composite identity', () => {
49
+ it('should use composite identity', async () => {
50
class Wrapper extends React.Component {
51
render() {
52
return <a>{this.props.children}</a>;
@@ -47,25 +54,27 @@ describe('ReactIdentity', () => {
54
}
55
56
const container = document.createElement('div');
57
+ const root = ReactDOMClient.createRoot(container);
58
let node1;
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
+ });
74
expect(node1).not.toBe(node2);
75
});
76
68
- function renderAComponentWithKeyIntoContainer(key, container) {
77
+ async function renderAComponentWithKeyIntoContainer(key, root) {
78
class Wrapper extends React.Component {
79
spanRef = React.createRef();
80
render() {
@@ -76,36 +85,41 @@ describe('ReactIdentity', () => {
85
);
86
}
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;
93
expect(span).not.toBe(null);
94
}
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 () => {
97
const detachedContainer = document.createElement('div');
87
- renderAComponentWithKeyIntoContainer("<'WEIRD/&\\key'>", detachedContainer);
98
+ const root = ReactDOMClient.createRoot(detachedContainer);
99
+ await renderAComponentWithKeyIntoContainer("<'WEIRD/&\\key'>", root);
100
});
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 () => {
103
// This test exists to protect against implementation details that
104
// incorrectly query escaped IDs using DOM tools like getElementById.
105
const attachedContainer = document.createElement('div');
106
+ const root = ReactDOMClient.createRoot(attachedContainer);
107
document.body.appendChild(attachedContainer);
108
96
- renderAComponentWithKeyIntoContainer("<'WEIRD/&\\key'>", attachedContainer);
109
+ await renderAComponentWithKeyIntoContainer("<'WEIRD/&\\key'>", root);
110
111
document.body.removeChild(attachedContainer);
112
});
113
101
- it('should not allow scripts in keys to execute', () => {
114
+ it('should not allow scripts in keys to execute', async () => {
115
const h4x0rKey =
116
'"><script>window[\'YOUVEBEENH4X0RED\']=true;</script><div id="';
117
118
const attachedContainer = document.createElement('div');
119
+ const root = ReactDOMClient.createRoot(attachedContainer);
120
document.body.appendChild(attachedContainer);
121
108
- renderAComponentWithKeyIntoContainer(h4x0rKey, attachedContainer);
122
+ await renderAComponentWithKeyIntoContainer(h4x0rKey, root);
123
124
document.body.removeChild(attachedContainer);
125
@@ -209,7 +223,7 @@ describe('ReactIdentity', () => {
223
}).not.toThrow();
224
});
225
212
- it('should retain key during updates in composite components', () => {
226
+ it('should retain key during updates in composite components', async () => {
227
class TestComponent extends React.Component {
228
render() {
229
return <div>{this.props.children}</div>;
@@ -236,16 +250,23 @@ describe('ReactIdentity', () => {
250
const instance0 = <span key="A" />;
251
const instance1 = <span key="B" />;
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;
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;
270
271
expect(beforeA).toBe(afterA);
272
expect(beforeB).toBe(afterB);
@@ -264,7 +285,7 @@ describe('ReactIdentity', () => {
285
}).not.toThrow();
286
});
287
267
- it('should throw if key is a Temporal-like object', () => {
288
+ it('should throw if key is a Temporal-like object', async () => {
289
class TemporalLike {
290
valueOf() {
291
// Throwing here is the behavior of ECMAScript "Temporal" date/time API.
@@ -277,15 +298,15 @@ describe('ReactIdentity', () => {
298
}
299
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')),
310
).toErrorDev(
311
'The provided key is an unsupported type TemporalLike.' +
312
' This value must be coerced to a string before using it here.',