Skip to content

Commit e55855e

Browse files
authored
Deprecate TestUtils.SimulateNative (#13407)
1 parent 4123d72 commit e55855e

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

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

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,71 @@ jest.mock('../events/isEventSupported');
1313

1414
describe('InvalidEventListeners', () => {
1515
let React;
16-
let ReactTestUtils;
16+
let ReactDOM;
17+
let container;
1718

1819
beforeEach(() => {
1920
jest.resetModules();
2021
React = require('react');
21-
ReactTestUtils = require('react-dom/test-utils');
22+
ReactDOM = require('react-dom');
23+
24+
container = document.createElement('div');
25+
document.body.appendChild(container);
26+
});
27+
28+
afterEach(() => {
29+
document.body.removeChild(container);
30+
container = null;
2231
});
2332

2433
it('should prevent non-function listeners, at dispatch', () => {
2534
let node;
2635
expect(() => {
27-
node = ReactTestUtils.renderIntoDocument(
28-
<div onClick="not a function" />,
29-
);
36+
node = ReactDOM.render(<div onClick="not a function" />, container);
3037
}).toErrorDev(
3138
'Expected `onClick` listener to be a function, instead got a value of `string` type.',
3239
);
33-
expect(() => ReactTestUtils.SimulateNative.click(node)).toThrowError(
34-
'Expected `onClick` listener to be a function, instead got a value of `string` type.',
40+
41+
spyOnProd(console, 'error');
42+
43+
const uncaughtErrors = [];
44+
function handleWindowError(e) {
45+
uncaughtErrors.push(e.error);
46+
}
47+
window.addEventListener('error', handleWindowError);
48+
try {
49+
node.dispatchEvent(
50+
new MouseEvent('click', {
51+
bubbles: true,
52+
}),
53+
);
54+
} finally {
55+
window.removeEventListener('error', handleWindowError);
56+
}
57+
expect(uncaughtErrors.length).toBe(1);
58+
expect(uncaughtErrors[0]).toEqual(
59+
expect.objectContaining({
60+
message:
61+
'Expected `onClick` listener to be a function, ' +
62+
'instead got a value of `string` type.',
63+
}),
3564
);
65+
66+
if (!__DEV__) {
67+
expect(console.error).toHaveBeenCalledTimes(1);
68+
expect(console.error.calls.argsFor(0)[0]).toMatch(
69+
'Expected `onClick` listener to be a function, ' +
70+
'instead got a value of `string` type.',
71+
);
72+
}
3673
});
3774

3875
it('should not prevent null listeners, at dispatch', () => {
39-
const node = ReactTestUtils.renderIntoDocument(<div onClick={null} />);
40-
expect(function() {
41-
ReactTestUtils.SimulateNative.click(node);
42-
}).not.toThrow();
76+
const node = ReactDOM.render(<div onClick={null} />, container);
77+
node.dispatchEvent(
78+
new MouseEvent('click', {
79+
bubbles: true,
80+
}),
81+
);
4382
});
4483
});

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ describe('ReactTestUtils', () => {
3535
expect(Object.keys(ReactTestUtils.SimulateNative).sort()).toMatchSnapshot();
3636
});
3737

38+
it('SimulateNative should warn about deprecation', () => {
39+
const container = document.createElement('div');
40+
const node = ReactDOM.render(<div />, container);
41+
expect(() =>
42+
ReactTestUtils.SimulateNative.click(node),
43+
).toWarnDev(
44+
'ReactTestUtils.SimulateNative is an undocumented API that does not match ' +
45+
'how the browser dispatches events, and will be removed in a future major ' +
46+
'version of React. If you rely on it for testing, consider attaching the root ' +
47+
'DOM container to the document during the test, and then dispatching native browser ' +
48+
'events by calling `node.dispatchEvent()` on the DOM nodes. Make sure to set ' +
49+
'the `bubbles` flag to `true` when creating the native browser event.',
50+
{withoutStack: true},
51+
);
52+
});
53+
3854
it('gives Jest mocks a passthrough implementation with mockComponent()', () => {
3955
class MockedComponent extends React.Component {
4056
render() {

packages/react-dom/src/test-utils/ReactTestUtils.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const [
4747
function Event(suffix) {}
4848

4949
let hasWarnedAboutDeprecatedMockComponent = false;
50+
let didWarnSimulateNativeDeprecated = false;
5051

5152
/**
5253
* @class ReactTestUtils
@@ -622,6 +623,20 @@ buildSimulators();
622623

623624
function makeNativeSimulator(eventType, topLevelType) {
624625
return function(domComponentOrNode, nativeEventData) {
626+
if (__DEV__) {
627+
if (!didWarnSimulateNativeDeprecated) {
628+
didWarnSimulateNativeDeprecated = true;
629+
console.warn(
630+
'ReactTestUtils.SimulateNative is an undocumented API that does not match ' +
631+
'how the browser dispatches events, and will be removed in a future major ' +
632+
'version of React. If you rely on it for testing, consider attaching the root ' +
633+
'DOM container to the document during the test, and then dispatching native browser ' +
634+
'events by calling `node.dispatchEvent()` on the DOM nodes. Make sure to set ' +
635+
'the `bubbles` flag to `true` when creating the native browser event.',
636+
);
637+
}
638+
}
639+
625640
const fakeNativeEvent = new Event(eventType);
626641
Object.assign(fakeNativeEvent, nativeEventData);
627642
if (isDOMComponent(domComponentOrNode)) {

0 commit comments

Comments
 (0)