Skip to content

Commit 99bfbb3

Browse files
eps1lonAndyPengc12
authored andcommitted
Remove usage of ReactTestUtils from ReactFunctionComponent (facebook#28331)
1 parent deaa2a4 commit 99bfbb3

File tree

1 file changed

+139
-65
lines changed

1 file changed

+139
-65
lines changed

packages/react-dom/src/__tests__/ReactFunctionComponent-test.js

Lines changed: 139 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
let PropTypes;
1313
let React;
1414
let ReactDOMClient;
15-
let ReactTestUtils;
1615
let act;
1716

1817
function FunctionComponent(props) {
@@ -26,7 +25,6 @@ describe('ReactFunctionComponent', () => {
2625
React = require('react');
2726
ReactDOMClient = require('react-dom/client');
2827
act = require('internal-test-utils').act;
29-
ReactTestUtils = require('react-dom/test-utils');
3028
});
3129

3230
it('should render stateless component', async () => {
@@ -161,25 +159,33 @@ describe('ReactFunctionComponent', () => {
161159
);
162160
});
163161

164-
it('should not throw when stateless component returns undefined', () => {
162+
it('should not throw when stateless component returns undefined', async () => {
165163
function NotAComponent() {}
166-
expect(function () {
167-
ReactTestUtils.renderIntoDocument(
168-
<div>
169-
<NotAComponent />
170-
</div>,
171-
);
172-
}).not.toThrowError();
164+
const container = document.createElement('div');
165+
const root = ReactDOMClient.createRoot(container);
166+
await expect(
167+
act(() => {
168+
root.render(
169+
<div>
170+
<NotAComponent />
171+
</div>,
172+
);
173+
}),
174+
).resolves.not.toThrowError();
173175
});
174176

175-
it('should throw on string refs in pure functions', () => {
177+
it('should throw on string refs in pure functions', async () => {
176178
function Child() {
177179
return <div ref="me" />;
178180
}
179181

180-
expect(function () {
181-
ReactTestUtils.renderIntoDocument(<Child test="test" />);
182-
}).toThrowError(
182+
const container = document.createElement('div');
183+
const root = ReactDOMClient.createRoot(container);
184+
await expect(
185+
act(() => {
186+
root.render(<Child test="test" />);
187+
}),
188+
).rejects.toThrowError(
183189
__DEV__
184190
? 'Function components cannot have string refs. We recommend using useRef() instead.'
185191
: // It happens because we don't save _owner in production for
@@ -193,7 +199,7 @@ describe('ReactFunctionComponent', () => {
193199
);
194200
});
195201

196-
it('should warn when given a string ref', () => {
202+
it('should warn when given a string ref', async () => {
197203
function Indirection(props) {
198204
return <div>{props.children}</div>;
199205
}
@@ -208,9 +214,13 @@ describe('ReactFunctionComponent', () => {
208214
}
209215
}
210216

211-
expect(() =>
212-
ReactTestUtils.renderIntoDocument(<ParentUsingStringRef />),
213-
).toErrorDev(
217+
await expect(async () => {
218+
const container = document.createElement('div');
219+
const root = ReactDOMClient.createRoot(container);
220+
await act(() => {
221+
root.render(<ParentUsingStringRef />);
222+
});
223+
}).toErrorDev(
214224
'Warning: Function components cannot be given refs. ' +
215225
'Attempts to access this ref will fail. ' +
216226
'Did you mean to use React.forwardRef()?\n\n' +
@@ -223,32 +233,36 @@ describe('ReactFunctionComponent', () => {
223233
);
224234

225235
// No additional warnings should be logged
226-
ReactTestUtils.renderIntoDocument(<ParentUsingStringRef />);
236+
const container = document.createElement('div');
237+
const root = ReactDOMClient.createRoot(container);
238+
await act(() => {
239+
root.render(<ParentUsingStringRef />);
240+
});
227241
});
228242

229-
it('should warn when given a function ref', () => {
243+
it('should warn when given a function ref and ignore them', async () => {
230244
function Indirection(props) {
231245
return <div>{props.children}</div>;
232246
}
233247

248+
const ref = jest.fn();
234249
class ParentUsingFunctionRef extends React.Component {
235250
render() {
236251
return (
237252
<Indirection>
238-
<FunctionComponent
239-
name="A"
240-
ref={arg => {
241-
expect(arg).toBe(null);
242-
}}
243-
/>
253+
<FunctionComponent name="A" ref={ref} />
244254
</Indirection>
245255
);
246256
}
247257
}
248258

249-
expect(() =>
250-
ReactTestUtils.renderIntoDocument(<ParentUsingFunctionRef />),
251-
).toErrorDev(
259+
await expect(async () => {
260+
const container = document.createElement('div');
261+
const root = ReactDOMClient.createRoot(container);
262+
await act(() => {
263+
root.render(<ParentUsingFunctionRef />);
264+
});
265+
}).toErrorDev(
252266
'Warning: Function components cannot be given refs. ' +
253267
'Attempts to access this ref will fail. ' +
254268
'Did you mean to use React.forwardRef()?\n\n' +
@@ -259,12 +273,17 @@ describe('ReactFunctionComponent', () => {
259273
' in Indirection (at **)\n' +
260274
' in ParentUsingFunctionRef (at **)',
261275
);
276+
expect(ref).not.toHaveBeenCalled();
262277

263278
// No additional warnings should be logged
264-
ReactTestUtils.renderIntoDocument(<ParentUsingFunctionRef />);
279+
const container = document.createElement('div');
280+
const root = ReactDOMClient.createRoot(container);
281+
await act(() => {
282+
root.render(<ParentUsingFunctionRef />);
283+
});
265284
});
266285

267-
it('deduplicates ref warnings based on element or owner', () => {
286+
it('deduplicates ref warnings based on element or owner', async () => {
268287
// When owner uses JSX, we can use exact line location to dedupe warnings
269288
class AnonymousParentUsingJSX extends React.Component {
270289
render() {
@@ -274,15 +293,24 @@ describe('ReactFunctionComponent', () => {
274293

275294
let instance1;
276295

277-
expect(() => {
278-
instance1 = ReactTestUtils.renderIntoDocument(
279-
<AnonymousParentUsingJSX />,
280-
);
296+
await expect(async () => {
297+
const container = document.createElement('div');
298+
const root = ReactDOMClient.createRoot(container);
299+
300+
await act(() => {
301+
root.render(
302+
<AnonymousParentUsingJSX ref={current => (instance1 = current)} />,
303+
);
304+
});
281305
}).toErrorDev('Warning: Function components cannot be given refs.');
282306
// Should be deduped (offending element is on the same line):
283307
instance1.forceUpdate();
284308
// Should also be deduped (offending element is on the same line):
285-
ReactTestUtils.renderIntoDocument(<AnonymousParentUsingJSX />);
309+
let container = document.createElement('div');
310+
let root = ReactDOMClient.createRoot(container);
311+
await act(() => {
312+
root.render(<AnonymousParentUsingJSX />);
313+
});
286314

287315
// When owner doesn't use JSX, and is anonymous, we warn once per internal instance.
288316
class AnonymousParentNotUsingJSX extends React.Component {
@@ -295,15 +323,23 @@ describe('ReactFunctionComponent', () => {
295323
}
296324

297325
let instance2;
298-
expect(() => {
299-
instance2 = ReactTestUtils.renderIntoDocument(
300-
<AnonymousParentNotUsingJSX />,
301-
);
326+
await expect(async () => {
327+
container = document.createElement('div');
328+
root = ReactDOMClient.createRoot(container);
329+
await act(() => {
330+
root.render(
331+
<AnonymousParentNotUsingJSX ref={current => (instance2 = current)} />,
332+
);
333+
});
302334
}).toErrorDev('Warning: Function components cannot be given refs.');
303335
// Should be deduped (same internal instance, no additional warnings)
304336
instance2.forceUpdate();
305337
// Could not be differentiated (since owner is anonymous and no source location)
306-
ReactTestUtils.renderIntoDocument(<AnonymousParentNotUsingJSX />);
338+
container = document.createElement('div');
339+
root = ReactDOMClient.createRoot(container);
340+
await act(() => {
341+
root.render(<AnonymousParentNotUsingJSX />);
342+
});
307343

308344
// When owner doesn't use JSX, but is named, we warn once per owner name
309345
class NamedParentNotUsingJSX extends React.Component {
@@ -315,19 +351,29 @@ describe('ReactFunctionComponent', () => {
315351
}
316352
}
317353
let instance3;
318-
expect(() => {
319-
instance3 = ReactTestUtils.renderIntoDocument(<NamedParentNotUsingJSX />);
354+
await expect(async () => {
355+
container = document.createElement('div');
356+
root = ReactDOMClient.createRoot(container);
357+
await act(() => {
358+
root.render(
359+
<NamedParentNotUsingJSX ref={current => (instance3 = current)} />,
360+
);
361+
});
320362
}).toErrorDev('Warning: Function components cannot be given refs.');
321363
// Should be deduped (same owner name, no additional warnings):
322364
instance3.forceUpdate();
323365
// Should also be deduped (same owner name, no additional warnings):
324-
ReactTestUtils.renderIntoDocument(<NamedParentNotUsingJSX />);
366+
container = document.createElement('div');
367+
root = ReactDOMClient.createRoot(container);
368+
await act(() => {
369+
root.render(<NamedParentNotUsingJSX />);
370+
});
325371
});
326372

327373
// This guards against a regression caused by clearing the current debug fiber.
328374
// https://github.com/facebook/react/issues/10831
329375
// @gate !disableLegacyContext || !__DEV__
330-
it('should warn when giving a function ref with context', () => {
376+
it('should warn when giving a function ref with context', async () => {
331377
function Child() {
332378
return null;
333379
}
@@ -349,7 +395,13 @@ describe('ReactFunctionComponent', () => {
349395
}
350396
}
351397

352-
expect(() => ReactTestUtils.renderIntoDocument(<Parent />)).toErrorDev(
398+
await expect(async () => {
399+
const container = document.createElement('div');
400+
const root = ReactDOMClient.createRoot(container);
401+
await act(() => {
402+
root.render(<Parent />);
403+
});
404+
}).toErrorDev(
353405
'Warning: Function components cannot be given refs. ' +
354406
'Attempts to access this ref will fail. ' +
355407
'Did you mean to use React.forwardRef()?\n\n' +
@@ -360,36 +412,40 @@ describe('ReactFunctionComponent', () => {
360412
);
361413
});
362414

363-
it('should provide a null ref', () => {
364-
function Child() {
365-
return <div />;
366-
}
367-
368-
const comp = ReactTestUtils.renderIntoDocument(<Child />);
369-
expect(comp).toBe(null);
370-
});
371-
372-
it('should use correct name in key warning', () => {
415+
it('should use correct name in key warning', async () => {
373416
function Child() {
374417
return <div>{[<span />]}</div>;
375418
}
376419

377-
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).toErrorDev(
420+
await expect(async () => {
421+
const container = document.createElement('div');
422+
const root = ReactDOMClient.createRoot(container);
423+
await act(() => {
424+
root.render(<Child />);
425+
});
426+
}).toErrorDev(
378427
'Each child in a list should have a unique "key" prop.\n\n' +
379428
'Check the render method of `Child`.',
380429
);
381430
});
382431

383432
// TODO: change this test after we deprecate default props support
384433
// for function components
385-
it('should support default props and prop types', () => {
434+
it('should support default props and prop types', async () => {
386435
function Child(props) {
387436
return <div>{props.test}</div>;
388437
}
389438
Child.defaultProps = {test: 2};
390439
Child.propTypes = {test: PropTypes.string};
391440

392-
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).toErrorDev([
441+
await expect(async () => {
442+
const container = document.createElement('div');
443+
const root = ReactDOMClient.createRoot(container);
444+
445+
await act(() => {
446+
root.render(<Child />);
447+
});
448+
}).toErrorDev([
393449
'Warning: Child: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
394450
'Warning: Failed prop type: Invalid prop `test` of type `number` ' +
395451
'supplied to `Child`, expected `string`.\n' +
@@ -427,28 +483,46 @@ describe('ReactFunctionComponent', () => {
427483
expect(el.textContent).toBe('en');
428484
});
429485

430-
it('should work with arrow functions', () => {
486+
it('should work with arrow functions', async () => {
431487
let Child = function () {
432488
return <div />;
433489
};
434490
// Will create a new bound function without a prototype, much like a native
435491
// arrow function.
436492
Child = Child.bind(this);
437493

438-
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).not.toThrow();
494+
await expect(async () => {
495+
const container = document.createElement('div');
496+
const root = ReactDOMClient.createRoot(container);
497+
await act(() => {
498+
root.render(<Child />);
499+
});
500+
}).not.toThrow();
439501
});
440502

441-
it('should allow simple functions to return null', () => {
503+
it('should allow simple functions to return null', async () => {
442504
const Child = function () {
443505
return null;
444506
};
445-
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).not.toThrow();
507+
await expect(async () => {
508+
const container = document.createElement('div');
509+
const root = ReactDOMClient.createRoot(container);
510+
await act(() => {
511+
root.render(<Child />);
512+
});
513+
}).not.toThrow();
446514
});
447515

448-
it('should allow simple functions to return false', () => {
516+
it('should allow simple functions to return false', async () => {
449517
function Child() {
450518
return false;
451519
}
452-
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).not.toThrow();
520+
const container = document.createElement('div');
521+
const root = ReactDOMClient.createRoot(container);
522+
await expect(
523+
act(() => {
524+
root.render(<Child />);
525+
}),
526+
).resolves.not.toThrow();
453527
});
454528
});

0 commit comments

Comments
 (0)