React testing library differences between clicks using userEvent, fireEvent and regular clicks

In the course of learning TDD with React, I noticed that there are different ways to trigger a click on an element in the test. It can be done through fireEvent.click(), userEvent.click() and HTML_ELEMENT.click().

They all work fine. After doing some research, I understood that userEvent.click() basically uses fireEvent under the hood, and it is preferable for automated tests (e.g. cypress), while the fireEvent.click() is more preferable in unit tests.

But I could not find what both userEvent and fireEvent differ from the regular HTML_ELEMENT.click() function that can be used.

What benefits do I gain from using them instead of using the regular click function?

1 answer

  • answered 2021-01-15 12:05 Taghi Khavari

    I think the fireEvent.click() only emits onClick which on the other hand userEvent.click() emits all sort of events which when user clicks will happen.

    here is one of the functions which will trigger when a labeled is clicked:

    function clickLabel(label, init, {clickCount}) {
      if (isLabelWithInternallyDisabledControl(label)) return
    
      fireEvent.pointerDown(label, init)
      fireEvent.mouseDown(
        label,
        getMouseEventOptions('mousedown', init, clickCount),
      )
      fireEvent.pointerUp(label, init)
      fireEvent.mouseUp(label, getMouseEventOptions('mouseup', init, clickCount))
      fireEvent.click(label, getMouseEventOptions('click', init, clickCount))
      // clicking the label will trigger a click of the label.control
      // however, it will not focus the label.control so we have to do it
      // ourselves.
      if (label.control) focus(label.control)
    }
    

    so in a nutshell fireEvent.click is one the steps that are used in userEvent.click and there are more steps

    you can read the source code here: https://github.com/testing-library/user-event/blob/master/src/click.js

    here are some more code from source code which will happen on userEvent.click

    function clickElement(element, init, {clickCount}) {
      const previousElement = getPreviouslyFocusedElement(element)
      fireEvent.pointerDown(element, init)
      if (!element.disabled) {
        const continueDefaultHandling = fireEvent.mouseDown(
          element,
          getMouseEventOptions('mousedown', init, clickCount),
        )
        if (
          continueDefaultHandling &&
          element !== element.ownerDocument.activeElement
        ) {
          if (previousElement && !isFocusable(element)) {
            blur(previousElement, init)
          } else {
            focus(element, init)
          }
        }
      }
      fireEvent.pointerUp(element, init)
      if (!element.disabled) {
        fireEvent.mouseUp(
          element,
          getMouseEventOptions('mouseup', init, clickCount),
        )
        fireEvent.click(element, getMouseEventOptions('click', init, clickCount))
        const parentLabel = element.closest('label')
        if (parentLabel?.control) focus(parentLabel.control, init)
      }
    }