Skip to content

Latest commit

 

History

History
141 lines (109 loc) · 7.28 KB

prefer-user-event.md

File metadata and controls

141 lines (109 loc) · 7.28 KB

Suggest using userEvent library instead of fireEvent for simulating user interaction (testing-library/prefer-user-event)

From testing-library/dom-testing-library#107:

[...] it is becoming apparent the need to express user actions on a web page using a higher-level abstraction than fireEvent

userEvent adds related event calls from browsers to make tests more realistic than its counterpart fireEvent, which is a low-level api.
See the appendix at the end to check how are the events from fireEvent mapped to userEvent.

Rule Details

This rule enforces the usage of userEvent methods over fireEvent. By default, the methods from userEvent take precedence, but you add exceptions by configuring the rule in .eslintrc.

Examples of incorrect code for this rule:

// a method in fireEvent that has a userEvent equivalent
import { fireEvent } from '@testing-library/dom';
// or const { fireEvent } = require('@testing-library/dom');
fireEvent.click(node);

// using fireEvent with an alias
import { fireEvent as fireEventAliased } from '@testing-library/dom';
fireEventAliased.click(node);

// using fireEvent after importing the entire library
import * as dom from '@testing-library/dom';
// or const dom = require(@testing-library/dom');
dom.fireEvent.click(node);

// using fireEvent as a function
import * as dom from '@testing-library/dom';
dom.fireEvent(node, dom.createEvent('click', node));

import { fireEvent, createEvent } from '@testing-library/dom';
const clickEvent = createEvent.click(node);
fireEvent(node, clickEvent);

Examples of correct code for this rule:

import userEvent from '@testing-library/user-event';
// or const userEvent = require('@testing-library/user-event');

// any userEvent method
userEvent.click();

// fireEvent method that does not have an alternative in userEvent
import { fireEvent } from '@testing-library/dom';
// or const { fireEvent } = require('@testing-library/dom');
fireEvent.cut(node);

import * as dom from '@testing-library/dom';
// or const dom = require('@testing-library/dom');
dom.fireEvent.cut(node);

import { fireEvent, createEvent } from '@testing-library/dom';
fireEvent(node, createEvent('cut', node));

Options

This rule allows to exclude specific functions with an equivalent in userEvent through configuration. This is useful if you need to allow an event from fireEvent to be used in the solution. For specific scenarios, you might want to consider disabling the rule inline.

The configuration consists of an array of strings with the names of fireEvents methods to be excluded.
An example looks like this

{
  "rules": {
    "prefer-user-event": [
      "error",
      {
        "allowedMethods": ["click", "change"]
      }
    ]
  }
}

With this configuration example, the following use cases are considered valid

// using a named import
import { fireEvent } from '@testing-library/dom';
// or const { fireEvent } = require('@testing-library/dom');
fireEvent.click(node);
fireEvent.change(node, { target: { value: 'foo' } });

// using fireEvent with an alias
import { fireEvent as fireEventAliased } from '@testing-library/dom';
fireEventAliased.click(node);
fireEventAliased.change(node, { target: { value: 'foo' } });

// using fireEvent after importing the entire library
import * as dom from '@testing-library/dom';
// or const dom = require('@testing-library/dom');
dom.fireEvent.click(node);
dom.fireEvent.change(node, { target: { value: 'foo' } });

When Not To Use It

When you don't want to use userEvent, such as if a legacy codebase is still using fireEvent or you need to have more low-level control over firing events (rather than the recommended approach of testing from a user's perspective)

Further Reading

Appendix

The following table lists all the possible equivalents from the low-level API fireEvent to the higher abstraction API userEvent. All the events not listed here do not have an equivalent (yet)

fireEvent method Possible options in userEvent
click
  • click
  • type
  • selectOptions
  • deselectOptions
change
  • upload
  • type
  • clear
  • selectOptions
  • deselectOptions
dblClick
  • dblClick
input
  • type
  • upload
  • selectOptions
  • deselectOptions
  • paste
keyDown
  • type
  • tab
keyPress
  • type
keyUp
  • type
  • tab
mouseDown
  • click
  • dblClick
  • selectOptions
  • deselectOptions
mouseEnter
  • hover
  • selectOptions
  • deselectOptions
mouseLeave
  • unhover
mouseMove
  • hover
  • unhover
  • selectOptions
  • deselectOptions
mouseOut
  • unhover
mouseOver
  • hover
  • selectOptions
  • deselectOptions
mouseUp
  • click
  • dblClick
  • selectOptions
  • deselectOptions
paste
  • paste
pointerDown
  • click
  • dblClick
  • selectOptions
  • deselectOptions
pointerEnter
  • hover
  • selectOptions
  • deselectOptions
pointerLeave
  • unhover
pointerMove
  • hover
  • unhover
  • selectOptions
  • deselectOptions
pointerOut
  • unhover
pointerOver
  • hover
  • selectOptions
  • deselectOptions
pointerUp
  • click
  • dblClick
  • selectOptions
  • deselectOptions