Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in event handler always results in test failure #1068

Closed
stefee opened this issue May 15, 2022 · 14 comments
Closed

Exception in event handler always results in test failure #1068

stefee opened this issue May 15, 2022 · 14 comments

Comments

@stefee
Copy link

stefee commented May 15, 2022

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 #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?

@eps1lon
Copy link
Member

eps1lon commented May 17, 2022

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 testing-library/testing-library-docs#1060

@stefee
Copy link
Author

stefee commented May 17, 2022

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

@stefee
Copy link
Author

stefee commented May 17, 2022

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.

@incompl
Copy link

incompl commented Jun 30, 2022

I am having this issue. Any news on this?

@MatanBobi
Copy link
Member

MatanBobi commented Jul 1, 2022

@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?

@stefee
Copy link
Author

stefee commented Jul 1, 2022

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

@MatanBobi
Copy link
Member

@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?

@stefee
Copy link
Author

stefee commented Oct 10, 2022

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

@MatanBobi
Copy link
Member

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.

@stefee
Copy link
Author

stefee commented Oct 10, 2022

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
Copy link
Author

stefee commented Oct 10, 2022

This was also explained by @eps1lon here #624 (comment)

@eps1lon eps1lon closed this as not planned Won't fix, can't repro, duplicate, stale May 22, 2023
@bigen1925
Copy link

@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 })

@camsteffen
Copy link

I just ran into this. I'm considering using reportError.

https://developer.mozilla.org/en-US/docs/Web/API/reportError

@felix-quotez
Copy link

It would be nice to not demand that event handler have to handle exceptions (in order to get the tests to pass). I even enjoy that errors can "bubble up" all the way to the top where tools like Sentry can be informed about them and report them. This even seems like a good and unified way to do error handling.

@eps1lon It would be nice if you could please reconsider you view on

I think this is up to you to handle exceptions thrown from event handlers.

Some related issues:

For now, I am using this as a workaround which seems to avoid that errors are reaching vitest

it('test', () => {
  (code with one error in event handler)
  process.once('unhandledRejection', () => { /* no op */ }
  (more test code)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants