'TypeError: Cannot read properties of undefined (reading 'click'). fireEvent.click works but userEvent.click does not. Why?

Just started learning React testing with Jest, and am struggling with something simple. When I call userEvent.click(btn), the test fails saying that userEvent.click() is undefined.

import { render, fireEvent, screen } from "@testing-library/react";
import { userEvent } from "@testing-library/user-event";
import '@testing-library/jest-dom';
import '@testing-library/dom'
import { Button } from "./Button";


describe("clicks button", () => {
  it("onclick", () => {
    render(<Button />);
    screen.debug();
    let btn = screen.getByTitle("dummyButton");
    expect(btn.innerHTML).toBe("Click me");
    userEvent.click(btn);
    btn = screen.getByTitle("dummyButton");
    expect(btn.innerHTML).toBe("ButtonClicked");
  });
});
export const Button = () =>{
    const [buttonText, setButtonText] = useState("Click me")
    const handleClick = () =>{
        setButtonText("ButtonClicked")
    }
    return(
        <div>
            <button onClick={handleClick} title="dummyButton">{buttonText}</button>
        </div>
    )
}


  ● clicks button › onclick

    TypeError: Cannot read properties of undefined (reading 'click')

      17 |     let btn = screen.getByTitle("dummyButton");
      18 |     expect(btn.innerHTML).toBe("Click me");
    > 19 |     userEvent.click(btn);
         |               ^
      20 |     btn = screen.getByTitle("dummyButton");
      21 |     expect(btn.innerHTML).toBe("ButtonClicked");
      22 |   });

      at Object.<anonymous> (src/Components/Button/Button.test.js:19:15)


Solution 1:[1]

Seems like it's a default export based on the docs:

import userEvent from '@testing-library/user-event'

can you update your import and try again?

Solution 2:[2]

What fixed it for me was npm install @testing-library/[email protected]

The User Event has a lot of problems IMO and hasn't been perfected. I had to downgrade my npm version to get it to work.

Solution 3:[3]

Try the below code. I have changed "it" to an async arrow function and added await before userEvent. This works for me. Also do a default import at the top.

describe("clicks button", () => {
  it("onclick", async () => {
    render(<Button />);
    screen.debug();
    let btn = screen.getByTitle("dummyButton");
    expect(btn.innerHTML).toBe("Click me");
    await userEvent.click(btn);
    btn = screen.getByTitle("dummyButton");
    expect(btn.innerHTML).toBe("ButtonClicked");
  });
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 sculs
Solution 2 Evan Erickson
Solution 3