title: Jest test `expect().toThrowError()` passes but still logs an uncaught error to the console
body: <p>I'm using Jest and react-testing-library to test a &quot;modal&quot; component in a &quot;portal&quot; that needs to me mounted to a DOM node. This DOM node is configurable but defaults to <code>body</code>. To get proper test coverage I pass it a bad value too, which should lead to an Error. I'm trying to assert this happens and catch the Error by using the <code>expect().toThrowError()</code> API, this works just fine. However, in the logs I still see an uncaught error printed. I think this maybe caused by the React library printing it before raising the same exception again, but that doesn't mean I can prevent it I guess.</p>
  <p>I could just return a fallback error message, in the UI, but I feel like this is not how this should work.</p>
  <p>Any suggestions on how to fix this, or even a suggestion to just take an entirely different approach?</p>
  <pre class="lang-js prettyprint-override"><code>// modal.js
  import React, { useEffect } from 'react';
  import ReactDOM from 'react-dom';
  
  export interface ModalProps {
    children: React.ReactNode;
    DOMNodeSelector?: string;
  }
  
  export const Modal: React.FC&lt;ModalProps&gt; = ({
    children,
    DOMNodeSelector = 'body',
  }) =&gt; {
    const wrapper = document.createElement('div');
    wrapper.classList.add('modal-wrapper');
  
    // Mount and unmount the modal in the portal
    useEffect(() =&gt; {
      const portal = document.querySelector(DOMNodeSelector);
      if (!portal)
        throw new Error(`Querying &quot;${DOMNodeSelector}&quot; did not yield a DOM node`);
      portal.appendChild(wrapper);
      return () =&gt; {
        portal.removeChild(wrapper);
      };
    }, []);
  
    return ReactDOM.createPortal(
      &lt;div className=&quot;modal&quot;&gt;{children}&lt;/div&gt;,
      wrapper,
    );
  };
  </code></pre>
  <pre class="lang-js prettyprint-override"><code>//modal.test.js
  import React from 'react';
  import { render } from '@testing-library/react';
  import {Modal} from './modal';
  
  describe('&lt;Modal&gt;', () =&gt; {
  it(`throws an Error when passed a bad dom node selector`, () =&gt; {
      expect(() =&gt; {
        render(
          &lt;Modal DOMNodeSelector=&quot;.badselector&quot;&gt;Hello World!&lt;/Modal&gt;,
        );
      }).toThrowError(/did not yield a dom node/i);
    });
  });
  export default Modal;
  </code></pre>
  <pre><code>console.error
      Error: Uncaught [Error: Querying &quot;.badselector&quot; did not yield a DOM node]
          at reportException (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24)
          at innerInvokeEventListeners (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9)
          at invokeEventListeners (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
          at HTMLUnknownElementImpl._dispatch (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
          at HTMLUnknownElementImpl.dispatchEvent (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLUnknownElement.dispatchEvent (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
          at Object.invokeGuardedCallbackDev (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:3994:16)
          at invokeGuardedCallback (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
          at flushPassiveEffectsImpl (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:23574:9)
          at unstable_runWithPriority (/workspaces/project/node_modules/.pnpm/scheduler@0.20.1/node_modules/scheduler/cjs/scheduler.development.js:646:12) Error: Querying &quot;.badselector&quot; did not yield a DOM node
          at /workspaces/project/src/modal.tsx:20:13
          at invokePassiveEffectCreate (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:23487:20)
          at HTMLUnknownElement.callCallback (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:3945:14)
          at HTMLUnknownElement.callTheUserObjectsOperation (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
          at innerInvokeEventListeners (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:318:25)
          at invokeEventListeners (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
          at HTMLUnknownElementImpl._dispatch (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
          at HTMLUnknownElementImpl.dispatchEvent (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLUnknownElement.dispatchEvent (/workspaces/project/node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
          at Object.invokeGuardedCallbackDev (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:3994:16)
          at invokeGuardedCallback (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
          at flushPassiveEffectsImpl (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:23574:9)
          at unstable_runWithPriority (/workspaces/project/node_modules/.pnpm/scheduler@0.20.1/node_modules/scheduler/cjs/scheduler.development.js:646:12)
          at runWithPriority$1 (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:11276:10)
          at flushPassiveEffects (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:23447:14)
          at Object.&lt;anonymous&gt;.flushWork (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom-test-utils.development.js:992:10)
          at act (/workspaces/project/node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1107:9)
          at render (/workspaces/project/node_modules/.pnpm/@testing-library/react@11.2.5_react-dom@17.0.1+react@17.0.1/node_modules/@testing-library/react/dist/pure.js:95:26)
          at /workspaces/project/src/modal.test.tsx:8:7
          at Object.&lt;anonymous&gt; (/workspaces/project/node_modules/.pnpm/expect@26.6.2/node_modules/expect/build/toThrowMatchers.js:83:11)
          at Object.toThrowError (/workspaces/project/node_modules/.pnpm/expect@26.6.2/node_modules/expect/build/index.js:338:21)
          at Object.&lt;anonymous&gt; (/workspaces/project/src/modal.test.tsx:11:8)
          at Object.asyncJestTest (/workspaces/project/node_modules/.pnpm/jest-jasmine2@26.6.3/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
          at /workspaces/project/node_modules/.pnpm/jest-jasmine2@26.6.3/node_modules/jest-jasmine2/build/queueRunner.js:45:12
          at new Promise (&lt;anonymous&gt;)
          at mapper (/workspaces/project/node_modules/.pnpm/jest-jasmine2@26.6.3/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
          at /workspaces/project/node_modules/.pnpm/jest-jasmine2@26.6.3/node_modules/jest-jasmine2/build/queueRunner.js:75:41
          at processTicksAndRejections (node:internal/process/task_queues:93:5)
  
        at VirtualConsole.&lt;anonymous&gt; (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
        at reportException (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:28)
        at innerInvokeEventListeners (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9)
        at invokeEventListeners (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
        at HTMLUnknownElementImpl._dispatch (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
        at HTMLUnknownElementImpl.dispatchEvent (node_modules/.pnpm/jsdom@16.4.0/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
  
    console.error
      The above error occurred in the &lt;Modal&gt; component:
      
          at Modal (/workspaces/project/src/modal.tsx:10:3)
      
      Consider adding an error boundary to your tree to customize error handling behavior.
      Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
  
        at logCapturedError (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:20085:23)
        at update.callback (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:20118:5)
        at callCallback (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:12318:12)
        at commitUpdateQueue (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:12339:9)
        at commitLifeCycles (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:20736:11)
        at commitLayoutEffects (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:23426:7)
        at HTMLUnknownElement.callCallback (node_modules/.pnpm/react-dom@17.0.1_react@17.0.1/node_modules/react-dom/cjs/react-dom.development.js:3945:14)
  </code></pre>