react-testing-library icon indicating copy to clipboard operation
react-testing-library copied to clipboard

Exception in event handler always results in test failure

Open stefee opened this issue 3 years ago • 6 comments

  • @testing-library/react version: latest
  • Testing Framework and version: Jest (latest)
  • DOM Environment: jsdom
  • Minimal repro: https://github.com/stefee/react-testing-library-repro-1068

I'm finding that when an error is thrown from inside an onClick handler, the test will fail and there's no way for us to assert on the error. I feel like this might be a regression based on this conversation https://github.com/testing-library/react-testing-library/issues/624 (which seems to be about onClick exceptions not resulting in exceptions).

The behavior I'm seeing (exception from within event handler results in unrecoverable error) means we can essentially never throw exceptions inside event handlers, since this makes it impossible for us to test the error handling of our components. This is problematic because some error tracking SDKs like DataDog RUM will treat unhandled exceptions differently to console.error. If we are forced to catch exceptions inside event handlers and log them, rather than allowing them to become unhandled exceptions, this makes it harder to track errors.

Here's an example:

function MyComponent() {
  function onClick() {
    try {
      ... // do something that might throw
    } catch (err) {
      ... // show error toast in the UI

      throw err; // throw err again because we want this to be an unhandled exception from the browser's point of view
    }
  }

  return (
    <button onClick={onClick}>Click Me</button>
  );
}

In this example, we want to be able to test the "show error toast" part in our unit tests, but we can't since the throw err will result in a test failure regardless.

Is the above considered to be bad practice, and we should be logging instead of throwing inside the catch? Or is this an issue with the test library?

stefee avatar May 15 '22 14:05 stefee

I think this is up to you to handle exceptions thrown from event handlers. I don't remember of the top of my hat but this also depends on your testing setup. If you have a minimal, cloneable repository I can take a look since this is also relevant to https://github.com/testing-library/testing-library-docs/issues/1060

eps1lon avatar May 17 '22 19:05 eps1lon

Here's a minimal reproduction: https://github.com/stefee/react-testing-library-repro-1068

stefee avatar May 17 '22 19:05 stefee

Here's the log output from npm test

