@samitouri / QOS-React-1 / commits / cf925ebc3c

convert ReactElementValidator-test to createRoot (#28223)

## Summary Converts `ReactTestUtils.renderIntoDocument` and `ReactDOM.findDOMNode` to `ReactDOMClient.createRoot` ## How did you test this change? `yarn test ReactElementValidator`

Noah Lemen committed Feb 2, 2024 at 15:19 UTC cf925ebc3c25e295658c17d4513dfa046e5074e9
1 file changed +89 -63
packages/react/src/__tests__/ReactElementValidator-test.internal.js
+89 -63
@@ -14,8 +14,8 @@
14
15 let PropTypes;
16 let React;
17 -let ReactDOM;
18 -let ReactTestUtils;
17 +let ReactDOMClient;
18 +let act;
19
20 let ReactFeatureFlags = require('shared/ReactFeatureFlags');
21
@@ -29,8 +29,8 @@ describe('ReactElementValidator', () => {
29 ReactFeatureFlags = require('shared/ReactFeatureFlags');
30 ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
31 React = require('react');
32 - ReactDOM = require('react-dom');
33 - ReactTestUtils = require('react-dom/test-utils');
32 + ReactDOMClient = require('react-dom/client');
33 + act = require('internal-test-utils').act;
34 ComponentClass = class extends React.Component {
35 render() {
36 return React.createElement('div');
@@ -47,7 +47,7 @@ describe('ReactElementValidator', () => {
47 }).toErrorDev('Each child in a list should have a unique "key" prop.');
48 });
49
50 - it('warns for keys for arrays of elements with owner info', () => {
50 + it('warns for keys for arrays of elements with owner info', async () => {
51 class InnerClass extends React.Component {
52 render() {
53 return React.createElement(ComponentClass, null, this.props.childSet);
@@ -65,8 +65,9 @@ describe('ReactElementValidator', () => {
65 }
66 }
67
68 - expect(() => {
69 - ReactTestUtils.renderIntoDocument(React.createElement(ComponentWrapper));
68 + await expect(async () => {
69 + const root = ReactDOMClient.createRoot(document.createElement('div'));
70 + await act(() => root.render(React.createElement(ComponentWrapper)));
71 }).toErrorDev(
72 'Each child in a list should have a unique "key" prop.' +
73 '\n\nCheck the render method of `InnerClass`. ' +
@@ -74,7 +75,7 @@ describe('ReactElementValidator', () => {
75 );
76 });
77
77 - it('warns for keys for arrays with no owner or parent info', () => {
78 + it('warns for keys for arrays with no owner or parent info', async () => {
79 function Anonymous() {
80 return <div />;
81 }
@@ -82,8 +83,9 @@ describe('ReactElementValidator', () => {
83
84 const divs = [<div />, <div />];
85
85 - expect(() => {
86 - ReactTestUtils.renderIntoDocument(<Anonymous>{divs}</Anonymous>);
86 + await expect(async () => {
87 + const root = ReactDOMClient.createRoot(document.createElement('div'));
88 + await act(() => root.render(<Anonymous>{divs}</Anonymous>));
89 }).toErrorDev(
90 'Warning: Each child in a list should have a unique ' +
91 '"key" prop. See https://reactjs.org/link/warning-keys for more information.\n' +
@@ -91,11 +93,13 @@ describe('ReactElementValidator', () => {
93 );
94 });
95
94 - it('warns for keys for arrays of elements with no owner info', () => {
96 + it('warns for keys for arrays of elements with no owner info', async () => {
97 const divs = [<div />, <div />];
98
97 - expect(() => {
98 - ReactTestUtils.renderIntoDocument(<div>{divs}</div>);
99 + await expect(async () => {
100 + const root = ReactDOMClient.createRoot(document.createElement('div'));
101 +
102 + await act(() => root.render(<div>{divs}</div>));
103 }).toErrorDev(
104 'Warning: Each child in a list should have a unique ' +
105 '"key" prop.\n\nCheck the top-level render call using <div>. See ' +
@@ -104,7 +108,7 @@ describe('ReactElementValidator', () => {
108 );
109 });
110
107 - it('warns for keys with component stack info', () => {
111 + it('warns for keys with component stack info', async () => {
112 function Component() {
113 return <div>{[<div />, <div />]}</div>;
114 }
@@ -117,7 +121,10 @@ describe('ReactElementValidator', () => {
121 return <Parent child={<Component />} />;
122 }
123
120 - expect(() => ReactTestUtils.renderIntoDocument(<GrandParent />)).toErrorDev(
124 + await expect(async () => {
125 + const root = ReactDOMClient.createRoot(document.createElement('div'));
126 + await act(() => root.render(<GrandParent />));
127 + }).toErrorDev(
128 'Warning: Each child in a list should have a unique ' +
129 '"key" prop.\n\nCheck the render method of `Component`. See ' +
130 'https://reactjs.org/link/warning-keys for more information.\n' +
@@ -128,7 +135,7 @@ describe('ReactElementValidator', () => {
135 );
136 });
137
131 - it('does not warn for keys when passing children down', () => {
138 + it('does not warn for keys when passing children down', async () => {
139 function Wrapper(props) {
140 return (
141 <div>
@@ -138,11 +145,14 @@ describe('ReactElementValidator', () => {
145 );
146 }
147
141 - ReactTestUtils.renderIntoDocument(
142 - <Wrapper>
143 - <span />
144 - <span />
145 - </Wrapper>,
148 + const root = ReactDOMClient.createRoot(document.createElement('div'));
149 + await act(() =>
150 + root.render(
151 + <Wrapper>
152 + <span />
153 + <span />
154 + </Wrapper>,
155 + ),
156 );
157 });
158
@@ -208,7 +218,7 @@ describe('ReactElementValidator', () => {
218 React.createElement(ComponentClass, null, [{}, {}]);
219 });
220
211 - it('should give context for PropType errors in nested components.', () => {
221 + it('should give context for PropType errors in nested components.', async () => {
222 // In this test, we're making sure that if a proptype error is found in a
223 // component, we give a small hint as to which parent instantiated that
224 // component as per warnings about key usage in ReactElementValidator.
@@ -221,8 +231,9 @@ describe('ReactElementValidator', () => {
231 function ParentComp() {
232 return React.createElement(MyComp, {color: 123});
233 }
224 - expect(() => {
225 - ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
234 + await expect(async () => {
235 + const root = ReactDOMClient.createRoot(document.createElement('div'));
236 + await act(() => root.render(React.createElement(ParentComp)));
237 }).toErrorDev(
238 'Warning: Failed prop type: ' +
239 'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
@@ -288,28 +299,33 @@ describe('ReactElementValidator', () => {
299 React.createElement('div');
300 });
301
291 - it('includes the owner name when passing null, undefined, boolean, or number', () => {
302 + it('includes the owner name when passing null, undefined, boolean, or number', async () => {
303 function ParentComp() {
304 return React.createElement(null);
305 }
306
296 - expect(() => {
297 - expect(() => {
298 - ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
299 - }).toThrowError(
307 + await expect(async () => {
308 + await expect(async () => {
309 + const root = ReactDOMClient.createRoot(document.createElement('div'));
310 + await act(() => root.render(React.createElement(ParentComp)));
311 + }).rejects.toThrowError(
312 'Element type is invalid: expected a string (for built-in components) ' +
313 'or a class/function (for composite components) but got: null.' +
314 (__DEV__ ? '\n\nCheck the render method of `ParentComp`.' : ''),
315 );
304 - }).toErrorDev(
316 + }).toErrorDev([
317 'Warning: React.createElement: type is invalid -- expected a string ' +
318 '(for built-in components) or a class/function (for composite ' +
319 'components) but got: null.' +
320 '\n\nCheck the render method of `ParentComp`.\n in ParentComp',
309 - );
321 + 'Warning: React.createElement: type is invalid -- expected a string ' +
322 + '(for built-in components) or a class/function (for composite ' +
323 + 'components) but got: null.' +
324 + '\n\nCheck the render method of `ParentComp`.\n in ParentComp',
325 + ]);
326 });
327
312 - it('should check default prop values', () => {
328 + it('should check default prop values', async () => {
329 class Component extends React.Component {
330 static propTypes = {prop: PropTypes.string.isRequired};
331 static defaultProps = {prop: null};
@@ -318,16 +334,17 @@ describe('ReactElementValidator', () => {
334 }
335 }
336
321 - expect(() =>
322 - ReactTestUtils.renderIntoDocument(React.createElement(Component)),
323 - ).toErrorDev(
337 + await expect(async () => {
338 + const root = ReactDOMClient.createRoot(document.createElement('div'));
339 + await act(() => root.render(React.createElement(Component)));
340 + }).toErrorDev(
341 'Warning: Failed prop type: The prop `prop` is marked as required in ' +
342 '`Component`, but its value is `null`.\n' +
343 ' in Component',
344 );
345 });
346
330 - it('should not check the default for explicit null', () => {
347 + it('should not check the default for explicit null', async () => {
348 class Component extends React.Component {
349 static propTypes = {prop: PropTypes.string.isRequired};
350 static defaultProps = {prop: 'text'};
@@ -336,9 +353,10 @@ describe('ReactElementValidator', () => {
353 }
354 }
355
339 - expect(() => {
340 - ReactTestUtils.renderIntoDocument(
341 - React.createElement(Component, {prop: null}),
356 + await expect(async () => {
357 + const root = ReactDOMClient.createRoot(document.createElement('div'));
358 + await act(() =>
359 + root.render(React.createElement(Component, {prop: null})),
360 );
361 }).toErrorDev(
362 'Warning: Failed prop type: The prop `prop` is marked as required in ' +
@@ -347,7 +365,7 @@ describe('ReactElementValidator', () => {
365 );
366 });
367
350 - it('should check declared prop types', () => {
368 + it('should check declared prop types', async () => {
369 class Component extends React.Component {
370 static propTypes = {
371 prop: PropTypes.string.isRequired,
@@ -357,11 +375,10 @@ describe('ReactElementValidator', () => {
375 }
376 }
377
360 - expect(() => {
361 - ReactTestUtils.renderIntoDocument(React.createElement(Component));
362 - ReactTestUtils.renderIntoDocument(
363 - React.createElement(Component, {prop: 42}),
364 - );
378 + const root = ReactDOMClient.createRoot(document.createElement('div'));
379 + await expect(async () => {
380 + await act(() => root.render(React.createElement(Component)));
381 + await act(() => root.render(React.createElement(Component, {prop: 42})));
382 }).toErrorDev([
383 'Warning: Failed prop type: ' +
384 'The prop `prop` is marked as required in `Component`, but its value ' +
@@ -374,12 +391,12 @@ describe('ReactElementValidator', () => {
391 ]);
392
393 // Should not error for strings
377 - ReactTestUtils.renderIntoDocument(
378 - React.createElement(Component, {prop: 'string'}),
394 + await act(() =>
395 + root.render(React.createElement(Component, {prop: 'string'})),
396 );
397 });
398
382 - it('should warn if a PropType creator is used as a PropType', () => {
399 + it('should warn if a PropType creator is used as a PropType', async () => {
400 class Component extends React.Component {
401 static propTypes = {
402 myProp: PropTypes.shape,
@@ -389,9 +406,10 @@ describe('ReactElementValidator', () => {
406 }
407 }
408
392 - expect(() => {
393 - ReactTestUtils.renderIntoDocument(
394 - React.createElement(Component, {myProp: {value: 'hi'}}),
409 + await expect(async () => {
410 + const root = ReactDOMClient.createRoot(document.createElement('div'));
411 + await act(() =>
412 + root.render(React.createElement(Component, {myProp: {value: 'hi'}})),
413 );
414 }).toErrorDev(
415 'Warning: Component: type specification of prop `myProp` is invalid; ' +
@@ -402,7 +420,7 @@ describe('ReactElementValidator', () => {
420 );
421 });
422
405 - it('should warn if component declares PropTypes instead of propTypes', () => {
423 + it('should warn if component declares PropTypes instead of propTypes', async () => {
424 class MisspelledPropTypesComponent extends React.Component {
425 static PropTypes = {
426 prop: PropTypes.string,
@@ -412,9 +430,12 @@ describe('ReactElementValidator', () => {
430 }
431 }
432
415 - expect(() => {
416 - ReactTestUtils.renderIntoDocument(
417 - React.createElement(MisspelledPropTypesComponent, {prop: 'Hi'}),
433 + await expect(async () => {
434 + const root = ReactDOMClient.createRoot(document.createElement('div'));
435 + await act(() =>
436 + root.render(
437 + React.createElement(MisspelledPropTypesComponent, {prop: 'Hi'}),
438 + ),
439 );
440 }).toErrorDev(
441 'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +
@@ -423,15 +444,16 @@ describe('ReactElementValidator', () => {
444 );
445 });
446
426 - it('warns for fragments with illegal attributes', () => {
447 + it('warns for fragments with illegal attributes', async () => {
448 class Foo extends React.Component {
449 render() {
450 return React.createElement(React.Fragment, {a: 1}, '123');
451 }
452 }
453
433 - expect(() => {
434 - ReactTestUtils.renderIntoDocument(React.createElement(Foo));
454 + await expect(async () => {
455 + const root = ReactDOMClient.createRoot(document.createElement('div'));
456 + await act(() => root.render(React.createElement(Foo)));
457 }).toErrorDev(
458 'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +
459 'can only have `key` and `children` props.',
@@ -466,19 +488,23 @@ describe('ReactElementValidator', () => {
488 });
489 }
490
469 - it('does not warn when using DOM node as children', () => {
491 + it('does not warn when using DOM node as children', async () => {
492 class DOMContainer extends React.Component {
493 + ref;
494 render() {
472 - return <div />;
495 + return <div ref={n => (this.ref = n)} />;
496 }
497 componentDidMount() {
475 - ReactDOM.findDOMNode(this).appendChild(this.props.children);
498 + this.ref.appendChild(this.props.children);
499 }
500 }
501
502 const node = document.createElement('div');
480 - // This shouldn't cause a stack overflow or any other problems (#3883)
481 - ReactTestUtils.renderIntoDocument(<DOMContainer>{node}</DOMContainer>);
503 + const root = ReactDOMClient.createRoot(document.createElement('div'));
504 + await act(() => {
505 + // This shouldn't cause a stack overflow or any other problems (#3883)
506 + root.render(<DOMContainer>{node}</DOMContainer>);
507 + });
508 });
509
510 it('should not enumerate enumerable numbers (#4776)', () => {