Skip to content

Commit f30e5e8

Browse files
authored
feat: document user-event v14 (#980)
1 parent e479c7d commit f30e5e8

File tree

11 files changed

+840
-2
lines changed

11 files changed

+840
-2
lines changed

docs/ecosystem-user-event.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
id: ecosystem-user-event
3-
title: user-event
3+
title: user-event v13
44
---
55

66
import Tabs from '@theme/Tabs'
@@ -10,6 +10,10 @@ import TabItem from '@theme/TabItem'
1010
advanced simulation of browser interactions than the built-in
1111
[`fireEvent`](dom-testing-library/api-events.mdx#fireevent) method.
1212

13+
> This page describes `user-event@13.5.0`.
14+
If you are starting or actively working on a project,
15+
we recommend to use [`user-event@14.0.0-beta`](user-event/intro) instead, as it includes important bug fixes and new features.
16+
1317
## Installation
1418

1519
<Tabs defaultValue="npm" values={[{ label: 'npm', value: 'npm' }, { label: 'Yarn', value: 'yarn' }]}>

docs/user-event/api-clipboard.mdx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
id: clipboard
3+
title: Clipboard
4+
---
5+
6+
Note that the
7+
[Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard) is
8+
usually not available outside of secure context.
9+
To enable testing of workflows involving the clipboard,
10+
[`userEvent.setup()`](setup) replaces `window.navigator.clipboard` with a stub.
11+
12+
## copy()
13+
14+
```ts
15+
copy(): Promise<DataTransfer|undefined>
16+
```
17+
18+
Copy the current selection.
19+
20+
If [`writeToClipboard`](options#writetoclipboard) is `true`, this will also
21+
write the data to the `Clipboard`.
22+
23+
## cut()
24+
25+
```ts
26+
cut(): Promise<DataTransfer|undefined>
27+
```
28+
29+
Cut the current selection.
30+
31+
If [`writeToClipboard`](options#writetoclipboard) is `true`, this will also
32+
write the data to the `Clipboard`.
33+
34+
When performed in editable context, it removes the selected content from the
35+
document.
36+
37+
## paste()
38+
39+
```ts
40+
paste(clipboardData?: DataTransfer|string): Promise<void>
41+
```
42+
43+
Paste data into the document.
44+
45+
When called without `clipboardData`, the content to be pasted is read from the
46+
`Clipboard`.
47+
48+
When performed in editable context, the pasted content is inserted into to the
49+
document.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
id: convenience
3+
title: Convenience APIs
4+
---
5+
6+
The following APIs are shortcuts for equivalent calls to the underlying
7+
[`pointer()`](pointer) and [`keyboard()`](keyboard) APIs.
8+
9+
## Clicks
10+
11+
### click()
12+
13+
```ts
14+
click(element: Element): Promise<void>
15+
```
16+
17+
```js
18+
pointer([{target: element}, {keys: '[MouseLeft]', target: element}])
19+
```
20+
21+
The first action might be skipped per [`skipHover`](options#skiphover).
22+
23+
### dblClick()
24+
25+
```ts
26+
dblClick(element: Element): Promise<void>
27+
```
28+
29+
```js
30+
pointer([{target: element}, {keys: '[MouseLeft][MouseLeft]', target: element}])
31+
```
32+
33+
### tripleClick()
34+
35+
```ts
36+
tripleClick(element: Element): Promise<void>
37+
```
38+
39+
```js
40+
pointer([
41+
{target: element},
42+
{keys: '[MouseLeft][MouseLeft][MouseLeft]', target: element},
43+
])
44+
```
45+
46+
## Mouse movement
47+
48+
### hover()
49+
50+
```ts
51+
hover(element: Element): Promise<void>
52+
```
53+
54+
```js
55+
pointer({target: element})
56+
```
57+
58+
### unhover()
59+
60+
```ts
61+
hover(element: Element): Promise<void>
62+
```
63+
64+
```js
65+
pointer({target: element.ownerDocument.body})
66+
```
67+
68+
## Keyboard
69+
70+
### tab()
71+
72+
```ts
73+
tab(options: {shift?: boolean})
74+
```
75+
76+
```js
77+
// without shift
78+
keyboard('{Tab}')
79+
// with shift=true
80+
keyboard('{Shift>}{Tab}{/Shift}')
81+
// with shift=false
82+
keyboard('[/ShiftLeft][/ShiftRight]{Tab}')
83+
```

docs/user-event/api-keyboard.mdx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
id: keyboard
3+
title: Keyboard
4+
---
5+
6+
```ts
7+
keyboard(input: KeyboardInput): Promise<void>
8+
```
9+
10+
The `keyboard` API allows to simulate interactions with a keyboard. It accepts a
11+
`string` describing the key actions.
12+
13+
Keystrokes can be described:
14+
15+
- Per printable character
16+
```js
17+
keyboard('foo') // translates to: f, o, o
18+
```
19+
The brackets `{` and `[` are used as special characters and can be referenced
20+
by doubling them.
21+
```js
22+
keyboard('{{a[[') // translates to: {, a, [
23+
```
24+
- Per
25+
[KeyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
26+
27+
```js
28+
keyboard('{Shift}{f}{o}{o}') // translates to: Shift, f, o, o
29+
```
30+
31+
This does not keep any key pressed. So `Shift` will be lifted before pressing
32+
`f`.
33+
34+
Characters with special meaning inside the key descriptor can be escaped by
35+
prefixing them with a backslash `\`.
36+
37+
```js
38+
keyboard('{}}') // translates to: }
39+
```
40+
41+
- Per
42+
[KeyboardEvent.code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code)
43+
```js
44+
keyboard('[ShiftLeft][KeyF][KeyO][KeyO]') // translates to: Shift, f, o, o
45+
```
46+
47+
Keys can be kept pressed by adding a `>` to the end of the descriptor.
48+
If this should result in repeated `keydown` events, you can add the number of
49+
repetitions.
50+
If the key should also be released after this, add a slash `/` to the end of the
51+
descriptor.
52+
53+
```js
54+
keyboard('{a>}') // press a without releasing it
55+
keyboard('{a>5}') // press a without releasing it and trigger 5 keydown
56+
keyboard('{a>5/}') // press a for 5 keydown and then release it
57+
```
58+
59+
A previously pressed key can be lifted by prefixing the descriptor with `/`.
60+
61+
```js
62+
keyboard('{/a}') // release a previously pressed a
63+
```
64+
65+
This allows to simulate key combinations.
66+
67+
```js
68+
keyboard('{Shift>}A{/Shift}') // translates to: Shift(down), A, Shift(up)
69+
```
70+
71+
The mapping of `key` to `code` is performed by a
72+
[default key map](https://github.com/testing-library/user-event/blob/beta/src/keyboard/keyMap.ts)
73+
portraying a "default" US-keyboard. You can provide your own local keyboard
74+
mapping per [`keyboardMap`](options#keyboardmap) option.
75+
76+
Currently the different `key` meanings of single keys are treated as different
77+
keys.
78+
79+
> Future versions might try to interpolate the modifiers needed to reach a
80+
> printable key on the keyboard. E.g. Automatically pressing `{Shift}` when
81+
> CapsLock is not active and `A` is referenced. If you don't wish this behavior,
82+
> you can deactivate the [`autoModify`](options#automodify) option to opt out
83+
> of this non-breaking change.

docs/user-event/api-pointer.mdx

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
id: pointer
3+
title: Pointer
4+
---
5+
6+
```ts
7+
pointer(input: PointerInput): Promise<void>
8+
```
9+
10+
The `pointer` API allows to simulate interactions with pointer devices. It
11+
accepts a single pointer action or an array of them.
12+
13+
```ts
14+
type PointerInput = PointerActionInput | Array<PointerActionInput>
15+
```
16+
17+
> Our primary target audience tests per `jest` in a `jsdom` environment and there
18+
is no layout in `jsdom`. This means that different from your browser the
19+
elements don't exist in a specific position, layer and size.
20+
We don't try to determine if the pointer action you describe is possible at that
21+
position in your layout.
22+
23+
## Pointer action
24+
25+
There are two types of actions: press and move.
26+
27+
### <a name="press" href="#"/>Pressing a button or touching the screen
28+
29+
A pointer action is a press action if it defines a key to be pressed, to be
30+
released, or both.
31+
32+
```js
33+
pointer({keys: '[MouseLeft]'})
34+
```
35+
36+
You can declare multiple press actions (on the same position) at once which will
37+
be resolved to multiple actions internally. If you don't need to declare any
38+
other properties you can also just supply the `keys` string.
39+
40+
```js
41+
pointer({keys: '[MouseLeft][MouseRight]'})
42+
// or
43+
pointer('[MouseLeft][MouseRight]')
44+
```
45+
46+
In order to press a button without releasing it, the button name is suffixed with
47+
`>`.
48+
For just releasing a previously pressed button, the tag is started with `/`.
49+
50+
```js
51+
pointer('[MouseLeft>]') // press the left mouse button
52+
pointer('[/MouseLeft]') // release the left mouse button
53+
```
54+
55+
Which buttons are available depends on the [`pointerMap`](options#pointermap).
56+
57+
### <a name="move" href="#"/>Moving a pointer
58+
59+
Every pointer action that is not a press action describes a pointer movement.
60+
61+
You can declare which pointer is moved per `pointerName` property. This defaults
62+
to `mouse`.
63+
64+
Note that the `mouse` pointer (`pointerId: 1`) is also the only pointer that
65+
always exists and has a position. A `touch` pointer only exists while the screen
66+
is touched and receives a new `pointerId` every time. For these pointers, we use
67+
the "button" name from the press action as `pointerName`.
68+
69+
```js
70+
pointer([
71+
// touch the screen at element1
72+
{keys: '[TouchA>]', target: element1},
73+
// move the touch pointer to element2
74+
{pointerName: 'TouchA', target: element2},
75+
// release the touch pointer at the last position (element2)
76+
{keys: '[/TouchA]'},
77+
])
78+
```
79+
80+
## Pointer position
81+
82+
### PointerTarget
83+
84+
```ts
85+
interface PointerTarget {
86+
target: Element
87+
coords?: PointerCoords
88+
}
89+
```
90+
91+
The `PointerTarget` props allows to describe the position of the pointer on the
92+
document.
93+
The `coords` you provide are applied as-is to the resulting
94+
[`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) and
95+
can be omitted.
96+
The `target` should be the element receiving the pointer input in the browser.
97+
This is the topmost element that can receive pointer event at those coordinates.
98+
99+
### SelectionTarget
100+
101+
```ts
102+
interface SelectionTarget {
103+
node?: Node
104+
offset?: number
105+
}
106+
```
107+
108+
Pointer actions can alter the selection in the document.
109+
In the browser every pointer position corresponds with a DOM position. This is a
110+
DOM node and a DOM offset which usually translates to the character closest to
111+
the pointer position.
112+
As all character in a no-layout environment are in the same layout position we
113+
assume a pointer position to be closest to the last descendant of the pointer
114+
`target`.
115+
116+
If you provide `offset`, we assume the pointer position to be closest to the
117+
`offset-th` character of `target.textContent`.
118+
119+
If you also provide `node`, we treat `node` and `offset` as the exact DOM
120+
position to be used for any selection.
121+
122+
```jsx
123+
// element: <div><span>foo</span><span>bar</span></div>
124+
// | marking the cursor.
125+
// [ ] marking a selection.
126+
127+
pointer({target: element, offset: 2, keys: '[MouseLeft]'})
128+
// => <div><span>fo|o</span><span>bar</span></div>
129+
130+
pointer([
131+
{target: element, offset: 2, keys: '[MouseLeft>]'},
132+
{offset: 5},
133+
])
134+
// => <div><span>fo[o</span><span>ba]r</span></div>
135+
136+
pointer({target: element, node: element, offset: 1, keys: '[MouseLeft]'})
137+
// => <div><span>foo</span>|<span>bar</span></div>
138+
```

0 commit comments

Comments
 (0)