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)', () => {