@samitouri / QOS-React-1 / commits / 759811b062

Convert ReactMultiChild-test.js to createRoot (#28117)

Matt Carroll committed Jan 26, 2024 at 13:18 UTC 759811b0627384e5dde8ac81397cb2b8c7390298
1 file changed +153 -104
packages/react-dom/src/__tests__/ReactMultiChild-test.js
+153 -104
@@ -11,17 +11,20 @@
11
12 describe('ReactMultiChild', () => {
13 let React;
14 - let ReactDOM;
14 + let ReactDOMClient;
15 + let act;
16
17 beforeEach(() => {
18 jest.resetModules();
19 React = require('react');
19 - ReactDOM = require('react-dom');
20 + ReactDOMClient = require('react-dom/client');
21 + act = require('internal-test-utils').act;
22 });
23
24 describe('reconciliation', () => {
23 - it('should update children when possible', () => {
25 + it('should update children when possible', async () => {
26 const container = document.createElement('div');
27 + const root = ReactDOMClient.createRoot(container);
28
29 const mockMount = jest.fn();
30 const mockUpdate = jest.fn();
@@ -40,31 +43,34 @@ describe('ReactMultiChild', () => {
43 expect(mockUpdate).toHaveBeenCalledTimes(0);
44 expect(mockUnmount).toHaveBeenCalledTimes(0);
45
43 - ReactDOM.render(
44 - <div>
45 - <MockComponent />
46 - </div>,
47 - container,
48 - );
46 + await act(async () => {
47 + root.render(
48 + <div>
49 + <MockComponent />
50 + </div>,
51 + );
52 + });
53
54 expect(mockMount).toHaveBeenCalledTimes(1);
55 expect(mockUpdate).toHaveBeenCalledTimes(0);
56 expect(mockUnmount).toHaveBeenCalledTimes(0);
57
54 - ReactDOM.render(
55 - <div>
56 - <MockComponent />
57 - </div>,
58 - container,
59 - );
58 + await act(async () => {
59 + root.render(
60 + <div>
61 + <MockComponent />
62 + </div>,
63 + );
64 + });
65
66 expect(mockMount).toHaveBeenCalledTimes(1);
67 expect(mockUpdate).toHaveBeenCalledTimes(1);
68 expect(mockUnmount).toHaveBeenCalledTimes(0);
69 });
70
66 - it('should replace children with different constructors', () => {
71 + it('should replace children with different constructors', async () => {
72 const container = document.createElement('div');
73 + const root = ReactDOMClient.createRoot(container);
74
75 const mockMount = jest.fn();
76 const mockUnmount = jest.fn();
@@ -80,29 +86,32 @@ describe('ReactMultiChild', () => {
86 expect(mockMount).toHaveBeenCalledTimes(0);
87 expect(mockUnmount).toHaveBeenCalledTimes(0);
88
83 - ReactDOM.render(
84 - <div>
85 - <MockComponent />
86 - </div>,
87 - container,
88 - );
89 + await act(async () => {
90 + root.render(
91 + <div>
92 + <MockComponent />
93 + </div>,
94 + );
95 + });
96
97 expect(mockMount).toHaveBeenCalledTimes(1);
98 expect(mockUnmount).toHaveBeenCalledTimes(0);
99
93 - ReactDOM.render(
94 - <div>
95 - <span />
96 - </div>,
97 - container,
98 - );
100 + await act(async () => {
101 + root.render(
102 + <div>
103 + <span />
104 + </div>,
105 + );
106 + });
107
108 expect(mockMount).toHaveBeenCalledTimes(1);
109 expect(mockUnmount).toHaveBeenCalledTimes(1);
110 });
111
104 - it('should NOT replace children with different owners', () => {
112 + it('should NOT replace children with different owners', async () => {
113 const container = document.createElement('div');
114 + const root = ReactDOMClient.createRoot(container);
115
116 const mockMount = jest.fn();
117 const mockUnmount = jest.fn();
@@ -124,24 +133,28 @@ describe('ReactMultiChild', () => {
133 expect(mockMount).toHaveBeenCalledTimes(0);
134 expect(mockUnmount).toHaveBeenCalledTimes(0);
135
127 - ReactDOM.render(<WrapperComponent />, container);
136 + await act(async () => {
137 + root.render(<WrapperComponent />);
138 + });
139
140 expect(mockMount).toHaveBeenCalledTimes(1);
141 expect(mockUnmount).toHaveBeenCalledTimes(0);
142
132 - ReactDOM.render(
133 - <WrapperComponent>
134 - <MockComponent />
135 - </WrapperComponent>,
136 - container,
137 - );
143 + await act(async () => {
144 + root.render(
145 + <WrapperComponent>
146 + <MockComponent />
147 + </WrapperComponent>,
148 + );
149 + });
150
151 expect(mockMount).toHaveBeenCalledTimes(1);
152 expect(mockUnmount).toHaveBeenCalledTimes(0);
153 });
154
143 - it('should replace children with different keys', () => {
155 + it('should replace children with different keys', async () => {
156 const container = document.createElement('div');
157 + const root = ReactDOMClient.createRoot(container);
158
159 const mockMount = jest.fn();
160 const mockUnmount = jest.fn();
@@ -157,29 +170,32 @@ describe('ReactMultiChild', () => {
170 expect(mockMount).toHaveBeenCalledTimes(0);
171 expect(mockUnmount).toHaveBeenCalledTimes(0);
172
160 - ReactDOM.render(
161 - <div>
162 - <MockComponent key="A" />
163 - </div>,
164 - container,
165 - );
173 + await act(async () => {
174 + root.render(
175 + <div>
176 + <MockComponent key="A" />
177 + </div>,
178 + );
179 + });
180
181 expect(mockMount).toHaveBeenCalledTimes(1);
182 expect(mockUnmount).toHaveBeenCalledTimes(0);
183
170 - ReactDOM.render(
171 - <div>
172 - <MockComponent key="B" />
173 - </div>,
174 - container,
175 - );
184 + await act(async () => {
185 + root.render(
186 + <div>
187 + <MockComponent key="B" />
188 + </div>,
189 + );
190 + });
191
192 expect(mockMount).toHaveBeenCalledTimes(2);
193 expect(mockUnmount).toHaveBeenCalledTimes(1);
194 });
195
181 - it('should warn for duplicated array keys with component stack info', () => {
196 + it('should warn for duplicated array keys with component stack info', async () => {
197 const container = document.createElement('div');
198 + const root = ReactDOMClient.createRoot(container);
199
200 class WrapperComponent extends React.Component {
201 render() {
@@ -196,14 +212,15 @@ describe('ReactMultiChild', () => {
212 );
213 }
214 }
199 -
200 - ReactDOM.render(<Parent>{[<div key="1" />]}</Parent>, container);
201 -
202 - expect(() =>
203 - ReactDOM.render(
204 - <Parent>{[<div key="1" />, <div key="1" />]}</Parent>,
205 - container,
206 - ),
215 + await act(async () => {
216 + root.render(<Parent>{[<div key="1" />]}</Parent>);
217 + });
218 +
219 + await expect(
220 + async () =>
221 + await act(async () => {
222 + root.render(<Parent>{[<div key="1" />, <div key="1" />]}</Parent>);
223 + }),
224 ).toErrorDev(
225 'Encountered two children with the same key, `1`. ' +
226 'Keys should be unique so that components maintain their identity ' +
@@ -217,8 +234,9 @@ describe('ReactMultiChild', () => {
234 );
235 });
236
220 - it('should warn for duplicated iterable keys with component stack info', () => {
237 + it('should warn for duplicated iterable keys with component stack info', async () => {
238 const container = document.createElement('div');
239 + const root = ReactDOMClient.createRoot(container);
240
241 class WrapperComponent extends React.Component {
242 render() {
@@ -253,17 +271,19 @@ describe('ReactMultiChild', () => {
271 },
272 };
273 }
256 -
257 - ReactDOM.render(
258 - <Parent>{createIterable([<div key="1" />])}</Parent>,
259 - container,
260 - );
261 -
262 - expect(() =>
263 - ReactDOM.render(
264 - <Parent>{createIterable([<div key="1" />, <div key="1" />])}</Parent>,
265 - container,
266 - ),
274 + await act(async () => {
275 + root.render(<Parent>{createIterable([<div key="1" />])}</Parent>);
276 + });
277 +
278 + await expect(
279 + async () =>
280 + await act(async () => {
281 + root.render(
282 + <Parent>
283 + {createIterable([<div key="1" />, <div key="1" />])}
284 + </Parent>,
285 + );
286 + }),
287 ).toErrorDev(
288 'Encountered two children with the same key, `1`. ' +
289 'Keys should be unique so that components maintain their identity ' +
@@ -278,7 +298,7 @@ describe('ReactMultiChild', () => {
298 });
299 });
300
281 - it('should warn for using maps as children with owner info', () => {
301 + it('should warn for using maps as children with owner info', async () => {
302 class Parent extends React.Component {
303 render() {
304 return (
@@ -294,7 +314,13 @@ describe('ReactMultiChild', () => {
314 }
315 }
316 const container = document.createElement('div');
297 - expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(
317 + const root = ReactDOMClient.createRoot(container);
318 + await expect(
319 + async () =>
320 + await act(async () => {
321 + root.render(<Parent />);
322 + }),
323 + ).toErrorDev(
324 'Using Maps as children is not supported. ' +
325 'Use an array of keyed ReactElements instead.\n' +
326 ' in div (at **)\n' +
@@ -302,15 +328,18 @@ describe('ReactMultiChild', () => {
328 );
329 });
330
305 - it('should warn for using generators as children', () => {
331 + it('should warn for using generators as children', async () => {
332 function* Foo() {
333 yield <h1 key="1">Hello</h1>;
334 yield <h1 key="2">World</h1>;
335 }
336
311 - const div = document.createElement('div');
312 - expect(() => {
313 - ReactDOM.render(<Foo />, div);
337 + const container = document.createElement('div');
338 + const root = ReactDOMClient.createRoot(container);
339 + await expect(async () => {
340 + await act(async () => {
341 + root.render(<Foo />);
342 + });
343 }).toErrorDev(
344 'Using Generators as children is unsupported and will likely yield ' +
345 'unexpected results because enumerating a generator mutates it. You may ' +
@@ -320,10 +349,12 @@ describe('ReactMultiChild', () => {
349 );
350
351 // Test de-duplication
323 - ReactDOM.render(<Foo />, div);
352 + await act(async () => {
353 + root.render(<Foo />);
354 + });
355 });
356
326 - it('should not warn for using generators in legacy iterables', () => {
357 + it('should not warn for using generators in legacy iterables', async () => {
358 const fooIterable = {
359 '@@iterator': function* () {
360 yield <h1 key="1">Hello</h1>;
@@ -335,15 +366,20 @@ describe('ReactMultiChild', () => {
366 return fooIterable;
367 }
368
338 - const div = document.createElement('div');
339 - ReactDOM.render(<Foo />, div);
340 - expect(div.textContent).toBe('HelloWorld');
369 + const container = document.createElement('div');
370 + const root = ReactDOMClient.createRoot(container);
371 + await act(async () => {
372 + root.render(<Foo />);
373 + });
374 + expect(container.textContent).toBe('HelloWorld');
375
342 - ReactDOM.render(<Foo />, div);
343 - expect(div.textContent).toBe('HelloWorld');
376 + await act(async () => {
377 + root.render(<Foo />);
378 + });
379 + expect(container.textContent).toBe('HelloWorld');
380 });
381
346 - it('should not warn for using generators in modern iterables', () => {
382 + it('should not warn for using generators in modern iterables', async () => {
383 const fooIterable = {
384 [Symbol.iterator]: function* () {
385 yield <h1 key="1">Hello</h1>;
@@ -356,14 +392,19 @@ describe('ReactMultiChild', () => {
392 }
393
394 const div = document.createElement('div');
359 - ReactDOM.render(<Foo />, div);
395 + const root = ReactDOMClient.createRoot(div);
396 + await act(async () => {
397 + root.render(<Foo />);
398 + });
399 expect(div.textContent).toBe('HelloWorld');
400
362 - ReactDOM.render(<Foo />, div);
401 + await act(async () => {
402 + root.render(<Foo />);
403 + });
404 expect(div.textContent).toBe('HelloWorld');
405 });
406
366 - it('should reorder bailed-out children', () => {
407 + it('should reorder bailed-out children', async () => {
408 class LetterInner extends React.Component {
409 render() {
410 return <div>{this.props.char}</div>;
@@ -393,15 +434,20 @@ describe('ReactMultiChild', () => {
434 }
435
436 const container = document.createElement('div');
437 + const root = ReactDOMClient.createRoot(container);
438
439 // Two random strings -- some additions, some removals, some moves
398 - ReactDOM.render(<Letters letters="XKwHomsNjIkBcQWFbiZU" />, container);
440 + await act(async () => {
441 + root.render(<Letters letters="XKwHomsNjIkBcQWFbiZU" />);
442 + });
443 expect(container.textContent).toBe('XKwHomsNjIkBcQWFbiZU');
400 - ReactDOM.render(<Letters letters="EHCjpdTUuiybDvhRJwZt" />, container);
444 + await act(async () => {
445 + root.render(<Letters letters="EHCjpdTUuiybDvhRJwZt" />);
446 + });
447 expect(container.textContent).toBe('EHCjpdTUuiybDvhRJwZt');
448 });
449
404 - it('prepares new children before unmounting old', () => {
450 + it('prepares new children before unmounting old', async () => {
451 const log = [];
452
453 class Spy extends React.Component {
@@ -426,20 +472,23 @@ describe('ReactMultiChild', () => {
472 const SpyB = props => <Spy {...props} />;
473
474 const container = document.createElement('div');
429 - ReactDOM.render(
430 - <div>
431 - <SpyA key="one" name="oneA" />
432 - <SpyA key="two" name="twoA" />
433 - </div>,
434 - container,
435 - );
436 - ReactDOM.render(
437 - <div>
438 - <SpyB key="one" name="oneB" />
439 - <SpyB key="two" name="twoB" />
440 - </div>,
441 - container,
442 - );
475 + const root = ReactDOMClient.createRoot(container);
476 + await act(async () => {
477 + root.render(
478 + <div>
479 + <SpyA key="one" name="oneA" />
480 + <SpyA key="two" name="twoA" />
481 + </div>,
482 + );
483 + });
484 + await act(async () => {
485 + root.render(
486 + <div>
487 + <SpyB key="one" name="oneB" />
488 + <SpyB key="two" name="twoB" />
489 + </div>,
490 + );
491 + });
492
493 expect(log).toEqual([
494 'oneA componentWillMount',