Skip to content

Commit cf925eb

Browse files
authored
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`
1 parent 38ef167 commit cf925eb

File tree

1 file changed

+89
-63
lines changed

1 file changed

+89
-63
lines changed

packages/react/src/__tests__/ReactElementValidator-test.internal.js

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
let PropTypes;
1616
let React;
17-
let ReactDOM;
18-
let ReactTestUtils;
17+
let ReactDOMClient;
18+
let act;
1919

2020
let ReactFeatureFlags = require('shared/ReactFeatureFlags');
2121

@@ -29,8 +29,8 @@ describe('ReactElementValidator', () => {
2929
ReactFeatureFlags = require('shared/ReactFeatureFlags');
3030
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
3131
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;
3434
ComponentClass = class extends React.Component {
3535
render() {
3636
return React.createElement('div');
@@ -47,7 +47,7 @@ describe('ReactElementValidator', () => {
4747
}).toErrorDev('Each child in a list should have a unique "key" prop.');
4848
});
4949

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 () => {
5151
class InnerClass extends React.Component {
5252
render() {
5353
return React.createElement(ComponentClass, null, this.props.childSet);
@@ -65,37 +65,41 @@ describe('ReactElementValidator', () => {
6565
}
6666
}
6767

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)));
7071
}).toErrorDev(
7172
'Each child in a list should have a unique "key" prop.' +
7273
'\n\nCheck the render method of `InnerClass`. ' +
7374
'It was passed a child from ComponentWrapper. ',
7475
);
7576
});
7677

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 () => {
7879
function Anonymous() {
7980
return <div />;
8081
}
8182
Object.defineProperty(Anonymous, 'name', {value: undefined});
8283

8384
const divs = [<div />, <div />];
8485

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>));
8789
}).toErrorDev(
8890
'Warning: Each child in a list should have a unique ' +
8991
'"key" prop. See https://reactjs.org/link/warning-keys for more information.\n' +
9092
' in div (at **)',
9193
);
9294
});
9395

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 () => {
9597
const divs = [<div />, <div />];
9698

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>));
99103
}).toErrorDev(
100104
'Warning: Each child in a list should have a unique ' +
101105
'"key" prop.\n\nCheck the top-level render call using <div>. See ' +
@@ -104,7 +108,7 @@ describe('ReactElementValidator', () => {
104108
);
105109
});
106110

107-
it('warns for keys with component stack info', () => {
111+
it('warns for keys with component stack info', async () => {
108112
function Component() {
109113
return <div>{[<div />, <div />]}</div>;
110114
}
@@ -117,7 +121,10 @@ describe('ReactElementValidator', () => {
117121
return <Parent child={<Component />} />;
118122
}
119123

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(
121128
'Warning: Each child in a list should have a unique ' +
122129
'"key" prop.\n\nCheck the render method of `Component`. See ' +
123130
'https://reactjs.org/link/warning-keys for more information.\n' +
@@ -128,7 +135,7 @@ describe('ReactElementValidator', () => {
128135
);
129136
});
130137

131-
it('does not warn for keys when passing children down', () => {
138+
it('does not warn for keys when passing children down', async () => {
132139
function Wrapper(props) {
133140
return (
134141
<div>
@@ -138,11 +145,14 @@ describe('ReactElementValidator', () => {
138145
);
139146
}
140147

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+
),
146156
);
147157
});
148158

@@ -208,7 +218,7 @@ describe('ReactElementValidator', () => {
208218
React.createElement(ComponentClass, null, [{}, {}]);
209219
});
210220

211-
it('should give context for PropType errors in nested components.', () => {
221+
it('should give context for PropType errors in nested components.', async () => {
212222
// In this test, we're making sure that if a proptype error is found in a
213223
// component, we give a small hint as to which parent instantiated that
214224
// component as per warnings about key usage in ReactElementValidator.
@@ -221,8 +231,9 @@ describe('ReactElementValidator', () => {
221231
function ParentComp() {
222232
return React.createElement(MyComp, {color: 123});
223233
}
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)));
226237
}).toErrorDev(
227238
'Warning: Failed prop type: ' +
228239
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
@@ -288,28 +299,33 @@ describe('ReactElementValidator', () => {
288299
React.createElement('div');
289300
});
290301

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 () => {
292303
function ParentComp() {
293304
return React.createElement(null);
294305
}
295306

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(
300312
'Element type is invalid: expected a string (for built-in components) ' +
301313
'or a class/function (for composite components) but got: null.' +
302314
(__DEV__ ? '\n\nCheck the render method of `ParentComp`.' : ''),
303315
);
304-
}).toErrorDev(
316+
}).toErrorDev([
305317
'Warning: React.createElement: type is invalid -- expected a string ' +
306318
'(for built-in components) or a class/function (for composite ' +
307319
'components) but got: null.' +
308320
'\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+
]);
310326
});
311327

312-
it('should check default prop values', () => {
328+
it('should check default prop values', async () => {
313329
class Component extends React.Component {
314330
static propTypes = {prop: PropTypes.string.isRequired};
315331
static defaultProps = {prop: null};
@@ -318,16 +334,17 @@ describe('ReactElementValidator', () => {
318334
}
319335
}
320336

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(
324341
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
325342
'`Component`, but its value is `null`.\n' +
326343
' in Component',
327344
);
328345
});
329346

330-
it('should not check the default for explicit null', () => {
347+
it('should not check the default for explicit null', async () => {
331348
class Component extends React.Component {
332349
static propTypes = {prop: PropTypes.string.isRequired};
333350
static defaultProps = {prop: 'text'};
@@ -336,9 +353,10 @@ describe('ReactElementValidator', () => {
336353
}
337354
}
338355

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})),
342360
);
343361
}).toErrorDev(
344362
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
@@ -347,7 +365,7 @@ describe('ReactElementValidator', () => {
347365
);
348366
});
349367

350-
it('should check declared prop types', () => {
368+
it('should check declared prop types', async () => {
351369
class Component extends React.Component {
352370
static propTypes = {
353371
prop: PropTypes.string.isRequired,
@@ -357,11 +375,10 @@ describe('ReactElementValidator', () => {
357375
}
358376
}
359377

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})));
365382
}).toErrorDev([
366383
'Warning: Failed prop type: ' +
367384
'The prop `prop` is marked as required in `Component`, but its value ' +
@@ -374,12 +391,12 @@ describe('ReactElementValidator', () => {
374391
]);
375392

376393
// 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'})),
379396
);
380397
});
381398

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 () => {
383400
class Component extends React.Component {
384401
static propTypes = {
385402
myProp: PropTypes.shape,
@@ -389,9 +406,10 @@ describe('ReactElementValidator', () => {
389406
}
390407
}
391408

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'}})),
395413
);
396414
}).toErrorDev(
397415
'Warning: Component: type specification of prop `myProp` is invalid; ' +
@@ -402,7 +420,7 @@ describe('ReactElementValidator', () => {
402420
);
403421
});
404422

405-
it('should warn if component declares PropTypes instead of propTypes', () => {
423+
it('should warn if component declares PropTypes instead of propTypes', async () => {
406424
class MisspelledPropTypesComponent extends React.Component {
407425
static PropTypes = {
408426
prop: PropTypes.string,
@@ -412,9 +430,12 @@ describe('ReactElementValidator', () => {
412430
}
413431
}
414432

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+
),
418439
);
419440
}).toErrorDev(
420441
'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +
@@ -423,15 +444,16 @@ describe('ReactElementValidator', () => {
423444
);
424445
});
425446

426-
it('warns for fragments with illegal attributes', () => {
447+
it('warns for fragments with illegal attributes', async () => {
427448
class Foo extends React.Component {
428449
render() {
429450
return React.createElement(React.Fragment, {a: 1}, '123');
430451
}
431452
}
432453

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)));
435457
}).toErrorDev(
436458
'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +
437459
'can only have `key` and `children` props.',
@@ -466,19 +488,23 @@ describe('ReactElementValidator', () => {
466488
});
467489
}
468490

469-
it('does not warn when using DOM node as children', () => {
491+
it('does not warn when using DOM node as children', async () => {
470492
class DOMContainer extends React.Component {
493+
ref;
471494
render() {
472-
return <div />;
495+
return <div ref={n => (this.ref = n)} />;
473496
}
474497
componentDidMount() {
475-
ReactDOM.findDOMNode(this).appendChild(this.props.children);
498+
this.ref.appendChild(this.props.children);
476499
}
477500
}
478501

479502
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+
});
482508
});
483509

484510
it('should not enumerate enumerable numbers (#4776)', () => {

0 commit comments

Comments
 (0)