diff --git a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
index 810452c64a313..3d21ca64e399e 100644
--- a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
@@ -13,9 +13,9 @@ function emptyFunction() {}
describe('ReactDOMTextarea', () => {
let React;
- let ReactDOM;
+ let ReactDOMClient;
let ReactDOMServer;
- let ReactTestUtils;
+ let act;
let renderTextarea;
@@ -25,15 +25,16 @@ describe('ReactDOMTextarea', () => {
jest.resetModules();
React = require('react');
- ReactDOM = require('react-dom');
+ ReactDOMClient = require('react-dom/client');
ReactDOMServer = require('react-dom/server');
- ReactTestUtils = require('react-dom/test-utils');
+ act = require('internal-test-utils').act;
- renderTextarea = function (component, container) {
- if (!container) {
- container = document.createElement('div');
- }
- const node = ReactDOM.render(component, container);
+ renderTextarea = async function (component, container, root) {
+ await act(() => {
+ root.render(component);
+ });
+
+ const node = container.firstChild;
// Fixing jsdom's quirky behavior -- in reality, the parser should strip
// off the leading newline but we need to do it by hand here.
@@ -46,93 +47,141 @@ describe('ReactDOMTextarea', () => {
jest.restoreAllMocks();
});
- it('should allow setting `defaultValue`', () => {
+ it('should allow setting `defaultValue`', async () => {
const container = document.createElement('div');
- const node = renderTextarea(, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
// Changing `defaultValue` should do nothing.
- renderTextarea(, container);
+ await renderTextarea(, container, root);
expect(node.value).toEqual('giraffe');
node.value = 'cat';
- renderTextarea(, container);
+ await renderTextarea(, container, root);
expect(node.value).toEqual('cat');
});
- it('should display `defaultValue` of number 0', () => {
- const stub = ;
- const node = renderTextarea(stub);
+ it('should display `defaultValue` of number 0', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('0');
});
- it('should display "false" for `defaultValue` of `false`', () => {
- const stub = ;
- const node = renderTextarea(stub);
+ it('should display "false" for `defaultValue` of `false`', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('false');
});
- it('should display "foobar" for `defaultValue` of `objToString`', () => {
+ it('should display "foobar" for `defaultValue` of `objToString`', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
const objToString = {
toString: function () {
return 'foobar';
},
};
-
- const stub = ;
- const node = renderTextarea(stub);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('foobar');
});
- it('should set defaultValue', () => {
+ it('should set defaultValue', async () => {
const container = document.createElement('div');
- ReactDOM.render(, container);
- ReactDOM.render(, container);
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
+ await act(() => {
+ root.render();
+ });
+ await act(() => {
+ root.render();
+ });
+
expect(container.firstChild.defaultValue).toBe('noise');
});
- it('should not render value as an attribute', () => {
- const stub = ;
- const node = renderTextarea(stub);
+ it('should not render value as an attribute', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.getAttribute('value')).toBe(null);
});
- it('should display `value` of number 0', () => {
- const stub = ;
- const node = renderTextarea(stub);
+ it('should display `value` of number 0', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('0');
});
- it('should update defaultValue to empty string', () => {
+ it('should update defaultValue to empty string', async () => {
const container = document.createElement('div');
- ReactDOM.render(, container);
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
+
+ await act(() => {
+ root.render();
+ });
+
expect(container.firstChild.defaultValue).toBe('');
});
- it('should allow setting `value` to `giraffe`', () => {
+ it('should allow setting `value` to `giraffe`', async () => {
const container = document.createElement('div');
- let stub = ;
- const node = renderTextarea(stub, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
- stub = ReactDOM.render(
- ,
- container,
- );
+ await act(() => {
+ root.render();
+ });
+
expect(node.value).toEqual('gorilla');
});
- it('will not initially assign an empty value (covers case where firefox throws a validation error when required attribute is set)', () => {
+ it('will not initially assign an empty value (covers case where firefox throws a validation error when required attribute is set)', async () => {
const container = document.createElement('div');
let counter = 0;
@@ -156,7 +205,10 @@ describe('ReactDOMTextarea', () => {
},
);
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
expect(counter).toEqual(0);
});
@@ -178,38 +230,50 @@ describe('ReactDOMTextarea', () => {
expect(div.firstChild.getAttribute('defaultValue')).toBe(null);
});
- it('should allow setting `value` to `true`', () => {
+ it('should allow setting `value` to `true`', async () => {
const container = document.createElement('div');
- let stub = ;
- const node = renderTextarea(stub, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
- stub = ReactDOM.render(
- ,
- container,
- );
+ await act(() => {
+ root.render();
+ });
+
expect(node.value).toEqual('true');
});
- it('should allow setting `value` to `false`', () => {
+ it('should allow setting `value` to `false`', async () => {
const container = document.createElement('div');
- let stub = ;
- const node = renderTextarea(stub, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
- stub = ReactDOM.render(
- ,
- container,
- );
+ await act(() => {
+ root.render();
+ });
+
expect(node.value).toEqual('false');
});
- it('should allow setting `value` to `objToString`', () => {
+ it('should allow setting `value` to `objToString`', async () => {
const container = document.createElement('div');
- let stub = ;
- const node = renderTextarea(stub, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
@@ -218,14 +282,15 @@ describe('ReactDOMTextarea', () => {
return 'foo';
},
};
- stub = ReactDOM.render(
- ,
- container,
- );
+
+ await act(() => {
+ root.render();
+ });
+
expect(node.value).toEqual('foo');
});
- it('should throw when value is set to a Temporal-like object', () => {
+ it('should throw when value is set to a Temporal-like object', async () => {
class TemporalLike {
valueOf() {
// Throwing here is the behavior of ECMAScript "Temporal" date/time API.
@@ -237,51 +302,72 @@ describe('ReactDOMTextarea', () => {
}
}
const container = document.createElement('div');
- const stub = ;
- const node = renderTextarea(stub, container);
+ const root = ReactDOMClient.createRoot(container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
expect(node.value).toBe('giraffe');
- const test = () =>
- ReactDOM.render(
- ,
- container,
- );
- expect(() =>
- expect(test).toThrowError(new TypeError('prod message')),
+ const test = async () => {
+ await act(() => {
+ root.render(
+ ,
+ );
+ });
+ };
+ await expect(() =>
+ expect(test).rejects.toThrowError(new TypeError('prod message')),
).toErrorDev(
'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +
'strings, not TemporalLike. This value must be coerced to a string before using it here.',
);
});
- it('should take updates to `defaultValue` for uncontrolled textarea', () => {
+ it('should take updates to `defaultValue` for uncontrolled textarea', async () => {
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
- const node = ReactDOM.render(, container);
+ const node = container.firstChild;
expect(node.value).toBe('0');
- ReactDOM.render(, container);
+ await act(() => {
+ root.render();
+ });
expect(node.value).toBe('0');
});
- it('should take updates to children in lieu of `defaultValue` for uncontrolled textarea', () => {
+ it('should take updates to children in lieu of `defaultValue` for uncontrolled textarea', async () => {
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
- const node = ReactDOM.render(, container);
+ const node = container.firstChild;
expect(node.value).toBe('0');
- ReactDOM.render(, container);
+ await act(() => {
+ root.render();
+ });
expect(node.value).toBe('0');
});
- it('should not incur unnecessary DOM mutations', () => {
+ it('should not incur unnecessary DOM mutations', async () => {
const container = document.createElement('div');
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
const node = container.firstChild;
let nodeValue = 'a';
@@ -295,25 +381,35 @@ describe('ReactDOMTextarea', () => {
}),
});
- ReactDOM.render(, container);
+ await act(() => {
+ root.render();
+ });
+
expect(nodeValueSetter).toHaveBeenCalledTimes(0);
- ReactDOM.render(, container);
+ await act(() => {
+ root.render();
+ });
+
expect(nodeValueSetter).toHaveBeenCalledTimes(1);
});
- it('should properly control a value of number `0`', () => {
- const stub = ;
+ it('should properly control a value of number `0`', async () => {
const setUntrackedValue = Object.getOwnPropertyDescriptor(
HTMLTextAreaElement.prototype,
'value',
).set;
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
document.body.appendChild(container);
try {
- const node = renderTextarea(stub, container);
+ const node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
setUntrackedValue.call(node, 'giraffe');
node.dispatchEvent(
@@ -326,30 +422,41 @@ describe('ReactDOMTextarea', () => {
});
if (ReactFeatureFlags.disableTextareaChildren) {
- it('should ignore children content', () => {
+ it('should ignore children content', async () => {
const container = document.createElement('div');
- let stub = ;
+ const root = ReactDOMClient.createRoot(container);
let node;
- expect(() => {
- node = renderTextarea(stub, container);
+ await expect(async () => {
+ node = await renderTextarea(
+ ,
+ container,
+ root,
+ );
}).toErrorDev(
'Use the `defaultValue` or `value` props instead of setting children on