Deprecate TestUtils.SimulateNative (#13407)
Dan Abramov committed
Apr 2, 2020 at 23:48 UTC
e55855e7aee04b8e47edc319fc828b6cff43beed
3 files changed
+81
-11
packages/react-dom/src/__tests__/InvalidEventListeners-test.js
+50
-11
@@ -13,32 +13,71 @@ jest.mock('../events/isEventSupported');
13
14
describe('InvalidEventListeners', () => {
15
let React;
16
- let ReactTestUtils;
16
+ let ReactDOM;
17
+ let container;
18
19
beforeEach(() => {
20
jest.resetModules();
21
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;
31
});
32
33
it('should prevent non-function listeners, at dispatch', () => {
34
let node;
35
expect(() => {
27
- node = ReactTestUtils.renderIntoDocument(
28
- <div onClick="not a function" />,
29
- );
36
+ node = ReactDOM.render(<div onClick="not a function" />, container);
37
}).toErrorDev(
38
'Expected `onClick` listener to be a function, instead got a value of `string` type.',
39
);
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
+ }),
64
);
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
+ }
73
});
74
75
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
+ );
82
});
83
});
packages/react-dom/src/__tests__/ReactTestUtils-test.js
+16
@@ -35,6 +35,22 @@ describe('ReactTestUtils', () => {
35
expect(Object.keys(ReactTestUtils.SimulateNative).sort()).toMatchSnapshot();
36
});
37
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
+
54
it('gives Jest mocks a passthrough implementation with mockComponent()', () => {
55
class MockedComponent extends React.Component {
56
render() {
packages/react-dom/src/test-utils/ReactTestUtils.js
+15
@@ -47,6 +47,7 @@ const [
47
function Event(suffix) {}
48
49
let hasWarnedAboutDeprecatedMockComponent = false;
50
+let didWarnSimulateNativeDeprecated = false;
51
52
/**
53
* @class ReactTestUtils
@@ -622,6 +623,20 @@ buildSimulators();
623
624
function makeNativeSimulator(eventType, topLevelType) {
625
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
+
640
const fakeNativeEvent = new Event(eventType);
641
Object.assign(fakeNativeEvent, nativeEventData);
642
if (isDOMComponent(domComponentOrNode)) {