Repository: facebook/react
Pull request: Convert ReactDOMSelect to createRoot


Changed files:
filename: packages/react-dom/src/__tests__/ReactDOMSelect-test.js
patch: @@ -19,20 +19,22 @@ Element.prototype.setAttribute = function (name, value) {
 describe('ReactDOMSelect', () => {
   let React;
   let ReactDOM;
+  let ReactDOMClient;
   let ReactDOMServer;
-  let ReactTestUtils;
+  let act;
 
   const noop = function () {};
 
   beforeEach(() => {
     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;
   });
 
-  it('should allow setting `defaultValue`', () => {
+  it('should allow setting `defaultValue`', async () => {
     const stub = (
       <select defaultValue="giraffe">
         <option value="monkey">A monkey!</option>
@@ -42,27 +44,36 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.value).toBe('giraffe');
 
-    // Changing `defaultValue` should do nothing.
-    ReactDOM.render(
-      <select defaultValue="gorilla">{options}</select>,
-      container,
-    );
+    await act(() => {
+      root.render(<select defaultValue="gorilla">{options}</select>);
+    });
+
     expect(node.value).toEqual('giraffe');
   });
 
   it('should not throw with `defaultValue` and without children', () => {
     const stub = <select defaultValue="dummy" />;
 
-    expect(() => {
-      ReactTestUtils.renderIntoDocument(stub);
+    expect(async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(stub);
+      });
     }).not.toThrow();
   });
 
-  it('should not control when using `defaultValue`', () => {
+  it('should not control when using `defaultValue`', async () => {
     const el = (
       <select defaultValue="giraffe">
         <option value="monkey">A monkey!</option>
@@ -71,17 +82,26 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const node = ReactDOM.render(el, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(el);
+    });
+
+    const node = container.firstChild;
 
     expect(node.value).toBe('giraffe');
 
     node.value = 'monkey';
-    ReactDOM.render(el, container);
+    await act(() => {
+      root.render(el);
+    });
+
     // Uncontrolled selects shouldn't change the value after first mounting
     expect(node.value).toEqual('monkey');
   });
 
-  it('should allow setting `defaultValue` with multiple', () => {
+  it('should allow setting `defaultValue` with multiple', async () => {
     const stub = (
       <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
         <option value="monkey">A monkey!</option>
@@ -91,26 +111,32 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
 
-    // Changing `defaultValue` should do nothing.
-    ReactDOM.render(
-      <select multiple={true} defaultValue={['monkey']}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} defaultValue={['monkey']}>
+          {options}
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
   });
 
-  it('should allow setting `value`', () => {
+  it('should allow setting `value`', async () => {
     const stub = (
       <select value="giraffe" onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -120,21 +146,28 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.value).toBe('giraffe');
 
-    // Changing the `value` prop should change the selected option.
-    ReactDOM.render(
-      <select value="gorilla" onChange={noop}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select value="gorilla" onChange={noop}>
+          {options}
+        </select>,
+      );
+    });
+
     expect(node.value).toEqual('gorilla');
   });
 
-  it('should default to the first non-disabled option', () => {
+  it('should default to the first non-disabled option', async () => {
     const stub = (
       <select defaultValue="">
         <option disabled={true}>Disabled</option>
@@ -144,12 +177,18 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
     expect(node.options[0].selected).toBe(false);
     expect(node.options[2].selected).toBe(true);
   });
 
-  it('should allow setting `value` to __proto__', () => {
+  it('should allow setting `value` to __proto__', async () => {
     const stub = (
       <select value="__proto__" onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -159,29 +198,40 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.value).toBe('__proto__');
 
-    // Changing the `value` prop should change the selected option.
-    ReactDOM.render(
-      <select value="gorilla" onChange={noop}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select value="gorilla" onChange={noop}>
+          {options}
+        </select>,
+      );
+    });
+
     expect(node.value).toEqual('gorilla');
   });
 
   it('should not throw with `value` and without children', () => {
     const stub = <select value="dummy" onChange={noop} />;
 
-    expect(() => {
-      ReactTestUtils.renderIntoDocument(stub);
+    expect(async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(stub);
+      });
     }).not.toThrow();
   });
 
-  it('should allow setting `value` with multiple', () => {
+  it('should allow setting `value` with multiple', async () => {
     const stub = (
       <select multiple={true} value={['giraffe', 'gorilla']} onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -191,26 +241,32 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
 
-    // Changing the `value` prop should change the selected options.
-    ReactDOM.render(
-      <select multiple={true} value={['monkey']} onChange={noop}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} value={['monkey']} onChange={noop}>
+          {options}
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(true); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should allow setting `value` to __proto__ with multiple', () => {
+  it('should allow setting `value` to __proto__ with multiple', async () => {
     const stub = (
       <select multiple={true} value={['__proto__', 'gorilla']} onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -220,60 +276,78 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // __proto__
     expect(node.options[2].selected).toBe(true); // gorilla
 
-    // Changing the `value` prop should change the selected options.
-    ReactDOM.render(
-      <select multiple={true} value={['monkey']} onChange={noop}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} value={['monkey']} onChange={noop}>
+          {options}
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(true); // monkey
     expect(node.options[1].selected).toBe(false); // __proto__
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should not select other options automatically', () => {
+  it('should not select other options automatically', async () => {
     const stub = (
       <select multiple={true} value={['12']} onChange={noop}>
         <option value="1">one</option>
         <option value="2">two</option>
         <option value="12">twelve</option>
       </select>
     );
-    const node = ReactTestUtils.renderIntoDocument(stub);
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // one
     expect(node.options[1].selected).toBe(false); // two
     expect(node.options[2].selected).toBe(true); // twelve
   });
 
-  it('should reset child options selected when they are changed and `value` is set', () => {
+  it('should reset child options selected when they are changed and `value` is set', async () => {
     const stub = <select multiple={true} value={['a', 'b']} onChange={noop} />;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
 
-    ReactDOM.render(
-      <select multiple={true} value={['a', 'b']} onChange={noop}>
-        <option value="a">a</option>
-        <option value="b">b</option>
-        <option value="c">c</option>
-      </select>,
-      container,
-    );
+    const node = container.firstChild;
+
+    await act(() => {
+      root.render(
+        <select multiple={true} value={['a', 'b']} onChange={noop}>
+          <option value="a">a</option>
+          <option value="b">b</option>
+          <option value="c">c</option>
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(true); // a
     expect(node.options[1].selected).toBe(true); // b
     expect(node.options[2].selected).toBe(false); // c
   });
 
-  it('should allow setting `value` with `objectToString`', () => {
+  it('should allow setting `value` with `objectToString`', async () => {
     const objectToString = {
       animal: 'giraffe',
       toString: function () {
@@ -289,7 +363,12 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const node = ReactDOM.render(el, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(el);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
@@ -305,14 +384,17 @@ describe('ReactDOMSelect', () => {
         <option value="gorilla">A gorilla!</option>
       </select>
     );
-    ReactDOM.render(el2, container);
+
+    await act(() => {
+      root.render(el2);
+    });
 
     expect(node.options[0].selected).toBe(true); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should allow switching to multiple', () => {
+  it('should allow switching to multiple', async () => {
     const stub = (
       <select defaultValue="giraffe">
         <option value="monkey">A monkey!</option>
@@ -322,26 +404,31 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
 
-    // When making it multiple, giraffe and gorilla should be selected
-    ReactDOM.render(
-      <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
-        {options}
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
+          {options}
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
   });
 
-  it('should allow switching from multiple', () => {
+  it('should allow switching from multiple', async () => {
     const stub = (
       <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
         <option value="monkey">A monkey!</option>
@@ -351,25 +438,27 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
 
-    // When removing multiple, defaultValue is applied again, being omitted
-    // means that "monkey" will be selected
-    ReactDOM.render(
-      <select defaultValue="gorilla">{options}</select>,
-      container,
-    );
+    await act(() => {
+      root.render(<select defaultValue="gorilla">{options}</select>);
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
   });
 
-  it('does not select an item when size is initially set to greater than 1', () => {
+  it('does not select an item when size is initially set to greater than 1', async () => {
     const stub = (
       <select size="2">
         <option value="monkey">A monkey!</option>
@@ -378,7 +467,13 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const select = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const select = container.firstChild;
 
     expect(select.options[0].selected).toBe(false);
     expect(select.options[1].selected).toBe(false);
@@ -388,7 +483,7 @@ describe('ReactDOMSelect', () => {
     expect(select.selectedIndex).toBe(-1);
   });
 
-  it('should remember value when switching to uncontrolled', () => {
+  it('should remember value when switching to uncontrolled', async () => {
     const stub = (
       <select value={'giraffe'} onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -398,20 +493,27 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
 
-    ReactDOM.render(<select>{options}</select>, container);
+    await act(() => {
+      root.render(<select>{options}</select>);
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should remember updated value when switching to uncontrolled', () => {
+  it('should remember updated value when switching to uncontrolled', async () => {
     const stub = (
       <select value={'giraffe'} onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -421,20 +523,27 @@ describe('ReactDOMSelect', () => {
     );
     const options = stub.props.children;
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(stub);
+    });
 
-    ReactDOM.render(
-      <select value="gorilla" onChange={noop}>
-        {options}
-      </select>,
-      container,
-    );
+    const node = container.firstChild;
+    await act(() => {
+      root.render(
+        <select value="gorilla" onChange={noop}>
+          {options}
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(true); // gorilla
 
-    ReactDOM.render(<select>{options}</select>, container);
+    await act(() => {
+      root.render(<select>{options}</select>);
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
@@ -534,64 +643,71 @@ describe('ReactDOMSelect', () => {
     expect(options[2].selected).toBe(true);
   });
 
-  it('should not control defaultValue if re-adding options', () => {
+  it('should not control defaultValue if re-adding options', async () => {
     const container = document.createElement('div');
 
-    const node = ReactDOM.render(
-      <select multiple={true} defaultValue={['giraffe']}>
-        <option key="monkey" value="monkey">
-          A monkey!
-        </option>
-        <option key="giraffe" value="giraffe">
-          A giraffe!
-        </option>
-        <option key="gorilla" value="gorilla">
-          A gorilla!
-        </option>
-      </select>,
-      container,
-    );
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(
+        <select multiple={true} defaultValue={['giraffe']}>
+          <option key="monkey" value="monkey">
+            A monkey!
+          </option>
+          <option key="giraffe" value="giraffe">
+            A giraffe!
+          </option>
+          <option key="gorilla" value="gorilla">
+            A gorilla!
+          </option>
+        </select>,
+      );
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
 
-    ReactDOM.render(
-      <select multiple={true} defaultValue={['giraffe']}>
-        <option key="monkey" value="monkey">
-          A monkey!
-        </option>
-        <option key="gorilla" value="gorilla">
-          A gorilla!
-        </option>
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} defaultValue={['giraffe']}>
+          <option key="monkey" value="monkey">
+            A monkey!
+          </option>
+          <option key="gorilla" value="gorilla">
+            A gorilla!
+          </option>
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(false); // gorilla
 
-    ReactDOM.render(
-      <select multiple={true} defaultValue={['giraffe']}>
-        <option key="monkey" value="monkey">
-          A monkey!
-        </option>
-        <option key="giraffe" value="giraffe">
-          A giraffe!
-        </option>
-        <option key="gorilla" value="gorilla">
-          A gorilla!
-        </option>
-      </select>,
-      container,
-    );
+    await act(() => {
+      root.render(
+        <select multiple={true} defaultValue={['giraffe']}>
+          <option key="monkey" value="monkey">
+            A monkey!
+          </option>
+          <option key="giraffe" value="giraffe">
+            A giraffe!
+          </option>
+          <option key="gorilla" value="gorilla">
+            A gorilla!
+          </option>
+        </select>,
+      );
+    });
 
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should support options with dynamic children', () => {
+  it('should support options with dynamic children', async () => {
     const container = document.createElement('div');
 
     let node;
@@ -612,38 +728,51 @@ describe('ReactDOMSelect', () => {
       );
     }
 
-    ReactDOM.render(<App value="monkey" />, container);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<App value="monkey" />);
+    });
+
     expect(node.options[0].selected).toBe(true); // monkey
     expect(node.options[1].selected).toBe(false); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
 
-    ReactDOM.render(<App value="giraffe" />, container);
+    await act(() => {
+      root.render(<App value="giraffe" />);
+    });
+
     expect(node.options[0].selected).toBe(false); // monkey
     expect(node.options[1].selected).toBe(true); // giraffe
     expect(node.options[2].selected).toBe(false); // gorilla
   });
 
-  it('should warn if value is null', () => {
-    expect(() =>
-      ReactTestUtils.renderIntoDocument(
-        <select value={null}>
-          <option value="test" />
-        </select>,
-      ),
-    ).toErrorDev(
+  it('should warn if value is null', async () => {
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+    await expect(async () => {
+      await act(() => {
+        root.render(
+          <select value={null}>
+            <option value="test" />
+          </select>,
+        );
+      });
+    }).toErrorDev(
       '`value` prop on `select` should not be null. ' +
         'Consider using an empty string to clear the component or `undefined` ' +
         'for uncontrolled components.',
     );
 
-    ReactTestUtils.renderIntoDocument(
-      <select value={null}>
-        <option value="test" />
-      </select>,
-    );
+    await act(() => {
+      root.render(
+        <select value={null}>
+          <option value="test" />
+        </select>,
+      );
+    });
   });
 
-  it('should warn if selected is set on <option>', () => {
+  it('should warn if selected is set on <option>', async () => {
     function App() {
       return (
         <select>
@@ -653,36 +782,50 @@ describe('ReactDOMSelect', () => {
       );
     }
 
-    expect(() => ReactTestUtils.renderIntoDocument(<App />)).toErrorDev(
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+    await expect(async () => {
+      await act(() => {
+        root.render(<App />);
+      });
+    }).toErrorDev(
       'Use the `defaultValue` or `value` props on <select> instead of ' +
         'setting `selected` on <option>.',
     );
 
-    ReactTestUtils.renderIntoDocument(<App />);
+    await act(() => {
+      root.render(<App />);
+    });
   });
 
-  it('should warn if value is null and multiple is true', () => {
-    expect(() =>
-      ReactTestUtils.renderIntoDocument(
-        <select value={null} multiple={true}>
-          <option value="test" />
-        </select>,
-      ),
-    ).toErrorDev(
+  it('should warn if value is null and multiple is true', async () => {
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+    await expect(async () => {
+      await act(() => {
+        root.render(
+          <select value={null} multiple={true}>
+            <option value="test" />
+          </select>,
+        );
+      });
+    }).toErrorDev(
       '`value` prop on `select` should not be null. ' +
         'Consider using an empty array when `multiple` is ' +
         'set to `true` to clear the component or `undefined` ' +
         'for uncontrolled components.',
     );
 
-    ReactTestUtils.renderIntoDocument(
-      <select value={null} multiple={true}>
-        <option value="test" />
-      </select>,
-    );
+    await act(() => {
+      root.render(
+        <select value={null} multiple={true}>
+          <option value="test" />
+        </select>,
+      );
+    });
   });
 
-  it('should refresh state on change', () => {
+  it('should refresh state on change', async () => {
     const stub = (
       <select value="giraffe" onChange={noop}>
         <option value="monkey">A monkey!</option>
@@ -694,70 +837,111 @@ describe('ReactDOMSelect', () => {
     document.body.appendChild(container);
 
     try {
-      const node = ReactDOM.render(stub, container);
+      const root = ReactDOMClient.createRoot(container);
 
-      node.dispatchEvent(
-        new Event('change', {bubbles: true, cancelable: false}),
-      );
+      await act(() => {
+        root.render(stub);
+      });
+
+      const node = container.firstChild;
+
+      await act(() => {
+        node.dispatchEvent(
+          new Event('change', {bubbles: true, cancelable: false}),
+        );
+      });
 
       expect(node.value).toBe('giraffe');
     } finally {
       document.body.removeChild(container);
     }
   });
 
-  it('should warn if value and defaultValue props are specified', () => {
-    expect(() =>
-      ReactTestUtils.renderIntoDocument(
-        <select value="giraffe" defaultValue="giraffe" readOnly={true}>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-          <option value="gorilla">A gorilla!</option>
-        </select>,
-      ),
-    ).toErrorDev(
+  it('should warn if value and defaultValue props are specified', async () => {
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+    await expect(async () => {
+      await act(() => {
+        root.render(
+          <select value="giraffe" defaultValue="giraffe" readOnly={true}>
+            <option value="monkey">A monkey!</option>
+            <option value="giraffe">A giraffe!</option>
+            <option value="gorilla">A gorilla!</option>
+          </select>,
+        );
+      });
+    }).toErrorDev(
       'Select elements must be either controlled or uncontrolled ' +
         '(specify either the value prop, or the defaultValue prop, but not ' +
         'both). Decide between using a controlled or uncontrolled select ' +
         'element and remove one of these props. More info: ' +
         'https://reactjs.org/link/controlled-components',
     );
 
-    ReactTestUtils.renderIntoDocument(
-      <select value="giraffe" defaultValue="giraffe" readOnly={true}>
-        <option value="monkey">A monkey!</option>
-        <option value="giraffe">A giraffe!</option>
-        <option value="gorilla">A gorilla!</option>
-      </select>,
-    );
+    await act(() => {
+      root.render(
+        <select value="giraffe" defaultValue="giraffe" readOnly={true}>
+          <option value="monkey">A monkey!</option>
+          <option value="giraffe">A giraffe!</option>
+          <option value="gorilla">A gorilla!</option>
+        </select>,
+      );
+    });
   });
 
-  it('should not warn about missing onChange in uncontrolled textareas', () => {
+  it('should not warn about missing onChange in uncontrolled textareas', async () => {
     const container = document.createElement('div');
-    ReactDOM.render(<select />, container);
-    ReactDOM.unmountComponentAtNode(container);
-    ReactDOM.render(<select value={undefined} />, container);
+    let root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(<select />);
+    });
+
+    await act(() => {
+      root.unmount();
+    });
+    root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(<select value={undefined} />);
+    });
   });
 
-  it('should be able to safely remove select onChange', () => {
-    function changeView() {
-      ReactDOM.unmountComponentAtNode(container);
+  it('should be able to safely remove select onChange', async () => {
+    const container = document.createElement('div');
+    const root = ReactDOMClient.createRoot(container);
+    async function changeView() {
+      await act(() => {
+        root.unmount();
+      });
     }
 
-    const container = document.createElement('div');
     const stub = (
       <select value="giraffe" onChange={changeView}>
         <option value="monkey">A monkey!</option>
         <option value="giraffe">A giraffe!</option>
         <option value="gorilla">A gorilla!</option>
       </select>
     );
-    const node = ReactDOM.render(stub, container);
 
-    expect(() => ReactTestUtils.Simulate.change(node)).not.toThrow();
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
+
+    await expect(
+      act(() => {
+        node.dispatchEvent(
+          new Event('change', {bubbles: true, cancelable: false}),
+        );
+      }),
+    ).resolves.not.toThrow();
+
+    expect(container.firstChild).toBe(null);
   });
 
-  it('should select grandchild options nested inside an optgroup', () => {
+  it('should select grandchild options nested inside an optgroup', async () => {
     const stub = (
       <select value="b" onChange={noop}>
         <optgroup label="group">
@@ -768,14 +952,20 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // a
     expect(node.options[1].selected).toBe(true); // b
     expect(node.options[2].selected).toBe(false); // c
   });
 
-  it('should allow controlling `value` in a nested render', () => {
+  it('should allow controlling `value` in a nested legacy render', async () => {
     let selectNode;
 
     class Parent extends React.Component {
@@ -839,7 +1029,7 @@ describe('ReactDOMSelect', () => {
     document.body.removeChild(container);
   });
 
-  it('should not select first option by default when multiple is set and no defaultValue is set', () => {
+  it('should not select first option by default when multiple is set and no defaultValue is set', async () => {
     const stub = (
       <select multiple={true} onChange={noop}>
         <option value="a">a</option>
@@ -848,180 +1038,228 @@ describe('ReactDOMSelect', () => {
       </select>
     );
     const container = document.createElement('div');
-    const node = ReactDOM.render(stub, container);
+    const root = ReactDOMClient.createRoot(container);
+
+    await act(() => {
+      root.render(stub);
+    });
+
+    const node = container.firstChild;
 
     expect(node.options[0].selected).toBe(false); // a
     expect(node.options[1].selected).toBe(false); // b
     expect(node.options[2].selected).toBe(false); // c
   });
 
   describe('When given a Symbol value', () => {
-    it('treats initial Symbol value as missing', () => {
-      let node;
-
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={Symbol('foobar')}>
-            <option value={Symbol('foobar')}>A Symbol!</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
+    it('treats initial Symbol value as missing', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select onChange={noop} value={Symbol('foobar')}>
+              <option value={Symbol('foobar')}>A Symbol!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
       }).toErrorDev('Invalid value for prop `value`');
 
+      const node = container.firstChild;
       expect(node.value).toBe('A Symbol!');
     });
 
-    it('treats updated Symbol value as missing', () => {
-      let node;
+    it('treats updated Symbol value as missing', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select onChange={noop} value="monkey">
+              <option value={Symbol('foobar')}>A Symbol!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev('Invalid value for prop `value`');
 
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value="monkey">
+      let node = container.firstChild;
+      expect(node.value).toBe('monkey');
+
+      await act(() => {
+        root.render(
+          <select onChange={noop} value={Symbol('foobar')}>
             <option value={Symbol('foobar')}>A Symbol!</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      }).toErrorDev('Invalid value for prop `value`');
-
-      expect(node.value).toBe('monkey');
+      });
 
-      node = ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} value={Symbol('foobar')}>
-          <option value={Symbol('foobar')}>A Symbol!</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
+      node = container.firstChild;
 
       expect(node.value).toBe('A Symbol!');
     });
 
-    it('treats initial Symbol defaultValue as an empty string', () => {
-      let node;
-
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select defaultValue={Symbol('foobar')}>
-            <option value={Symbol('foobar')}>A Symbol!</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
+    it('treats initial Symbol defaultValue as an empty string', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select defaultValue={Symbol('foobar')}>
+              <option value={Symbol('foobar')}>A Symbol!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
       }).toErrorDev('Invalid value for prop `value`');
 
+      const node = container.firstChild;
       expect(node.value).toBe('A Symbol!');
     });
 
-    it('treats updated Symbol defaultValue as an empty string', () => {
-      let node;
+    it('treats updated Symbol defaultValue as an empty string', async () => {
+      let container = document.createElement('div');
+      let root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select defaultValue="monkey">
+              <option value={Symbol('foobar')}>A Symbol!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev('Invalid value for prop `value`');
+
+      let node = container.firstChild;
+      expect(node.value).toBe('monkey');
 
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select defaultValue="monkey">
+      container = document.createElement('div');
+      root = ReactDOMClient.createRoot(container);
+      await act(() => {
+        root.render(
+          <select defaultValue={Symbol('foobar')}>
             <option value={Symbol('foobar')}>A Symbol!</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      }).toErrorDev('Invalid value for prop `value`');
-
-      expect(node.value).toBe('monkey');
-
-      node = ReactTestUtils.renderIntoDocument(
-        <select defaultValue={Symbol('foobar')}>
-          <option value={Symbol('foobar')}>A Symbol!</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
+      });
 
+      node = container.firstChild;
       expect(node.value).toBe('A Symbol!');
     });
   });
 
   describe('When given a function value', () => {
-    it('treats initial function value as missing', () => {
-      let node;
-
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={() => {}}>
-            <option value={() => {}}>A function!</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
+    it('treats initial function value as missing', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select onChange={noop} value={() => {}}>
+              <option value={() => {}}>A function!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
       }).toErrorDev('Invalid value for prop `value`');
 
+      const node = container.firstChild;
       expect(node.value).toBe('A function!');
     });
 
-    it('treats initial function defaultValue as an empty string', () => {
-      let node;
-
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select defaultValue={() => {}}>
-            <option value={() => {}}>A function!</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
+    it('treats initial function defaultValue as an empty string', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select defaultValue={() => {}}>
+              <option value={() => {}}>A function!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
       }).toErrorDev('Invalid value for prop `value`');
 
+      const node = container.firstChild;
       expect(node.value).toBe('A function!');
     });
 
-    it('treats updated function value as an empty string', () => {
-      let node;
+    it('treats updated function value as an empty string', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select onChange={noop} value="monkey">
+              <option value={() => {}}>A function!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev('Invalid value for prop `value`');
 
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value="monkey">
+      let node = container.firstChild;
+      expect(node.value).toBe('monkey');
+
+      await act(() => {
+        root.render(
+          <select onChange={noop} value={() => {}}>
             <option value={() => {}}>A function!</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      }).toErrorDev('Invalid value for prop `value`');
-
-      expect(node.value).toBe('monkey');
-
-      node = ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} value={() => {}}>
-          <option value={() => {}}>A function!</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
+      });
 
+      node = container.firstChild;
       expect(node.value).toBe('A function!');
     });
 
-    it('treats updated function defaultValue as an empty string', () => {
-      let node;
+    it('treats updated function defaultValue as an empty string', async () => {
+      let container = document.createElement('div');
+      let root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select defaultValue="monkey">
+              <option value={() => {}}>A function!</option>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev('Invalid value for prop `value`');
+
+      let node = container.firstChild;
+      expect(node.value).toBe('monkey');
 
-      expect(() => {
-        node = ReactTestUtils.renderIntoDocument(
-          <select defaultValue="monkey">
+      container = document.createElement('div');
+      root = ReactDOMClient.createRoot(container);
+      await act(() => {
+        root.render(
+          <select defaultValue={() => {}}>
             <option value={() => {}}>A function!</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      }).toErrorDev('Invalid value for prop `value`');
+      });
 
-      expect(node.value).toBe('monkey');
-
-      node = ReactTestUtils.renderIntoDocument(
-        <select defaultValue={() => {}}>
-          <option value={() => {}}>A function!</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
+      node = container.firstChild;
 
       expect(node.value).toBe('A function!');
     });
@@ -1039,367 +1277,479 @@ describe('ReactDOMSelect', () => {
       }
     }
 
-    it('throws when given a Temporal.PlainDate-like value (select)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={new TemporalLike()}>
-            <option value="2020-01-01">like a Temporal.PlainDate</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like value (select)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value={new TemporalLike()}>
+                <option value="2020-01-01">like a Temporal.PlainDate</option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).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.',
-      );
+        '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('throws when given a Temporal.PlainDate-like value (option)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value="2020-01-01">
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like value (option)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value="2020-01-01">
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        'The provided `value` attribute is an unsupported type TemporalLike.' +
+          ' This value must be coerced to a string before using it here.',
+      ]);
     });
 
-    it('throws when given a Temporal.PlainDate-like value (both)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={new TemporalLike()}>
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like value (both)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value={new TemporalLike()}>
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        'The provided `value` attribute is an unsupported type TemporalLike.' +
+          ' This value must be coerced to a string before using it here.',
+      ]);
     });
 
-    it('throws with updated Temporal.PlainDate-like value (select)', () => {
-      ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} value="monkey">
-          <option value="2020-01-01">like a Temporal.PlainDate</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={new TemporalLike()}>
+    it('throws with updated Temporal.PlainDate-like value (select)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(
+          <select onChange={noop} value="monkey">
             <option value="2020-01-01">like a Temporal.PlainDate</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+      });
+
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value={new TemporalLike()}>
+                <option value="2020-01-01">like a Temporal.PlainDate</option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).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('throws with updated Temporal.PlainDate-like value (option)', () => {
-      ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} value="2020-01-01">
-          <option value="donkey">like a Temporal.PlainDate</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
+    it('throws with updated Temporal.PlainDate-like value (option)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(
           <select onChange={noop} value="2020-01-01">
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
+            <option value="donkey">like a Temporal.PlainDate</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+      });
+
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value="2020-01-01">
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev(
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
       );
     });
 
-    it('throws with updated Temporal.PlainDate-like value (both)', () => {
-      ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} value="donkey">
-          <option value="donkey">like a Temporal.PlainDate</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={new TemporalLike()}>
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
+    it('throws with updated Temporal.PlainDate-like value (both)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(
+          <select onChange={noop} value="donkey">
+            <option value="donkey">like a Temporal.PlainDate</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+      });
+
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value={new TemporalLike()}>
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        '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('throws when given a Temporal.PlainDate-like defaultValue (select)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} defaultValue={new TemporalLike()}>
-            <option value="2020-01-01">like a Temporal.PlainDate</option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like defaultValue (select)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} defaultValue={new TemporalLike()}>
+                <option value="2020-01-01">like a Temporal.PlainDate</option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).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.',
-      );
+        '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('throws when given a Temporal.PlainDate-like defaultValue (option)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} defaultValue="2020-01-01">
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like defaultValue (option)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} defaultValue="2020-01-01">
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        'The provided `value` attribute is an unsupported type TemporalLike.' +
+          ' This value must be coerced to a string before using it here.',
+      ]);
     });
 
-    it('throws when given a Temporal.PlainDate-like value (both)', () => {
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} defaultValue={new TemporalLike()}>
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-          </select>,
-        );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+    it('throws when given a Temporal.PlainDate-like value (both)', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} defaultValue={new TemporalLike()}>
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        'The provided `value` attribute is an unsupported type TemporalLike.' +
+          ' This value must be coerced to a string before using it here.',
+      ]);
     });
 
-    it('throws with updated Temporal.PlainDate-like defaultValue (select)', () => {
-      ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} defaultValue="monkey">
-          <option value="2020-01-01">like a Temporal.PlainDate</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} defaultValue={new TemporalLike()}>
+    it('throws with updated Temporal.PlainDate-like defaultValue (select)', async () => {
+      let container = document.createElement('div');
+      let root = ReactDOMClient.createRoot(container);
+      await act(() => {
+        root.render(
+          <select onChange={noop} defaultValue="monkey">
             <option value="2020-01-01">like a Temporal.PlainDate</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+      });
+
+      container = document.createElement('div');
+      root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} defaultValue={new TemporalLike()}>
+                <option value="2020-01-01">like a Temporal.PlainDate</option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).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.',
-      );
+        '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('throws with updated Temporal.PlainDate-like defaultValue (both)', () => {
-      ReactTestUtils.renderIntoDocument(
-        <select onChange={noop} defaultValue="monkey">
-          <option value="donkey">like a Temporal.PlainDate</option>
-          <option value="monkey">A monkey!</option>
-          <option value="giraffe">A giraffe!</option>
-        </select>,
-      );
-      const test = () => {
-        ReactTestUtils.renderIntoDocument(
-          <select onChange={noop} value={new TemporalLike()}>
-            <option value={new TemporalLike()}>
-              like a Temporal.PlainDate
-            </option>
+    it('throws with updated Temporal.PlainDate-like defaultValue (both)', async () => {
+      let container = document.createElement('div');
+      let root = ReactDOMClient.createRoot(container);
+
+      await act(() => {
+        root.render(
+          <select onChange={noop} defaultValue="monkey">
+            <option value="donkey">like a Temporal.PlainDate</option>
             <option value="monkey">A monkey!</option>
             <option value="giraffe">A giraffe!</option>
           </select>,
         );
-      };
-      expect(() =>
-        expect(test).toThrowError(new TypeError('prod message')),
-      ).toErrorDev(
+      });
+
+      container = document.createElement('div');
+      root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await expect(
+          act(() => {
+            root.render(
+              <select onChange={noop} value={new TemporalLike()}>
+                <option value={new TemporalLike()}>
+                  like a Temporal.PlainDate
+                </option>
+                <option value="monkey">A monkey!</option>
+                <option value="giraffe">A giraffe!</option>
+              </select>,
+            );
+          }),
+        ).rejects.toThrowError(new TypeError('prod message'));
+      }).toErrorDev([
         'The provided `value` attribute is an unsupported type TemporalLike.' +
           ' This value must be coerced to a string before using it here.',
-      );
+        'The provided `value` attribute is an unsupported type TemporalLike.' +
+          ' This value must be coerced to a string before using it here.',
+      ]);
     });
 
-    it('should not warn about missing onChange if value is not set', () => {
-      expect(() => {
-        ReactTestUtils.renderIntoDocument(
-          <select>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        );
-      }).not.toThrow();
+    it('should not warn about missing onChange if value is not set', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(
+        act(() => {
+          root.render(
+            <select>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        }),
+      ).resolves.not.toThrow();
     });
 
-    it('should not throw an error about missing onChange if value is undefined', () => {
-      expect(() => {
-        ReactTestUtils.renderIntoDocument(
-          <select value={undefined}>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        );
-      }).not.toThrow();
+    it('should not throw an error about missing onChange if value is undefined', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(
+        act(() => {
+          root.render(
+            <select value={undefined}>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        }),
+      ).resolves.not.toThrow();
     });
 
-    it('should not warn about missing onChange if onChange is set', () => {
+    it('should not warn about missing onChange if onChange is set', async () => {
       const change = jest.fn();
-      expect(() => {
-        ReactTestUtils.renderIntoDocument(
-          <select value="monkey" onChange={change}>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        );
-      }).not.toThrow();
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(
+        act(() => {
+          root.render(
+            <select value="monkey" onChange={change}>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        }),
+      ).resolves.not.toThrow();
     });
 
-    it('should not warn about missing onChange if disabled is true', () => {
-      expect(() => {
-        ReactTestUtils.renderIntoDocument(
-          <select value="monkey" disabled={true}>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        );
-      }).not.toThrow();
+    it('should not warn about missing onChange if disabled is true', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(
+        act(() => {
+          root.render(
+            <select value="monkey" disabled={true}>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        }),
+      ).resolves.not.toThrow();
     });
 
-    it('should warn about missing onChange if value is false', () => {
-      expect(() =>
-        ReactTestUtils.renderIntoDocument(
-          <select value={false}>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        ),
-      ).toErrorDev(
+    it('should warn about missing onChange if value is false', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select value={false}>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev(
         'Warning: You provided a `value` prop to a form ' +
           'field without an `onChange` handler. This will render a read-only ' +
           'field. If the field should be mutable use `defaultValue`. ' +
           'Otherwise, set `onChange`.',
       );
     });
 
-    it('should warn about missing onChange if value is 0', () => {
-      expect(() =>
-        ReactTestUtils.renderIntoDocument(
-          <select value={0}>
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        ),
-      ).toErrorDev(
+    it('should warn about missing onChange if value is 0', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select value={0}>
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev(
         'Warning: You provided a `value` prop to a form ' +
           'field without an `onChange` handler. This will render a read-only ' +
           'field. If the field should be mutable use `defaultValue`. ' +
           'Otherwise, set `onChange`.',
       );
     });
 
-    it('should warn about missing onChange if value is "0"', () => {
-      expect(() =>
-        ReactTestUtils.renderIntoDocument(
-          <select value="0">
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        ),
-      ).toErrorDev(
+    it('should warn about missing onChange if value is "0"', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select value="0">
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev(
         'Warning: You provided a `value` prop to a form ' +
           'field without an `onChange` handler. This will render a read-only ' +
           'field. If the field should be mutable use `defaultValue`. ' +
           'Otherwise, set `onChange`.',
       );
     });
 
-    it('should warn about missing onChange if value is ""', () => {
-      expect(() =>
-        ReactTestUtils.renderIntoDocument(
-          <select value="">
-            <option value="monkey">A monkey!</option>
-            <option value="giraffe">A giraffe!</option>
-            <option value="gorilla">A gorilla!</option>
-          </select>,
-        ),
-      ).toErrorDev(
+    it('should warn about missing onChange if value is ""', async () => {
+      const container = document.createElement('div');
+      const root = ReactDOMClient.createRoot(container);
+      await expect(async () => {
+        await act(() => {
+          root.render(
+            <select value="">
+              <option value="monkey">A monkey!</option>
+              <option value="giraffe">A giraffe!</option>
+              <option value="gorilla">A gorilla!</option>
+            </select>,
+          );
+        });
+      }).toErrorDev(
         'Warning: You provided a `value` prop to a form ' +
           'field without an `onChange` handler. This will render a read-only ' +
           'field. If the field should be mutable use `defaultValue`. ' +