This rule raises an issue when a promise is passed to a fireEvent method instead of a DOM element.

Why is this an issue?

fireEvent dispatches a DOM event by calling DOM APIs directly on the value passed as its first argument. It expects a resolved DOM element, not a promise.

The asynchronous queries findBy* and findAllBy* return a promise that resolves to an element once it appears in the DOM. Passing that promise to fireEvent without awaiting it hands fireEvent a Promise object, which has none of the DOM methods it tries to call, so the event is never dispatched and the test throws at runtime. This happens whether the query result is passed directly, stored in a variable that still holds the unresolved promise, or built with new Promise(…​). Because the failure is immediate and deterministic rather than a subtle bug, the test is guaranteed to break.

To fix it, resolve the promise before handing it to fireEvent: await the asynchronous query, or use the synchronous getBy* query when the element is already in the DOM.

import { fireEvent, screen } from '@testing-library/react';

test('submits on click', async () => {
  fireEvent.click(screen.findByRole('button', { name: 'Submit' })); // Noncompliant: "findByRole" returns a promise, not a DOM element
});
import { fireEvent, screen } from '@testing-library/react';

test('submits on click', async () => {
  fireEvent.click(await screen.findByRole('button', { name: 'Submit' }));
});

Resources

Documentation