View log output
> jest

  console.error
    Error: Uncaught [Error: Fail]
        at reportException (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
        at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:343:9)
        at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
        at HTMLUnknownElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
        at HTMLUnknownElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
        at HTMLUnknownElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
        at Object.invokeGuardedCallbackDev (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4210:16)
        at invokeGuardedCallback (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4274:31)
        at invokeGuardedCallbackAndCatchFirstError (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4288:25)
        at executeDispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9038:3) {
      detail: Error: Fail
          at onClick (/Users/stef.jones/src/react-testing-library-repro-1068/Component.spec.jsx:28:15)
          at onClick (/Users/stef.jones/src/react-testing-library-repro-1068/Component.jsx:6:11)
          at HTMLUnknownElement.callCallback (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4161:14)
          at HTMLUnknownElement.callTheUserObjectsOperation (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
          at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
          at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
          at HTMLUnknownElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
          at HTMLUnknownElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLUnknownElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
          at Object.invokeGuardedCallbackDev (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4210:16)
          at invokeGuardedCallback (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4274:31)
          at invokeGuardedCallbackAndCatchFirstError (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4288:25)
          at executeDispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9038:3)
          at processDispatchQueueItemsInOrder (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9070:7)
          at processDispatchQueue (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9083:5)
          at dispatchEventsForPlugins (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9094:3)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9285:12
          at batchedUpdates$1 (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:26096:12)
          at batchedUpdates (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:3988:12)
          at dispatchEventForPluginEventSystem (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9284:3)
          at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6462:5)
          at dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6454:5)
          at dispatchDiscreteEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6427:5)
          at HTMLDivElement.callTheUserObjectsOperation (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
          at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
          at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
          at HTMLButtonElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
          at HTMLButtonElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLButtonElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1708:33
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:79:16
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/act-compat.js:58:24
          at act (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react/cjs/react.development.js:2510:16)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/act-compat.js:57:25
          at Object.eventWrapper (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:78:28)
          at wrapEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1682:39)
          at dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1708:10)
          at dispatchUIEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1717:10)
          at firePointerEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2164:10)
          at fire (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2450:12)
          at up (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2442:9)
          at pointerPress (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2308:7)
          at pointerAction (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2529:33)
          at Object.asyncWrapper (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:71:14)
          at Object.<anonymous> (/Users/stef.jones/src/react-testing-library-repro-1068/Component.spec.jsx:34:3),
      type: 'unhandled exception'
    }

      at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:70:23)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:343:9)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)

  console.error
    Error: Uncaught [Error: Fail]
        at reportException (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
        at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:343:9)
        at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
        at HTMLButtonElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
        at HTMLButtonElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
        at HTMLButtonElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
        at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1708:33
        at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:79:16
        at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/act-compat.js:58:24
        at act (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react/cjs/react.development.js:2510:16) {
      detail: Error: Fail
          at onClick (/Users/stef.jones/src/react-testing-library-repro-1068/Component.spec.jsx:28:15)
          at onClick (/Users/stef.jones/src/react-testing-library-repro-1068/Component.jsx:6:11)
          at HTMLUnknownElement.callCallback (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4161:14)
          at HTMLUnknownElement.callTheUserObjectsOperation (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
          at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
          at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
          at HTMLUnknownElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
          at HTMLUnknownElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLUnknownElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
          at Object.invokeGuardedCallbackDev (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4210:16)
          at invokeGuardedCallback (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4274:31)
          at invokeGuardedCallbackAndCatchFirstError (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:4288:25)
          at executeDispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9038:3)
          at processDispatchQueueItemsInOrder (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9070:7)
          at processDispatchQueue (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9083:5)
          at dispatchEventsForPlugins (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9094:3)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9285:12
          at batchedUpdates$1 (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:26096:12)
          at batchedUpdates (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:3988:12)
          at dispatchEventForPluginEventSystem (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:9284:3)
          at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6462:5)
          at dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6454:5)
          at dispatchDiscreteEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react-dom/cjs/react-dom.development.js:6427:5)
          at HTMLDivElement.callTheUserObjectsOperation (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
          at innerInvokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
          at invokeEventListeners (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
          at HTMLButtonElementImpl._dispatch (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
          at HTMLButtonElementImpl.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
          at HTMLButtonElement.dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1708:33
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:79:16
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/act-compat.js:58:24
          at act (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/react/cjs/react.development.js:2510:16)
          at /Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/act-compat.js:57:25
          at Object.eventWrapper (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:78:28)
          at wrapEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1682:39)
          at dispatchEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1708:10)
          at dispatchUIEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:1717:10)
          at firePointerEvent (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2164:10)
          at fire (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2450:12)
          at up (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2442:9)
          at pointerPress (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2308:7)
          at pointerAction (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/user-event/dist/index.cjs:2529:33)
          at Object.asyncWrapper (/Users/stef.jones/src/react-testing-library-repro-1068/node_modules/@testing-library/react/dist/pure.js:71:14)
          at Object.<anonymous> (/Users/stef.jones/src/react-testing-library-repro-1068/Component.spec.jsx:34:3),
      type: 'unhandled exception'
    }

      at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:70:23)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:343:9)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
      at HTMLButtonElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
      at HTMLButtonElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)

 FAIL  ./Component.spec.jsx
  ✓ should not call the error handler if an error is not thrown (93 ms)
  ✕ should call the error handler if an error is thrown (65 ms)

  ● should call the error handler if an error is thrown

    Fail

      26 |       onClick={() => {
      27 |         // ❌ throw error
    > 28 |         throw new Error("Fail");
         |               ^
      29 |       }}
      30 |       handleError={handleError}
      31 |     />

      at onClick (Component.spec.jsx:28:15)
      at onClick (Component.jsx:6:11)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:4161:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:4210:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4274:31)
      at invokeGuardedCallbackAndCatchFirstError (node_modules/react-dom/cjs/react-dom.development.js:4288:25)
      at executeDispatch (node_modules/react-dom/cjs/react-dom.development.js:9038:3)
      at processDispatchQueueItemsInOrder (node_modules/react-dom/cjs/react-dom.development.js:9070:7)
      at processDispatchQueue (node_modules/react-dom/cjs/react-dom.development.js:9083:5)
      at dispatchEventsForPlugins (node_modules/react-dom/cjs/react-dom.development.js:9094:3)
      at node_modules/react-dom/cjs/react-dom.development.js:9285:12
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:26096:12)
      at batchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:3988:12)
      at dispatchEventForPluginEventSystem (node_modules/react-dom/cjs/react-dom.development.js:9284:3)
      at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (node_modules/react-dom/cjs/react-dom.development.js:6462:5)
      at dispatchEvent (node_modules/react-dom/cjs/react-dom.development.js:6454:5)
      at dispatchDiscreteEvent (node_modules/react-dom/cjs/react-dom.development.js:6427:5)
      at HTMLDivElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:340:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:276:3)
      at HTMLButtonElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:223:9)
      at HTMLButtonElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLButtonElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
      at node_modules/@testing-library/user-event/dist/index.cjs:1708:33
      at node_modules/@testing-library/react/dist/pure.js:79:16
      at node_modules/@testing-library/react/dist/act-compat.js:58:24
      at act (node_modules/react/cjs/react.development.js:2510:16)
      at node_modules/@testing-library/react/dist/act-compat.js:57:25
      at Object.eventWrapper (node_modules/@testing-library/react/dist/pure.js:78:28)
      at wrapEvent (node_modules/@testing-library/user-event/dist/index.cjs:1682:39)
      at dispatchEvent (node_modules/@testing-library/user-event/dist/index.cjs:1708:10)
      at dispatchUIEvent (node_modules/@testing-library/user-event/dist/index.cjs:1717:10)
      at firePointerEvent (node_modules/@testing-library/user-event/dist/index.cjs:2164:10)
      at fire (node_modules/@testing-library/user-event/dist/index.cjs:2450:12)
      at up (node_modules/@testing-library/user-event/dist/index.cjs:2442:9)
      at pointerPress (node_modules/@testing-library/user-event/dist/index.cjs:2308:7)
      at pointerAction (node_modules/@testing-library/user-event/dist/index.cjs:2529:33)
      at Object.asyncWrapper (node_modules/@testing-library/react/dist/pure.js:71:14)
      at Object.<anonymous> (Component.spec.jsx:34:3)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        1.703 s
