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

userEvent.click() behavior is inconsistent with browser when onPointerDown prevents default #1211

Open
githorse opened this issue Apr 18, 2024 · 0 comments

Comments

@githorse
Copy link

githorse commented Apr 18, 2024

  • @testing-library/dom 9.3.4
  • vitest 1.5.0
  • jest-environment-jsdom 27.5.1
  • node 20.12.2

The behavior of userEvent.click() is inconsistent with what happens in the browser under the specific condition when I preventDefault inside onPointerDown:

test("clicking doesn't work :(", async () => {
  const user = userEvent.setup()
  const spy = vi.fn(() => console.log('clicked!'))
  render(
    <Button
      data-testid='clickme'
      onClick={spy}
      onPointerDown={(e) => {
        e.preventDefault()  // <-- the problem
      }}
    >
      Click Me
    </Button>
  )
  await user.click(screen.getByTestId('clickme'))
  expect(spy).toHaveBeenCalledOnce() // ✗ fails
})

If I comment out the problematic line (e.preventDefault()), the test passes:

test("clicking works :)", async () => {
  const user = userEvent.setup()
  const spy = vi.fn(() => console.log('clicked!'))
  render(
    <Button
      data-testid='clickme'
      onClick={spy}
      onPointerDown={() => {
        // e.preventDefault()  <-- ok
      }}
    >
      Click Me
    </Button>
  )
  await user.click(screen.getByTestId('clickme'))
  expect(spy).toHaveBeenCalledOnce() // ✔️ passes
})

If I use fireEvent instead of userEvent, it works:

test("clicking works :)", async () => {
  const spy = vi.fn(() => console.log('clicked!'))
  render(
    <Button
      data-testid='clickme'
      onClick={spy}
      onPointerDown={(e) => {
        e.preventDefault()
      }}
    >
      Click Me
    </Button>
  )
  fireEvent.click(screen.getByTestId('clickme')) // <-- ok
  expect(spy).toHaveBeenCalledOnce() // ✔️ passes
})

If I use onMouseDown instead of onPointerDown, it's also ok:

test("clicking works :)", async () => {
  const user = userEvent.setup()
  const spy = vi.fn(() => console.log('clicked!'))
  render(
    <Button
      data-testid='clickme'
      onClick={spy}
      onMouseDown={(e) => {  // <-- ok
        e.preventDefault()
      }}
    >
      Click Me
    </Button>
  )
  await user.click(screen.getByTestId('clickme'))
  expect(spy).toHaveBeenCalledOnce() // ✔️ passes
})

More importantly, if I put this exact same button on the page and click it (in Chrome 123.0.6312.124), it works fine; the onClick fires as expected.

<Button
  onClick={() => console.log('clicked!')}  // <-- ok
  onPointerDown={(e) => {
    e.preventDefault()
  }}
>
  Click Me
</Button>

So userEvent.click() is doing something differently than what seems be happening with the real user interaction.

Leaving aside the question of whether the code inside onPointerDown is a good idea or not (my real code is a little more complicated), why is userEvent doing something different here than what happens in the browser? Is there a workaround?

@MatanBobi MatanBobi transferred this issue from testing-library/dom-testing-library Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant