Skip to content

Commit 3382867

Browse files
chore: expose User Event in the exports and website (#1410)
* chore: expose User Event in the exports and website * docs: tweaks, add beta notice * chore: anotate fireEvent api * docs: tweaks
1 parent b9a3fb2 commit 3382867

File tree

5 files changed

+54
-37
lines changed

5 files changed

+54
-37
lines changed

src/pure.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export {
1414
export { getDefaultNormalizer } from './matches';
1515
export { renderHook } from './renderHook';
1616
export { screen } from './screen';
17+
export { userEvent } from './user-event';
1718

1819
export type {
1920
RenderOptions,
@@ -23,3 +24,4 @@ export type {
2324
} from './render';
2425
export type { RenderHookOptions, RenderHookResult } from './renderHook';
2526
export type { Config } from './config';
27+
export type { UserEventConfig } from './user-event';

src/user-event/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { setup } from './setup';
33
import { PressOptions } from './press';
44
import { TypeOptions } from './type';
55

6+
export { UserEventConfig } from './setup';
7+
68
export const userEvent = {
79
setup,
810

website/docs/API.md

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,22 @@ title: API
77

88
- [`render`](#render)
99
- [`render` options](#render-options)
10-
- [`wrapper` option](#wrapper-option)
11-
- [`createNodeMock` option](#createnodemock-option)
12-
- [`unstable_validateStringsRenderedWithinText` option](#unstable_validatestringsrenderedwithintext-option)
1310
- [`...queries`](#queries)
14-
- [Example](#example)
1511
- [`update`](#update)
1612
- [`unmount`](#unmount)
1713
- [`debug`](#debug)
18-
- [`message` option](#message-option)
19-
- [`mapProps` option](#mapprops-option)
20-
- [`debug.shallow`](#debugshallow)
2114
- [`toJSON`](#tojson)
2215
- [`root`](#root)
23-
- [`UNSAFE_root`](#unsafe_root)
16+
- [`UNSAFE_root`](#unsaferoot)
2417
- [`screen`](#screen)
2518
- [`cleanup`](#cleanup)
2619
- [`fireEvent`](#fireevent)
2720
- [`fireEvent[eventName]`](#fireeventeventname)
2821
- [`fireEvent.press`](#fireeventpress)
2922
- [`fireEvent.changeText`](#fireeventchangetext)
3023
- [`fireEvent.scroll`](#fireeventscroll)
31-
- [On a `ScrollView`](#on-a-scrollview)
32-
- [On a `FlatList`](#on-a-flatlist)
3324
- [`waitFor`](#waitfor)
34-
- [Using Jest fake timers](#using-jest-fake-timers)
25+
- [Using a React Native version \< 0.71 with Jest fake timers](#using-a-react-native-version--071-with-jest-fake-timers)
3526
- [`waitForElementToBeRemoved`](#waitforelementtoberemoved)
3627
- [`within`, `getQueriesForElement`](#within-getqueriesforelement)
3728
- [`queryBy*` APIs](#queryby-apis)
@@ -40,24 +31,12 @@ title: API
4031
- [`renderHook`](#renderhook)
4132
- [`callback`](#callback)
4233
- [`options` (Optional)](#options-optional)
43-
- [`initialProps`](#initialprops)
44-
- [`wrapper`](#wrapper)
4534
- [`RenderHookResult` object](#renderhookresult-object)
46-
- [`result`](#result)
47-
- [`rerender`](#rerender)
48-
- [`unmount`](#unmount-1)
4935
- [Examples](#examples)
50-
- [With `initialProps`](#with-initialprops)
51-
- [With `wrapper`](#with-wrapper)
5236
- [Configuration](#configuration)
5337
- [`configure`](#configure)
54-
- [`asyncUtilTimeout` option](#asyncutiltimeout-option)
55-
- [`defaultIncludeHiddenElements` option](#defaultincludehiddenelements-option)
56-
- [`defaultDebugOptions` option](#defaultdebugoptions-option)
5738
- [`resetToDefaults()`](#resettodefaults)
5839
- [Environment variables](#environment-variables)
59-
- [`RNTL_SKIP_AUTO_CLEANUP`](#rntl_skip_auto_cleanup)
60-
- [`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`](#rntl_skip_auto_detect_fake_timers)
6140
- [Accessibility](#accessibility)
6241
- [`isHiddenFromAccessibility`](#ishiddenfromaccessibility)
6342

@@ -346,9 +325,16 @@ function fireEvent(
346325
): void {}
347326
```
348327

349-
Fires native-like event with data.
328+
:::note
329+
For common events like `press` or `type` it's recommended to use [User Event API](UserEvent.md) as it offers
330+
more realistic event simulation by emitting a sequence of events with proper event objects that mimic React Native runtime behavior.
331+
332+
Use Fire Event for cases not supported by User Event and for triggering event handlers on composite components.
333+
:::
350334

351-
Invokes a given event handler (whether native or custom) on the element, bubbling to the root of the rendered tree.
335+
`fireEvent` API allows you to trigger all kind of event handlers on both host and composite components. It will try to invoke a single event handler traversing the component tree bottom-up from passed element and trying to find enabled event handler named `onXxx` when `xxx` is the name of the event passed.
336+
337+
Unlike User Event, this API does not automatically pass event object to event handler, this is responsibility of the user to construct such object.
352338

353339
```jsx
354340
import { render, screen, fireEvent } from '@testing-library/react-native';
@@ -402,6 +388,10 @@ Convenience methods for common events like: `press`, `changeText`, `scroll`.
402388
fireEvent.press: (element: ReactTestInstance, ...data: Array<any>) => void
403389
```
404390

391+
:::note
392+
It is recommended to use the User Event [`press()`](UserEvent.md#press) helper instead as it offers more realistic simulation of press interaction, including pressable support.
393+
:::
394+
405395
Invokes `press` event handler on the element or parent element in the tree.
406396

407397
```jsx
@@ -434,6 +424,10 @@ expect(onPressMock).toHaveBeenCalledWith(eventData);
434424
fireEvent.changeText: (element: ReactTestInstance, ...data: Array<any>) => void
435425
```
436426

427+
:::note
428+
It is recommended to use the User Event [`type()`](UserEvent.md#type) helper instead as it offers more realistic simulation of text change interaction, including key-by-key typing, element focus, and other editing events.
429+
:::
430+
437431
Invokes `changeText` event handler on the element or parent element in the tree.
438432

439433
```jsx

website/docs/UserEvent.md

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,31 @@ title: User Event
55

66
### Table of contents
77

8-
- [`userEvent.setup`](#usereventsetup)
8+
- [Comparison with Fire Event API](#comparison-with-fire-event-api)
9+
- [`setup()`](#setup)
910
- [Options](#options)
1011
- [`press()`](#press)
1112
- [`longPress()`](#longpress)
13+
- [Options](#options-1)
1214
- [`type()`](#type)
13-
- [Options:](#options-1)
15+
- [Options](#options-2)
1416
- [Sequence of events](#sequence-of-events)
1517

18+
:::caution
19+
User Event API is in beta stage.
1620

17-
## `userEvent.setup`
21+
This means that we plan to keep the public API signatures to remain stable, but we might introduce breaking behavioural changes, e.g. changing the ordering or timing of emitted events, without a major version update. Hopefully, well written code should not rely on such specific details.
22+
:::
23+
24+
## Comparison with Fire Event API
25+
26+
Fire Event is our original event simulation API. It offers ability to invoke **any event handler** declared on **either host or composite elements**. If the element does not have `onEventName` event handler for passed `eventName` event, or the element is disabled, Fire Event will traverse up the component tree, looking for event handler on both host and composite elements along the way. By default it will **not pass any event data**, but the user might provide it in the last argument.
27+
28+
In contrast, User Event provides realistic event simulation for main user interactions like `press` or `type`. Each of the interactions will trigger a **sequence of events** corresponding to React Native runtime behavior. These events will be invoked **only on host elements**, and **will automatically receive event data** corresponding to each event.
29+
30+
If User Event supports given interaction you should always prefer it over Fire Event counterpart, as it will make your tests much more realistic and hence reliable. In other cases, e.g. when event is not supported by User Event, or when invoking event handlers on composite elements, you have to use Fire Event as the only available option.
31+
32+
## `setup()`
1833

1934
```ts
2035
userEvent.setup(options?: {
@@ -28,11 +43,11 @@ Example
2843
const user = userEvent.setup();
2944
```
3045

31-
Creates User Event instances which can be used to trigger events.
46+
Creates an User Event object instance which can be used to trigger events.
3247

3348
### Options
34-
- `delay` - controls the default delay between subsequent events, e.g. keystrokes, etc.
35-
- `advanceTimers` - time advancement utility function that should be used for fake timers. The default setup handles both real and Jest fake timers.
49+
- `delay` - controls the default delay between subsequent events, e.g. keystrokes.
50+
- `advanceTimers` - time advancement utility function that should be used for fake timers. The default setup handles both real timers and Jest fake timers.
3651

3752

3853
## `press()`
@@ -49,7 +64,7 @@ const user = userEvent.setup();
4964
await user.press(element);
5065
```
5166

52-
This helper simulates a press on any pressable element, e.g. `Pressable`, `TouchableOpacity`, `Text`, `TextInput`, etc. Unlike `fireEvent.press()` which is a simpler API that will only call the `onPress` prop, this simulates the entire press event in a more realistic way by reproducing what really happens when a user presses an interface view. This will trigger additional events like `pressIn` and `pressOut`.
67+
This helper simulates a press on any pressable element, e.g. `Pressable`, `TouchableOpacity`, `Text`, `TextInput`, etc. Unlike `fireEvent.press()` which is a simpler API that will only call the `onPress` prop, this function simulates the entire press interaction in a more realistic way by reproducing event sequence emitted by React Native runtime. This helper will trigger additional events like `pressIn` and `pressOut`.
5368

5469
## `longPress()`
5570

@@ -68,6 +83,9 @@ await user.longPress(element);
6883

6984
Simulates a long press user interaction. In React Native the `longPress` event is emitted when the press duration exceeds long press threshold (by default 500 ms). In other aspects this actions behaves similar to regular `press` action, e.g. by emitting `pressIn` and `pressOut` events. The press duration is customisable through the options. This should be useful if you use the `delayLongPress` prop. When using real timers this will take 500 ms so it is highly recommended to use that API with fake timers to prevent test taking a long time to run.
7085

86+
### Options
87+
- `duration` - duration of the press in miliseconds. Default value is 500 ms.
88+
7189
## `type()`
7290

7391
```ts
@@ -90,7 +108,7 @@ This helper simulates user focusing on `TextInput` element, typing `text` one ch
90108
91109
This function supports only host `TextInput` elements. Passing other element type will result in throwing error.
92110
93-
### Options:
111+
### Options
94112
- `skipPress` - if true, `pressIn` and `pressOut` events will not be triggered.
95113
- `submitEditing` - if true, `submitEditing` event will be triggered after typing the text.
96114
@@ -100,14 +118,14 @@ The sequence of events depends on `multiline` prop, as well as passed options.
100118
101119
Events will not be emitted if `editable` prop is set to `false`.
102120
103-
Entering the element:
121+
**Entering the element**:
104122
- `pressIn` (optional)
105123
- `focus`
106124
- `pressOut` (optional)
107125
108126
The `pressIn` and `pressOut` events are sent by default, but can be skipped by passing `skipPress: true` option.
109127
110-
Typing (for each character):
128+
**Typing (for each character)**:
111129
- `keyPress`
112130
- `textInput` (optional)
113131
- `change`
@@ -116,9 +134,10 @@ Typing (for each character):
116134
117135
The `textInput` event is sent only for mutliline text inputs.
118136
119-
Leaving the element:
137+
**Leaving the element**:
120138
- `submitEditing` (optional)
121139
- `endEditing`
122140
- `blur`
123141
124142
The `submitEditing` event is skipped by default. It can sent by setting `submitEditing: true` option.
143+

website/sidebars.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
22
docs: {
33
Introduction: ['getting-started', 'faq'],
4-
'API Reference': ['api', 'api-queries'],
4+
'API Reference': ['api', 'api-queries', 'user-event'],
55
Guides: [
66
'troubleshooting',
77
'how-should-i-query',

0 commit comments

Comments
 (0)