Ran all test suites.

stefee avatar May 17 '22 19:05 stefee

I am having this issue. Any news on this?

incompl avatar Jun 30 '22 23:06 incompl

@stefee it looks like the reproduction link isn't working, any chance you can have a look please? @incompl do you have a cloneable reproduction so we'll be able to investigate?

MatanBobi avatar Jul 01 '22 04:07 MatanBobi

@MatanBobi I just fixed the link, had it set as private by mistake. 🥇

stefee avatar Jul 01 '22 08:07 stefee

@stefee sorry it took me some time to get to this. I saw the reproduction and I'm leaning towards saying that this should be handled in the user land as part of an ErrorBoundary since we wouldn't want these errors to be left unhandled in our app. What's the use case to not wrap it in a test ErrorBoundary that will present the thrown error?

MatanBobi avatar Oct 10 '22 12:10 MatanBobi

Thanks @MatanBobi.

My understanding of ErrorBoundary is it's to handle errors thrown during the render critical path, not thrown from event callbacks. Is that not correct?

Source: https://reactjs.org/docs/error-boundaries.html#how-about-event-handlers

stefee avatar Oct 10 '22 13:10 stefee

You are correct, but they just recommend you to catch the error inside the event handler. Once you decide not to catch it and throw it, if I'm not mistaken, it will be caught in an ErrorBoundary.

MatanBobi avatar Oct 10 '22 13:10 MatanBobi

Once you decide not to catch it and throw it, if I'm not mistaken, it will be caught in an ErrorBoundary.

This is not my understanding. If an error is thrown from within an event handler and is not wrapped in try/catch then the only result of this is an error log appearing in the console, just like how in regular JavaScript event callbacks in the browser will not affect execution of other code.

This will not be sent to an ErrorBoundary for the reason stated in the docs:

React doesn’t need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle methods, the event handlers don’t happen during rendering. So if they throw, React still knows what to display on the screen.

Note also the docs says:

If you need to catch an error inside an event handler, use the regular JavaScript try / catch

This is not considered to be a requirement or recommendation by default, it's only necessary to catch errors in an event handler if you need to for showing feedback to the user or send to an external error tracker.

My opinion is that React in the test environment should behave the same way as React in the browser, and so throwing an error in an event handler should not cause fireEvent to fail in tests.

stefee avatar Oct 10 '22 13:10 stefee

This was also explained by @eps1lon here https://github.com/testing-library/react-testing-library/issues/624#issuecomment-605105191

stefee avatar Oct 10 '22 13:10 stefee

@eps1lon I think it is a difficult topic if throwing in event handlers should be handled as errors of test cases, and it is so nice if we can also handle as passing of test cases.

Could you consider adding a feature like this?

import { render } from '@testing-library/react'

render(ui, { failIfEventHandlerThrows: false })

bigen1925 avatar Jan 05 '24 05:01 bigen1925