The problem
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
The solution
user-event
tries to simulate the real events that would happen in the browser
as the user interacts with it. For example userEvent.click(checkbox)
would
change the state of the checkbox.
The library is still a work in progress and any help is appreciated.
Installation
With NPM:
npm install @testing-library/user-event --save-dev
With Yarn:
yarn add @testing-library/user-event --dev
Now simply import it in your tests:
import userEvent from "@testing-library/user-event";
// or
var userEvent = require("@testing-library/user-event");
API
click(element)
Clicks element
, depending on what element
is it can have different side
effects.
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
const { getByText, getByTestId } = test("click", () => {
render(
<div>
<label htmlFor="checkbox">Check</label>
<input id="checkbox" data-testid="checkbox" type="checkbox" />
</div>
);
});
userEvent.click(getByText("Check"));
expect(getByTestId("checkbox")).toHaveAttribute("checked", true);
dblClick(element)
Clicks element
twice, depending on what element
is it can have different
side effects.
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
test("double click", () => {
const onChange = jest.fn();
const { getByTestId } = render(
<input type="checkbox" id="checkbox" onChange={onChange} />
);
const checkbox = getByTestId("checkbox");
userEvent.dblClick(checkbox);
expect(onChange).toHaveBeenCalledTimes(2);
expect(checkbox).toHaveProperty("checked", false);
});
type(element, text, [options])
Writes text
inside an <input>
or a <textarea>
.
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
const { getByText } = test("click", () => {
render(<textarea data-testid="email" />);
});
userEvent.type(getByTestId("email"), "Hello, World!");
expect(getByTestId("email")).toHaveAttribute("value", "Hello, World!");
If options.allAtOnce
is true
, type
will write text
at once rather than
one character at the time. false
is the default value.
options.delay
is the number of milliseconds that pass between two characters
are typed. By default it's 0. You can use this option if your component has a
different behavior for fast or slow users.
selectOptions(element, values, [options])
Selects the specified option(s) of a <select>
or a <select multiple>
element.
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
const { getByTestId } = render(
<select multiple data-testid="select-multiple">
<option data-testid="val1" value="1">
1
</option>
<option data-testid="val2" value="2">
2
</option>
<option data-testid="val3" value="3">
3
</option>
</select>
);
userEvent.selectOptions(getByTestId("select-multiple"), ["1", "3"]);
expect(getByTestId("val1").selected).toBe(true);
expect(getByTestId("val2").selected).toBe(false);
expect(getByTestId("val3").selected).toBe(true);
The values
parameter can be either an array of values or a singular scalar
value.
If options.target
parameter is set, it will use its value to extract option to
select.
Contributors
Thanks goes to these wonderful people
(emoji key):
This project follows the
all-contributors
specification. Contributions of any kind welcome!