Skip to content

Commit c6dfc9f

Browse files
committed
refactor: make fireEvent async by default
1 parent 71ea251 commit c6dfc9f

File tree

6 files changed

+66
-45
lines changed

6 files changed

+66
-45
lines changed

.gemini/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"context": {
3-
"contextFileName": "AGENTS.md"
3+
"contextFileName": "AGENTS.md"
44
}
5-
}
5+
}

AGENTS.md

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,43 @@ This document provides context for the Gemini code assistant to understand the `
66

77
`@testing-library/react-native` (RNTL) provides a set of utilities for testing React Native components. It is designed to facilitate writing tests that resemble how users interact with the application, avoiding implementation details.
88

9-
* **Core Principle:** "The more your tests resemble the way your software is used, the more confidence they can give you."
10-
* **Tech Stack:** TypeScript, React Native, Jest.
11-
* **Architecture:** The library simulates the React Native runtime on top of `universal-test-renderer`.
9+
- **Core Principle:** "The more your tests resemble the way your software is used, the more confidence they can give you."
10+
- **Tech Stack:** TypeScript, React Native, Jest.
11+
- **Architecture:** The library simulates the React Native runtime on top of `universal-test-renderer`.
1212

1313
## Building and Running
1414

1515
The project uses `yarn` for dependency management and script execution.
1616

17-
* **Installation:** `yarn install`
18-
* **Run Tests:** `yarn test` (Runs Jest)
19-
* **Run Tests (CI):** `yarn test:ci` (Runs Jest with worker limits)
20-
* **Lint Code:** `yarn lint` (Runs ESLint on `src`)
21-
* **Type Check:** `yarn typecheck` (Runs TypeScript compiler)
22-
* **Format Check:** `yarn prettier`
23-
* **Validate All:** `yarn validate` (Runs Prettier, ESLint, Typecheck, and Tests in sequence)
24-
* **Build Project:** `yarn build` (Cleans, builds JS with Babel, builds TS types, and copies Flow types)
17+
- **Installation:** `yarn install`
18+
- **Run Tests:** `yarn test` (Runs Jest)
19+
- **Run Tests (CI):** `yarn test:ci` (Runs Jest with worker limits)
20+
- **Lint Code:** `yarn lint` (Runs ESLint on `src`)
21+
- **Type Check:** `yarn typecheck` (Runs TypeScript compiler)
22+
- **Format Check:** `yarn prettier`
23+
- **Validate All:** `yarn validate` (Runs Prettier, ESLint, Typecheck, and Tests in sequence)
24+
- **Build Project:** `yarn build` (Cleans, builds JS with Babel, builds TS types, and copies Flow types)
2525

2626
## Development Conventions
2727

28-
* **Code Style:**
29-
* **Linting:** ESLint is configured with `@callstack/eslint-config` and `typescript-eslint`. It enforces strict rules, including `no-console` and consistent type imports.
30-
* **Formatting:** Prettier is used for code formatting (single quotes, trailing commas).
31-
* **Imports:** Sorted using `eslint-plugin-simple-import-sort`.
32-
33-
* **Testing:**
34-
* **Framework:** Jest with `react-native` preset.
35-
* **Location:** Tests are located within `src`, typically in `__tests__` directories or co-located.
36-
* **Setup:** `jest-setup.ts` configures the test environment. `src/index.ts` automatically configures cleanup after each test unless skipped.
37-
* **Coverage:** Collected from `src`, excluding tests.
38-
39-
* **Commits & Releases:**
40-
* **Commits:** Follow the **Conventional Commits** specification (e.g., `fix:`, `feat:`, `chore:`). This is enforced and used for changelog generation.
41-
* **Releases:** Managed via `release-it`.
42-
43-
* **File Structure:**
44-
* `src/`: Source code.
45-
* `src/pure.ts`: Core logic without side effects (no auto-cleanup).
46-
* `src/index.ts`: Main entry point, re-exports `pure` and adds side effects (auto-cleanup).
47-
* `examples/`: Example React Native applications using the library.
48-
* `website/`: Documentation website.
28+
- **Code Style:**
29+
- **Linting:** ESLint is configured with `@callstack/eslint-config` and `typescript-eslint`. It enforces strict rules, including `no-console` and consistent type imports.
30+
- **Formatting:** Prettier is used for code formatting (single quotes, trailing commas).
31+
- **Imports:** Sorted using `eslint-plugin-simple-import-sort`.
32+
33+
- **Testing:**
34+
- **Framework:** Jest with `react-native` preset.
35+
- **Location:** Tests are located within `src`, typically in `__tests__` directories or co-located.
36+
- **Setup:** `jest-setup.ts` configures the test environment. `src/index.ts` automatically configures cleanup after each test unless skipped.
37+
- **Coverage:** Collected from `src`, excluding tests.
38+
39+
- **Commits & Releases:**
40+
- **Commits:** Follow the **Conventional Commits** specification (e.g., `fix:`, `feat:`, `chore:`). This is enforced and used for changelog generation.
41+
- **Releases:** Managed via `release-it`.
42+
43+
- **File Structure:**
44+
- `src/`: Source code.
45+
- `src/pure.ts`: Core logic without side effects (no auto-cleanup).
46+
- `src/index.ts`: Main entry point, re-exports `pure` and adds side effects (auto-cleanup).
47+
- `examples/`: Example React Native applications using the library.
48+
- `website/`: Documentation website.

src/__tests__/wait-for.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ afterEach(() => {
4040
test('waits for element until it stops throwing', async () => {
4141
render(<BananaContainer />);
4242

43-
fireEvent.press(screen.getByText('Change freshness!'));
43+
await fireEvent.press(screen.getByText('Change freshness!'));
4444

4545
expect(screen.queryByText('Fresh')).toBeNull();
4646

@@ -52,7 +52,7 @@ test('waits for element until it stops throwing', async () => {
5252
test('waits for element until timeout is met', async () => {
5353
render(<BananaContainer />);
5454

55-
fireEvent.press(screen.getByText('Change freshness!'));
55+
await fireEvent.press(screen.getByText('Change freshness!'));
5656

5757
await expect(waitFor(() => screen.getByText('Fresh'), { timeout: 100 })).rejects.toThrow();
5858

@@ -65,7 +65,7 @@ test('waitFor defaults to asyncWaitTimeout config option', async () => {
6565
configure({ asyncUtilTimeout: 100 });
6666
render(<BananaContainer />);
6767

68-
fireEvent.press(screen.getByText('Change freshness!'));
68+
await fireEvent.press(screen.getByText('Change freshness!'));
6969
await expect(waitFor(() => screen.getByText('Fresh'))).rejects.toThrow();
7070

7171
// Async action ends after 300ms and we only waited 100ms, so we need to wait
@@ -77,7 +77,7 @@ test('waitFor timeout option takes precendence over `asyncWaitTimeout` config op
7777
configure({ asyncUtilTimeout: 2000 });
7878
render(<BananaContainer />);
7979

80-
fireEvent.press(screen.getByText('Change freshness!'));
80+
await fireEvent.press(screen.getByText('Change freshness!'));
8181
await expect(waitFor(() => screen.getByText('Fresh'), { timeout: 100 })).rejects.toThrow();
8282

8383
// Async action ends after 300ms and we only waited 100ms, so we need to wait
@@ -127,7 +127,7 @@ test('waits for async event with fireEvent', async () => {
127127
const spy = jest.fn();
128128
render(<Comp onPress={spy} />);
129129

130-
fireEvent.press(screen.getByText('Trigger'));
130+
await fireEvent.press(screen.getByText('Trigger'));
131131

132132
await waitFor(() => {
133133
expect(spy).toHaveBeenCalled();
@@ -140,7 +140,7 @@ test.each([false, true])(
140140
jest.useFakeTimers({ legacyFakeTimers });
141141
render(<BananaContainer />);
142142

143-
fireEvent.press(screen.getByText('Change freshness!'));
143+
await fireEvent.press(screen.getByText('Change freshness!'));
144144
expect(screen.queryByText('Fresh')).toBeNull();
145145

146146
jest.advanceTimersByTime(300);
@@ -305,7 +305,7 @@ test.each([
305305
await waitFor(() => screen.getByText('red'));
306306

307307
// Check that the `onPress` callback is called with the already-updated value of `syncedColor`.
308-
fireEvent.press(screen.getByText('Trigger'));
308+
await fireEvent.press(screen.getByText('Trigger'));
309309
expect(onPress).toHaveBeenCalledWith('red');
310310
},
311311
);

src/fire-event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,4 @@ function tryGetContentOffset(event: unknown): Point | null {
226226
}
227227

228228
return null;
229-
}
229+
}

typings/index.flow.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,21 @@ type FireEventFunction = (
286286
element: ReactTestInstance,
287287
eventName: string,
288288
...data: Array<any>
289-
) => any;
289+
) => Promise<any>;
290290

291291
type FireEventAPI = FireEventFunction & {
292+
press: (element: ReactTestInstance, ...data: Array<any>) => Promise<any>,
293+
changeText: (element: ReactTestInstance, ...data: Array<any>) => Promise<any>,
294+
scroll: (element: ReactTestInstance, ...data: Array<any>) => Promise<any>,
295+
};
296+
297+
type DeprecatedFireEventSyncFunction = (
298+
element: ReactTestInstance,
299+
eventName: string,
300+
...data: Array<any>
301+
) => any;
302+
303+
type DeprecatedFireEventSyncAPI = DeprecatedFireEventSyncFunction & {
292304
press: (element: ReactTestInstance, ...data: Array<any>) => any,
293305
changeText: (element: ReactTestInstance, ...data: Array<any>) => any,
294306
scroll: (element: ReactTestInstance, ...data: Array<any>) => any,
@@ -325,6 +337,7 @@ declare module '@testing-library/react-native' {
325337

326338
declare export var cleanup: () => void;
327339
declare export var fireEvent: FireEventAPI;
340+
declare export var deprecated_fireEventSync: DeprecatedFireEventSyncAPI;
328341

329342
declare export var waitFor: WaitForFunction;
330343

website/docs/14.x/docs/api/events/fire-event.mdx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ Use Fire Event for cases not supported by User Event and for triggering event ha
1010
:::
1111

1212
```ts
13-
function fireEvent(element: ReactTestInstance, eventName: string, ...data: unknown[]): Promise<unknown>;
13+
function fireEvent(
14+
element: ReactTestInstance,
15+
eventName: string,
16+
...data: unknown[]
17+
): Promise<unknown>;
1418
```
1519

1620
The `fireEvent` API allows you to trigger all kinds 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.
@@ -171,7 +175,11 @@ await fireEvent.scroll(screen.getByText('scroll-view'), eventData);
171175
## `deprecated_fireEventSync` {#deprecated-fire-event-sync}
172176

173177
```ts
174-
function deprecated_fireEventSync(element: ReactTestInstance, eventName: string, ...data: unknown[]): void;
178+
function deprecated_fireEventSync(
179+
element: ReactTestInstance,
180+
eventName: string,
181+
...data: unknown[]
182+
): void;
175183
```
176184

177185
Synchronous version of `fireEvent`. Deprecated and will be removed in future versions.

0 commit comments

Comments
 (0)