diff --git a/packages/react-dom/src/__tests__/ReactTestUtils-test.js b/packages/react-dom/src/__tests__/ReactTestUtils-test.js
index 2fa0ea75a36e8..d26f6d8e808f9 100644
--- a/packages/react-dom/src/__tests__/ReactTestUtils-test.js
+++ b/packages/react-dom/src/__tests__/ReactTestUtils-test.js
@@ -31,6 +31,7 @@ describe('ReactTestUtils', () => {
expect(Object.keys(ReactTestUtils.Simulate).sort()).toMatchSnapshot();
});
+ // @gate !disableDOMTestUtils
it('gives Jest mocks a passthrough implementation with mockComponent()', async () => {
class MockedComponent extends React.Component {
render() {
@@ -60,6 +61,7 @@ describe('ReactTestUtils', () => {
expect(container.textContent).toBe('Hello');
});
+ // @gate !disableDOMTestUtils
it('can scryRenderedComponentsWithType', async () => {
class Child extends React.Component {
render() {
@@ -88,6 +90,7 @@ describe('ReactTestUtils', () => {
expect(scryResults.length).toBe(1);
});
+ // @gate !disableDOMTestUtils
it('can scryRenderedDOMComponentsWithClass with TextComponent', async () => {
class Wrapper extends React.Component {
render() {
@@ -112,6 +115,7 @@ describe('ReactTestUtils', () => {
expect(scryResults.length).toBe(0);
});
+ // @gate !disableDOMTestUtils
it('can scryRenderedDOMComponentsWithClass with className contains \\n', async () => {
class Wrapper extends React.Component {
render() {
@@ -136,6 +140,7 @@ describe('ReactTestUtils', () => {
expect(scryResults.length).toBe(1);
});
+ // @gate !disableDOMTestUtils
it('can scryRenderedDOMComponentsWithClass with multiple classes', async () => {
class Wrapper extends React.Component {
render() {
@@ -187,6 +192,7 @@ describe('ReactTestUtils', () => {
expect(scryResults5.length).toBe(0);
});
+ // @gate !disableDOMTestUtils
it('traverses children in the correct order', async () => {
class Wrapper extends React.Component {
render() {
@@ -225,6 +231,7 @@ describe('ReactTestUtils', () => {
expect(log).toEqual(['orangepurple', 'orange', 'purple']);
});
+ // @gate !disableDOMTestUtils
it('should support injected wrapper components as DOM components', async () => {
const injectedDOMComponents = [
'button',
@@ -291,6 +298,7 @@ describe('ReactTestUtils', () => {
expect(ReactTestUtils.isDOMComponent(component.bodyRef.current)).toBe(true);
});
+ // @gate !disableDOMTestUtils
it('can scry with stateless components involved', async () => {
const Function = () => (
@@ -320,6 +328,7 @@ describe('ReactTestUtils', () => {
expect(hrs.length).toBe(2);
});
+ // @gate !disableDOMTestUtils
it('provides a clear error when passing invalid objects to scry', () => {
// This is probably too relaxed but it's existing behavior.
ReactTestUtils.findAllInRenderedTree(null, 'span');
@@ -377,6 +386,7 @@ describe('ReactTestUtils', () => {
});
describe('Simulate', () => {
+ // @gate !disableDOMTestUtils
it('should change the value of an input field', async () => {
const obj = {
handler: function (e) {
@@ -399,6 +409,7 @@ describe('ReactTestUtils', () => {
);
});
+ // @gate !disableDOMTestUtils
it('should change the value of an input field in a component', async () => {
class SomeComponent extends React.Component {
inputRef = React.createRef();
@@ -442,6 +453,7 @@ describe('ReactTestUtils', () => {
);
});
+ // @gate !disableDOMTestUtils
it('should not warn when used with extra properties', async () => {
const CLIENT_X = 100;
@@ -468,6 +480,7 @@ describe('ReactTestUtils', () => {
});
});
+ // @gate !disableDOMTestUtils
it('should set the type of the event', async () => {
let event;
const stub = jest.fn().mockImplementation(e => {
@@ -488,6 +501,7 @@ describe('ReactTestUtils', () => {
expect(event.nativeEvent.type).toBe('keydown');
});
+ // @gate !disableDOMTestUtils
it('should work with renderIntoDocument', async () => {
const onChange = jest.fn();
@@ -520,6 +534,7 @@ describe('ReactTestUtils', () => {
);
});
+ // @gate !disableDOMTestUtils
it('should have mouse enter simulated by test utils', async () => {
const idCallOrder = [];
const recordID = function (id) {
@@ -560,8 +575,17 @@ describe('ReactTestUtils', () => {
});
expect(idCallOrder).toEqual([CHILD]);
});
+
+ // @gate disableDOMTestUtils
+ it('throws', async () => {
+ expect(ReactTestUtils.Simulate.click).toThrow(
+ '`Simulate` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ });
});
+ // @gate !disableDOMTestUtils
it('should call setState callback with no arguments', async () => {
let mockArgs;
class Component extends React.Component {
@@ -573,14 +597,12 @@ describe('ReactTestUtils', () => {
}
}
- const container = document.createElement('div');
- const root = ReactDOMClient.createRoot(container);
- await act(() => {
- root.render(
);
- });
+ ReactTestUtils.renderIntoDocument(
);
expect(mockArgs.length).toEqual(0);
});
+
+ // @gate !disableDOMTestUtils
it('should find rendered component with type in document', async () => {
class MyComponent extends React.Component {
render() {
@@ -602,4 +624,12 @@ describe('ReactTestUtils', () => {
expect(renderedComponentType).toBe(instance);
});
+
+ // @gate disableDOMTestUtils
+ it('throws on every removed function', async () => {
+ expect(ReactTestUtils.isDOMComponent).toThrow(
+ '`isDOMComponent` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ });
});
diff --git a/packages/react-dom/src/test-utils/ReactTestUtils.js b/packages/react-dom/src/test-utils/ReactTestUtils.js
index 7391ea2b6f6f8..afd4f5a88b9e7 100644
--- a/packages/react-dom/src/test-utils/ReactTestUtils.js
+++ b/packages/react-dom/src/test-utils/ReactTestUtils.js
@@ -21,6 +21,7 @@ import {
} from 'react-reconciler/src/ReactWorkTags';
import {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';
import {ELEMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType';
+import {disableDOMTestUtils} from 'shared/ReactFeatureFlags';
import assign from 'shared/assign';
import isArray from 'shared/isArray';
@@ -126,6 +127,13 @@ function validateClassInstance(inst, methodName) {
* @lends ReactTestUtils
*/
function renderIntoDocument(element) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`renderIntoDocument` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
const div = document.createElement('div');
// None of our tests actually require attaching the container to the
// DOM, and doing so creates a mess that we rely on test isolation to
@@ -136,22 +144,57 @@ function renderIntoDocument(element) {
}
function isElement(element) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isElement` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
return React.isValidElement(element);
}
function isElementOfType(inst, convenienceConstructor) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isElementOfType` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
return React.isValidElement(inst) && inst.type === convenienceConstructor;
}
function isDOMComponent(inst) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isDOMComponent` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
}
function isDOMComponentElement(inst) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isDOMComponentElement` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
return !!(inst && React.isValidElement(inst) && !!inst.tagName);
}
function isCompositeComponent(inst) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isCompositeComponent` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
if (isDOMComponent(inst)) {
// Accessing inst.setState warns; just return false as that'll be what
// this returns when we have DOM nodes as refs directly
@@ -165,6 +208,13 @@ function isCompositeComponent(inst) {
}
function isCompositeComponentWithType(inst, type) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`isCompositeComponentWithType` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
if (!isCompositeComponent(inst)) {
return false;
}
@@ -174,6 +224,13 @@ function isCompositeComponentWithType(inst, type) {
}
function findAllInRenderedTree(inst, test) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`findAllInRenderedTree` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(inst, 'findAllInRenderedTree');
if (!inst) {
return [];
@@ -188,6 +245,13 @@ function findAllInRenderedTree(inst, test) {
* @return {array} an array of all the matches.
*/
function scryRenderedDOMComponentsWithClass(root, classNames) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`scryRenderedDOMComponentsWithClass` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
return findAllInRenderedTree(root, function (inst) {
if (isDOMComponent(inst)) {
@@ -223,6 +287,13 @@ function scryRenderedDOMComponentsWithClass(root, classNames) {
* @return {!ReactDOMComponent} The one match.
*/
function findRenderedDOMComponentWithClass(root, className) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`findRenderedDOMComponentWithClass` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'findRenderedDOMComponentWithClass');
const all = scryRenderedDOMComponentsWithClass(root, className);
if (all.length !== 1) {
@@ -243,6 +314,13 @@ function findRenderedDOMComponentWithClass(root, className) {
* @return {array} an array of all the matches.
*/
function scryRenderedDOMComponentsWithTag(root, tagName) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`scryRenderedDOMComponentsWithTag` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
return findAllInRenderedTree(root, function (inst) {
return (
@@ -259,6 +337,13 @@ function scryRenderedDOMComponentsWithTag(root, tagName) {
* @return {!ReactDOMComponent} The one match.
*/
function findRenderedDOMComponentWithTag(root, tagName) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`findRenderedDOMComponentWithTag` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'findRenderedDOMComponentWithTag');
const all = scryRenderedDOMComponentsWithTag(root, tagName);
if (all.length !== 1) {
@@ -278,6 +363,13 @@ function findRenderedDOMComponentWithTag(root, tagName) {
* @return {array} an array of all the matches.
*/
function scryRenderedComponentsWithType(root, componentType) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`scryRenderedComponentsWithType` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'scryRenderedComponentsWithType');
return findAllInRenderedTree(root, function (inst) {
return isCompositeComponentWithType(inst, componentType);
@@ -291,6 +383,13 @@ function scryRenderedComponentsWithType(root, componentType) {
* @return {!ReactComponent} The one match.
*/
function findRenderedComponentWithType(root, componentType) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`findRenderedComponentWithType` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
validateClassInstance(root, 'findRenderedComponentWithType');
const all = scryRenderedComponentsWithType(root, componentType);
if (all.length !== 1) {
@@ -319,6 +418,13 @@ function findRenderedComponentWithType(root, componentType) {
* @return {object} the ReactTestUtils object (for chaining)
*/
function mockComponent(module, mockTagName) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`mockComponent` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
if (__DEV__) {
if (!hasWarnedAboutDeprecatedMockComponent) {
hasWarnedAboutDeprecatedMockComponent = true;
@@ -340,6 +446,13 @@ function mockComponent(module, mockTagName) {
}
function nativeTouchData(x, y) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`nativeTouchData` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
return {
touches: [{pageX: x, pageY: y}],
};
@@ -578,6 +691,13 @@ const directDispatchEventTypes = new Set([
*/
function makeSimulator(eventType) {
return function (domNode, eventData) {
+ if (disableDOMTestUtils) {
+ throw new Error(
+ '`Simulate` was removed from `react-dom/test-utils`. ' +
+ 'See https://react.dev/warnings/react-test-renderer for more info.',
+ );
+ }
+
if (React.isValidElement(domNode)) {
throw new Error(
'TestUtils.Simulate expected a DOM node as the first argument but received ' +
diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js
index cd6273a229404..a06e36e72775b 100644
--- a/packages/shared/ReactFeatureFlags.js
+++ b/packages/shared/ReactFeatureFlags.js
@@ -198,6 +198,8 @@ export const enableReactTestRendererWarning = false;
// before removing them in stable in the next Major
export const disableLegacyMode = __NEXT_MAJOR__;
+export const disableDOMTestUtils = __NEXT_MAJOR__;
+
// HTML boolean attributes need a special PropertyInfoRecord.
// Between support of these attributes in browsers and React supporting them as
// boolean props library users can use them as `
`.
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js
index 444d956e8dbde..e738374135b34 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js
@@ -102,6 +102,7 @@ export const disableStringRefs = false;
export const enableReactTestRendererWarning = false;
export const disableLegacyMode = false;
+export const disableDOMTestUtils = true;
export const enableBigIntSupport = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js
index 8e992b805f4d9..fea0b7ea509d5 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-oss.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js
@@ -21,6 +21,7 @@ const __TODO_NEXT_RN_MAJOR__ = false;
export const enableRefAsProp = __TODO_NEXT_RN_MAJOR__;
export const disableStringRefs = __TODO_NEXT_RN_MAJOR__;
export const disableLegacyMode = __TODO_NEXT_RN_MAJOR__;
+export const disableDOMTestUtils = __TODO_NEXT_RN_MAJOR__;
export const enableBigIntSupport = __TODO_NEXT_RN_MAJOR__;
export const useModernStrictMode = __TODO_NEXT_RN_MAJOR__;
export const enableReactTestRendererWarning = __TODO_NEXT_RN_MAJOR__;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
index 819554d5cf6b0..9e8a2e1ab4d26 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
@@ -97,6 +97,7 @@ export const enableReactTestRendererWarning = false;
export const enableBigIntSupport = __NEXT_MAJOR__;
export const disableLegacyMode = __NEXT_MAJOR__;
export const disableLegacyContext = __NEXT_MAJOR__;
+export const disableDOMTestUtils = __NEXT_MAJOR__;
export const enableNewBooleanProps = __NEXT_MAJOR__;
export const disableModulePatternComponents = __NEXT_MAJOR__;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
index 01fc8ab188614..a01ea8045b951 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
@@ -90,6 +90,7 @@ export const disableStringRefs = false;
export const enableReactTestRendererWarning = false;
export const disableLegacyMode = false;
+export const disableDOMTestUtils = true;
export const enableBigIntSupport = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
index ba307873cef59..8625d541e6f13 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
@@ -92,6 +92,7 @@ export const disableStringRefs = false;
export const enableReactTestRendererWarning = false;
export const disableLegacyMode = false;
+export const disableDOMTestUtils = false;
export const enableBigIntSupport = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index 698cc86366b2c..9814fccc1070c 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -125,5 +125,7 @@ export const disableStringRefs = false;
export const disableLegacyMode = false;
+export const disableDOMTestUtils = false;
+
// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): FeatureFlagsType): ExportsType);