ReactDOM: Remove every test-util except `act()` (#28541)
Sebastian Silbermann committed
Mar 27, 2024 at 16:04 UTC
ec4d26ceb8bbb622188c858b6b3d1a5f1e86f2f7
9 files changed
+164
-5
packages/react-dom/src/__tests__/ReactTestUtils-test.js
+35
-5
@@ -31,6 +31,7 @@ describe('ReactTestUtils', () => {
31
expect(Object.keys(ReactTestUtils.Simulate).sort()).toMatchSnapshot();
32
});
33
34
+ // @gate !disableDOMTestUtils
35
it('gives Jest mocks a passthrough implementation with mockComponent()', async () => {
36
class MockedComponent extends React.Component {
37
render() {
@@ -60,6 +61,7 @@ describe('ReactTestUtils', () => {
61
expect(container.textContent).toBe('Hello');
62
});
63
64
+ // @gate !disableDOMTestUtils
65
it('can scryRenderedComponentsWithType', async () => {
66
class Child extends React.Component {
67
render() {
@@ -88,6 +90,7 @@ describe('ReactTestUtils', () => {
90
expect(scryResults.length).toBe(1);
91
});
92
93
+ // @gate !disableDOMTestUtils
94
it('can scryRenderedDOMComponentsWithClass with TextComponent', async () => {
95
class Wrapper extends React.Component {
96
render() {
@@ -112,6 +115,7 @@ describe('ReactTestUtils', () => {
115
expect(scryResults.length).toBe(0);
116
});
117
118
+ // @gate !disableDOMTestUtils
119
it('can scryRenderedDOMComponentsWithClass with className contains \\n', async () => {
120
class Wrapper extends React.Component {
121
render() {
@@ -136,6 +140,7 @@ describe('ReactTestUtils', () => {
140
expect(scryResults.length).toBe(1);
141
});
142
143
+ // @gate !disableDOMTestUtils
144
it('can scryRenderedDOMComponentsWithClass with multiple classes', async () => {
145
class Wrapper extends React.Component {
146
render() {
@@ -187,6 +192,7 @@ describe('ReactTestUtils', () => {
192
expect(scryResults5.length).toBe(0);
193
});
194
195
+ // @gate !disableDOMTestUtils
196
it('traverses children in the correct order', async () => {
197
class Wrapper extends React.Component {
198
render() {
@@ -225,6 +231,7 @@ describe('ReactTestUtils', () => {
231
expect(log).toEqual(['orangepurple', 'orange', 'purple']);
232
});
233
234
+ // @gate !disableDOMTestUtils
235
it('should support injected wrapper components as DOM components', async () => {
236
const injectedDOMComponents = [
237
'button',
@@ -291,6 +298,7 @@ describe('ReactTestUtils', () => {
298
expect(ReactTestUtils.isDOMComponent(component.bodyRef.current)).toBe(true);
299
});
300
301
+ // @gate !disableDOMTestUtils
302
it('can scry with stateless components involved', async () => {
303
const Function = () => (
304
<div>
@@ -320,6 +328,7 @@ describe('ReactTestUtils', () => {
328
expect(hrs.length).toBe(2);
329
});
330
331
+ // @gate !disableDOMTestUtils
332
it('provides a clear error when passing invalid objects to scry', () => {
333
// This is probably too relaxed but it's existing behavior.
334
ReactTestUtils.findAllInRenderedTree(null, 'span');
@@ -377,6 +386,7 @@ describe('ReactTestUtils', () => {
386
});
387
388
describe('Simulate', () => {
389
+ // @gate !disableDOMTestUtils
390
it('should change the value of an input field', async () => {
391
const obj = {
392
handler: function (e) {
@@ -399,6 +409,7 @@ describe('ReactTestUtils', () => {
409
);
410
});
411
412
+ // @gate !disableDOMTestUtils
413
it('should change the value of an input field in a component', async () => {
414
class SomeComponent extends React.Component {
415
inputRef = React.createRef();
@@ -442,6 +453,7 @@ describe('ReactTestUtils', () => {
453
);
454
});
455
456
+ // @gate !disableDOMTestUtils
457
it('should not warn when used with extra properties', async () => {
458
const CLIENT_X = 100;
459
@@ -468,6 +480,7 @@ describe('ReactTestUtils', () => {
480
});
481
});
482
483
+ // @gate !disableDOMTestUtils
484
it('should set the type of the event', async () => {
485
let event;
486
const stub = jest.fn().mockImplementation(e => {
@@ -488,6 +501,7 @@ describe('ReactTestUtils', () => {
501
expect(event.nativeEvent.type).toBe('keydown');
502
});
503
504
+ // @gate !disableDOMTestUtils
505
it('should work with renderIntoDocument', async () => {
506
const onChange = jest.fn();
507
@@ -520,6 +534,7 @@ describe('ReactTestUtils', () => {
534
);
535
});
536
537
+ // @gate !disableDOMTestUtils
538
it('should have mouse enter simulated by test utils', async () => {
539
const idCallOrder = [];
540
const recordID = function (id) {
@@ -560,8 +575,17 @@ describe('ReactTestUtils', () => {
575
});
576
expect(idCallOrder).toEqual([CHILD]);
577
});
578
+
579
+ // @gate disableDOMTestUtils
580
+ it('throws', async () => {
581
+ expect(ReactTestUtils.Simulate.click).toThrow(
582
+ '`Simulate` was removed from `react-dom/test-utils`. ' +
583
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
584
+ );
585
+ });
586
});
587
588
+ // @gate !disableDOMTestUtils
589
it('should call setState callback with no arguments', async () => {
590
let mockArgs;
591
class Component extends React.Component {
@@ -573,14 +597,12 @@ describe('ReactTestUtils', () => {
597
}
598
}
599
576
- const container = document.createElement('div');
577
- const root = ReactDOMClient.createRoot(container);
578
- await act(() => {
579
- root.render(<Component />);
580
- });
600
+ ReactTestUtils.renderIntoDocument(<Component />);
601
602
expect(mockArgs.length).toEqual(0);
603
});
604
+
605
+ // @gate !disableDOMTestUtils
606
it('should find rendered component with type in document', async () => {
607
class MyComponent extends React.Component {
608
render() {
@@ -602,4 +624,12 @@ describe('ReactTestUtils', () => {
624
625
expect(renderedComponentType).toBe(instance);
626
});
627
+
628
+ // @gate disableDOMTestUtils
629
+ it('throws on every removed function', async () => {
630
+ expect(ReactTestUtils.isDOMComponent).toThrow(
631
+ '`isDOMComponent` was removed from `react-dom/test-utils`. ' +
632
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
633
+ );
634
+ });
635
});
packages/react-dom/src/test-utils/ReactTestUtils.js
+120
@@ -21,6 +21,7 @@ import {
21
} from 'react-reconciler/src/ReactWorkTags';
22
import {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';
23
import {ELEMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType';
24
+import {disableDOMTestUtils} from 'shared/ReactFeatureFlags';
25
import assign from 'shared/assign';
26
import isArray from 'shared/isArray';
27
@@ -126,6 +127,13 @@ function validateClassInstance(inst, methodName) {
127
* @lends ReactTestUtils
128
*/
129
function renderIntoDocument(element) {
130
+ if (disableDOMTestUtils) {
131
+ throw new Error(
132
+ '`renderIntoDocument` was removed from `react-dom/test-utils`. ' +
133
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
134
+ );
135
+ }
136
+
137
const div = document.createElement('div');
138
// None of our tests actually require attaching the container to the
139
// DOM, and doing so creates a mess that we rely on test isolation to
@@ -136,22 +144,57 @@ function renderIntoDocument(element) {
144
}
145
146
function isElement(element) {
147
+ if (disableDOMTestUtils) {
148
+ throw new Error(
149
+ '`isElement` was removed from `react-dom/test-utils`. ' +
150
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
151
+ );
152
+ }
153
+
154
return React.isValidElement(element);
155
}
156
157
function isElementOfType(inst, convenienceConstructor) {
158
+ if (disableDOMTestUtils) {
159
+ throw new Error(
160
+ '`isElementOfType` was removed from `react-dom/test-utils`. ' +
161
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
162
+ );
163
+ }
164
+
165
return React.isValidElement(inst) && inst.type === convenienceConstructor;
166
}
167
168
function isDOMComponent(inst) {
169
+ if (disableDOMTestUtils) {
170
+ throw new Error(
171
+ '`isDOMComponent` was removed from `react-dom/test-utils`. ' +
172
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
173
+ );
174
+ }
175
+
176
return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
177
}
178
179
function isDOMComponentElement(inst) {
180
+ if (disableDOMTestUtils) {
181
+ throw new Error(
182
+ '`isDOMComponentElement` was removed from `react-dom/test-utils`. ' +
183
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
184
+ );
185
+ }
186
+
187
return !!(inst && React.isValidElement(inst) && !!inst.tagName);
188
}
189
190
function isCompositeComponent(inst) {
191
+ if (disableDOMTestUtils) {
192
+ throw new Error(
193
+ '`isCompositeComponent` was removed from `react-dom/test-utils`. ' +
194
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
195
+ );
196
+ }
197
+
198
if (isDOMComponent(inst)) {
199
// Accessing inst.setState warns; just return false as that'll be what
200
// this returns when we have DOM nodes as refs directly
@@ -165,6 +208,13 @@ function isCompositeComponent(inst) {
208
}
209
210
function isCompositeComponentWithType(inst, type) {
211
+ if (disableDOMTestUtils) {
212
+ throw new Error(
213
+ '`isCompositeComponentWithType` was removed from `react-dom/test-utils`. ' +
214
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
215
+ );
216
+ }
217
+
218
if (!isCompositeComponent(inst)) {
219
return false;
220
}
@@ -174,6 +224,13 @@ function isCompositeComponentWithType(inst, type) {
224
}
225
226
function findAllInRenderedTree(inst, test) {
227
+ if (disableDOMTestUtils) {
228
+ throw new Error(
229
+ '`findAllInRenderedTree` was removed from `react-dom/test-utils`. ' +
230
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
231
+ );
232
+ }
233
+
234
validateClassInstance(inst, 'findAllInRenderedTree');
235
if (!inst) {
236
return [];
@@ -188,6 +245,13 @@ function findAllInRenderedTree(inst, test) {
245
* @return {array} an array of all the matches.
246
*/
247
function scryRenderedDOMComponentsWithClass(root, classNames) {
248
+ if (disableDOMTestUtils) {
249
+ throw new Error(
250
+ '`scryRenderedDOMComponentsWithClass` was removed from `react-dom/test-utils`. ' +
251
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
252
+ );
253
+ }
254
+
255
validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
256
return findAllInRenderedTree(root, function (inst) {
257
if (isDOMComponent(inst)) {
@@ -223,6 +287,13 @@ function scryRenderedDOMComponentsWithClass(root, classNames) {
287
* @return {!ReactDOMComponent} The one match.
288
*/
289
function findRenderedDOMComponentWithClass(root, className) {
290
+ if (disableDOMTestUtils) {
291
+ throw new Error(
292
+ '`findRenderedDOMComponentWithClass` was removed from `react-dom/test-utils`. ' +
293
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
294
+ );
295
+ }
296
+
297
validateClassInstance(root, 'findRenderedDOMComponentWithClass');
298
const all = scryRenderedDOMComponentsWithClass(root, className);
299
if (all.length !== 1) {
@@ -243,6 +314,13 @@ function findRenderedDOMComponentWithClass(root, className) {
314
* @return {array} an array of all the matches.
315
*/
316
function scryRenderedDOMComponentsWithTag(root, tagName) {
317
+ if (disableDOMTestUtils) {
318
+ throw new Error(
319
+ '`scryRenderedDOMComponentsWithTag` was removed from `react-dom/test-utils`. ' +
320
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
321
+ );
322
+ }
323
+
324
validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
325
return findAllInRenderedTree(root, function (inst) {
326
return (
@@ -259,6 +337,13 @@ function scryRenderedDOMComponentsWithTag(root, tagName) {
337
* @return {!ReactDOMComponent} The one match.
338
*/
339
function findRenderedDOMComponentWithTag(root, tagName) {
340
+ if (disableDOMTestUtils) {
341
+ throw new Error(
342
+ '`findRenderedDOMComponentWithTag` was removed from `react-dom/test-utils`. ' +
343
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
344
+ );
345
+ }
346
+
347
validateClassInstance(root, 'findRenderedDOMComponentWithTag');
348
const all = scryRenderedDOMComponentsWithTag(root, tagName);
349
if (all.length !== 1) {
@@ -278,6 +363,13 @@ function findRenderedDOMComponentWithTag(root, tagName) {
363
* @return {array} an array of all the matches.
364
*/
365
function scryRenderedComponentsWithType(root, componentType) {
366
+ if (disableDOMTestUtils) {
367
+ throw new Error(
368
+ '`scryRenderedComponentsWithType` was removed from `react-dom/test-utils`. ' +
369
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
370
+ );
371
+ }
372
+
373
validateClassInstance(root, 'scryRenderedComponentsWithType');
374
return findAllInRenderedTree(root, function (inst) {
375
return isCompositeComponentWithType(inst, componentType);
@@ -291,6 +383,13 @@ function scryRenderedComponentsWithType(root, componentType) {
383
* @return {!ReactComponent} The one match.
384
*/
385
function findRenderedComponentWithType(root, componentType) {
386
+ if (disableDOMTestUtils) {
387
+ throw new Error(
388
+ '`findRenderedComponentWithType` was removed from `react-dom/test-utils`. ' +
389
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
390
+ );
391
+ }
392
+
393
validateClassInstance(root, 'findRenderedComponentWithType');
394
const all = scryRenderedComponentsWithType(root, componentType);
395
if (all.length !== 1) {
@@ -319,6 +418,13 @@ function findRenderedComponentWithType(root, componentType) {
418
* @return {object} the ReactTestUtils object (for chaining)
419
*/
420
function mockComponent(module, mockTagName) {
421
+ if (disableDOMTestUtils) {
422
+ throw new Error(
423
+ '`mockComponent` was removed from `react-dom/test-utils`. ' +
424
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
425
+ );
426
+ }
427
+
428
if (__DEV__) {
429
if (!hasWarnedAboutDeprecatedMockComponent) {
430
hasWarnedAboutDeprecatedMockComponent = true;
@@ -340,6 +446,13 @@ function mockComponent(module, mockTagName) {
446
}
447
448
function nativeTouchData(x, y) {
449
+ if (disableDOMTestUtils) {
450
+ throw new Error(
451
+ '`nativeTouchData` was removed from `react-dom/test-utils`. ' +
452
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
453
+ );
454
+ }
455
+
456
return {
457
touches: [{pageX: x, pageY: y}],
458
};
@@ -578,6 +691,13 @@ const directDispatchEventTypes = new Set([
691
*/
692
function makeSimulator(eventType) {
693
return function (domNode, eventData) {
694
+ if (disableDOMTestUtils) {
695
+ throw new Error(
696
+ '`Simulate` was removed from `react-dom/test-utils`. ' +
697
+ 'See https://react.dev/warnings/react-dom-test-utils for more info.',
698
+ );
699
+ }
700
+
701
if (React.isValidElement(domNode)) {
702
throw new Error(
703
'TestUtils.Simulate expected a DOM node as the first argument but received ' +
packages/shared/ReactFeatureFlags.js
+2
@@ -187,6 +187,8 @@ export const enableReactTestRendererWarning = __NEXT_MAJOR__;
187
// before removing them in stable in the next Major
188
export const disableLegacyMode = __NEXT_MAJOR__;
189
190
+export const disableDOMTestUtils = __NEXT_MAJOR__;
191
+
192
// HTML boolean attributes need a special PropertyInfoRecord.
193
// Between support of these attributes in browsers and React supporting them as
194
// boolean props library users can use them as `<div someBooleanAttribute="" />`.
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -100,6 +100,7 @@ export const disableStringRefs = false;
100
101
export const enableReactTestRendererWarning = false;
102
export const disableLegacyMode = false;
103
+export const disableDOMTestUtils = false;
104
105
// Flow magic to verify the exports of this file match the original version.
106
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -21,6 +21,7 @@ const __TODO_NEXT_RN_MAJOR__ = false;
21
export const enableRefAsProp = __TODO_NEXT_RN_MAJOR__;
22
export const disableStringRefs = __TODO_NEXT_RN_MAJOR__;
23
export const disableLegacyMode = __TODO_NEXT_RN_MAJOR__;
24
+export const disableDOMTestUtils = __TODO_NEXT_RN_MAJOR__;
25
export const enableBigIntSupport = __TODO_NEXT_RN_MAJOR__;
26
export const useModernStrictMode = __TODO_NEXT_RN_MAJOR__;
27
export const enableReactTestRendererWarning = __TODO_NEXT_RN_MAJOR__;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -92,6 +92,7 @@ export const disableStringRefs = __NEXT_MAJOR__;
92
export const enableBigIntSupport = __NEXT_MAJOR__;
93
export const disableLegacyMode = __NEXT_MAJOR__;
94
export const disableLegacyContext = __NEXT_MAJOR__;
95
+export const disableDOMTestUtils = __NEXT_MAJOR__;
96
export const enableNewBooleanProps = __NEXT_MAJOR__;
97
export const disableModulePatternComponents = __NEXT_MAJOR__;
98
export const enableRenderableContext = __NEXT_MAJOR__;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+1
@@ -87,6 +87,7 @@ export const disableStringRefs = false;
87
88
export const enableReactTestRendererWarning = false;
89
export const disableLegacyMode = false;
90
+export const disableDOMTestUtils = false;
91
92
export const enableBigIntSupport = false;
93
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -89,6 +89,7 @@ export const disableStringRefs = false;
89
90
export const enableReactTestRendererWarning = false;
91
export const disableLegacyMode = false;
92
+export const disableDOMTestUtils = false;
93
94
export const enableBigIntSupport = true;
95
packages/shared/forks/ReactFeatureFlags.www.js
+2
@@ -121,5 +121,7 @@ export const disableStringRefs = false;
121
122
export const disableLegacyMode = false;
123
124
+export const disableDOMTestUtils = false;
125
+
126
// Flow magic to verify the exports of this file match the original version.
127
((((null: any): ExportsType): FeatureFlagsType): ExportsType);