实用程序 API
以下 API 在实际用户交互中没有一一对应的等效项。
因此,它们的行為是对如何将“感知”的用户交互转换为 DOM 上的实际事件的一种解释。
clear()
clear(element: Element): Promise<void>
此 API 可用于轻松清除可编辑元素。
- 聚焦元素
- 选择所有内容,如同浏览器菜单
- 删除内容,如同浏览器菜单
test('clear', async () => {
const user = userEvent.setup()
render(<textarea defaultValue="Hello, World!" />)
await user.clear(screen.getByRole('textbox'))
expect(screen.getByRole('textbox')).toHaveValue('')
})
如果元素无法聚焦或内容无法选择,则 Promise
会被拒绝。
selectOptions()、deselectOptions()
selectOptions(
element: Element,
values: HTMLElement | HTMLElement[] | string[] | string,
): Promise<void>
deselectOptions(
element: Element,
values: HTMLElement | HTMLElement[] | string[] | string,
): Promise<void>
在 HTMLSelectElement 或 listbox 中选择/取消选择给定的选项。
values
参数可以引用选项的 value、HTML 内容,或者只是提供元素本身。它也可以接受这些参数的数组。
仅当指定了 multiple 时,才可以在
HTMLSelectElement
中选择多个选项和/或取消选择选项。
test('selectOptions', async () => {
const user = userEvent.setup()
render(
<select multiple>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>,
)
await user.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 () => {
const user = userEvent.setup()
render(
<select multiple>
<option value="1">A</option>
<option value="2" selected>
B
</option>
<option value="3">C</option>
</select>,
)
await user.deselectOptions(screen.getByRole('listbox'), '2')
expect(screen.getByText('B').selected).toBe(false)
})
请注意,此 API 触发指针事件,因此会受到 pointerEventsCheck 的影响。
type()
type(
element: Element,
text: KeyboardInput,
options?: {
skipClick?: boolean
skipAutoClose?: boolean
initialSelectionStart?: number
initialSelectionEnd?: number
}
): Promise<void>
在输入元素中输入文字。
如果您只想模拟在键盘上按下按钮,则应使用
keyboard()
。
如果您只想方便地将一些文本插入输入字段或文本区域,则可以使用type()
。
- 除非
skipClick
为true
,否则会单击该元素。 - 如果设置了
initialSelectionStart
,则在元素上设置选择。如果未设置initialSelectionEnd
,则会导致选择折叠。 - 按照
keyboard()
的方式输入给定的text
。 - 除非
skipAutoClose
为true
,否则会释放所有按下的键。
test('type into an input field', async () => {
const user = userEvent.setup()
render(<input defaultValue="Hello," />)
const input = screen.getByRole('textbox')
await user.type(input, ' World!')
expect(input).toHaveValue('Hello, World!')
})
upload()
upload(
element: HTMLElement,
fileOrFiles: File | File[],
): Promise<void>
更改文件输入,就像用户单击它并在结果的文件上传对话框中选择文件一样。
不匹配
accept
属性的文件将被自动丢弃,除非applyAccept
设置为false
。
test('upload file', async () => {
const user = userEvent.setup()
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 user.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 () => {
const user = userEvent.setup()
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 user.upload(input, files)
expect(input.files).toHaveLength(2)
expect(input.files[0]).toBe(files[0])
expect(input.files[1]).toBe(files[1])
})