Utility APIs
The following APIs don't have one-to-one equivalents in a real user interaction. Their behavior is therefore an interpretation how the "perceived" user interaction might be translated to actual events on the DOM.
clear()
clear(element: Element): Promise<void>
This API can be used to easily clear an editable element.
- Focus element
- Select all contents as per browser menu
- Delete contents as per browser menu
test('clear', async () => {
render(<textarea defaultValue="Hello, World!" />)
await userEvent.clear(screen.getByRole('textbox'))
expect(screen.getByRole('textbox')).toHaveValue('')
})
The Promise
is rejected if the element can not be focused or contents can not
be selected.
selectOptions(), deselectOptions()
selectOptions(
element: Element,
values: HTMLElement | HTMLElement[] | string[] | string,
): Promise<void>
deselectOptions(
element: Element,
values: HTMLElement | HTMLElement[] | string[] | string,
): Promise<void>
Select/deselect the given options in an HTMLSelectElement or listbox.
The values
parameter can refer to an option per its value, HTML content or
just provide the element. It also accepts an array of these.
Selecting multiple options and/or deselecting options of
HTMLSelectElement
is only possible if multiple is specified.
test('selectOptions', async () => {
render(
<select multiple>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>,
)
await userEvent.selectOptions(screen.getByRole('listbox'), ['1', 'C'])
expect(screen.getByRole('option', {name: 'A'}).selected).toBe(true)
expect(screen.getByRole('option', {name: 'B'}).selected).toBe(false)
expect(screen.getByRole('option', {name: 'C'}).selected).toBe(true)
})
test('deselectOptions', async () => {
render(
<select multiple>
<option value="1">A</option>
<option value="2" selected>
B
</option>
<option value="3">C</option>
</select>,
)
await userEvent.deselectOptions(screen.getByRole('listbox'), '2')
expect(screen.getByText('B').selected).toBe(false)
})
Note that this API triggers pointer events and is therefore subject to pointerEventsCheck.
type()
type(
element: Element,
text: KeyboardInput,
options?: {
skipClick?: boolean
skipAutoClose?: boolean
initialSelectionStart?: number
initialSelectionEnd?: number
}
): Promise<void>
Type into an input element.
You should use
keyboard()
if you want to just simulate pressing buttons on the keyboard.
You can usetype()
if you just want to conveniently insert some text into an input field or textarea.
- Unless
skipClick
istrue
, click the element. - If
initialSelectionStart
is set, set the selection on the element. IfinitialSelectionEnd
is not set, this results in a collapsed selection. - Type the given
text
perkeyboard()
. - Unless
skipAutoClose
istrue
, release all pressed keys.
test('type into an input field', async () => {
render(<input defaultValue="Hello," />)
const input = screen.getByRole('textbox')
await userEvent.type(input, ' World!')
expect(input).toHaveValue('Hello, World!')
})
upload()
upload(
element: HTMLElement,
fileOrFiles: File | File[],
): Promise<void>
Change a file input as if a user clicked it and selected files in the resulting file upload dialog.
Files that don't match an
accept
property will be automatically discarded, unlessapplyAccept
is set tofalse
.
test('upload file', async () => {
render(
<div>
<label htmlFor="file-uploader">Upload file:</label>
<input id="file-uploader" type="file" />
</div>,
)
const file = new File(['hello'], 'hello.png', {type: 'image/png'})
const input = screen.getByLabelText(/upload file/i)
await userEvent.upload(input, file)
expect(input.files[0]).toBe(file)
expect(input.files.item(0)).toBe(file)
expect(input.files).toHaveLength(1)
})
test('upload multiple files', async () => {
render(
<div>
<label htmlFor="file-uploader">Upload file:</label>
<input id="file-uploader" type="file" multiple />
</div>,
)
const files = [
new File(['hello'], 'hello.png', {type: 'image/png'}),
new File(['there'], 'there.png', {type: 'image/png'}),
]
const input = screen.getByLabelText(/upload file/i)
await userEvent.upload(input, files)
expect(input.files).toHaveLength(2)
expect(input.files[0]).toBe(files[0])
expect(input.files[1]).toBe(files[1])
})