Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ jobs:
- name: Typecheck React 19.2-only tests
run: yarn typecheck:react-19_2

docs:
runs-on: ubuntu-latest
name: Docs
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup Node.js and deps
uses: ./.github/actions/setup-deps

- name: Check generated package docs
run: yarn docs:check

- name: Setup Node.js and website deps
uses: ./.github/actions/setup-website-deps

- name: Validate website docs
run: yarn --cwd website validate

typecheck-rn-0-85:
runs-on: ubuntu-latest
name: Typecheck → RN 0.85
Expand Down
2 changes: 1 addition & 1 deletion .release-it.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"hooks": {
"before:init": ["yarn typecheck", "yarn test", "yarn lint"],
"before:init": ["yarn docs:check", "yarn typecheck", "yarn test", "yarn lint"],
"after:bump": "yarn build",
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
},
Expand Down
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
[![MIT License][license-badge]][license]
[![Sponsored by Callstack][callstack-badge]][callstack]

> [!WARNING]
> **Beta Version:** This version (v14) is currently in beta. APIs and behavior may change before the stable release. Please report any issues you encounter.
>
> For stable version (v13) see [README-v13.md](./README-v13.md).

## The problem

You want to write maintainable tests for your React Native components. Your tests should avoid implementation details and focus on giving you confidence. They should remain maintainable so refactors (changes to implementation but not functionality) don't break your tests and slow you and your team down.
Expand All @@ -34,7 +29,7 @@ This project is inspired by [React Testing Library](https://github.com/testing-l
Open a Terminal in your project's folder and run:

```sh
npm install --save-dev @testing-library/react-native@alpha
npm install --save-dev @testing-library/react-native
```

This library has a `peerDependencies` listing for [Test Renderer](https://github.com/mdjastrzebski/test-renderer). Make sure to install it as a dev dependency:
Expand Down
31 changes: 31 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# React Native Testing Library package docs

These markdown files are bundled with the npm package for coding agents. They describe the installed package version.

Start with [LLM Guidelines](./guides/llm-guidelines.md) for the agent setup snippet and quick rules, or use the included page list below to load specific references.

## Included pages

- [LLM Guidelines](./guides/llm-guidelines.md) - Quick rules for agents writing RNTL tests.
- [Quick Start](./guides/quick-start.md) - Installation and setup basics.
- [How to Query](./guides/how-to-query.md) - Query priority and selection guidance.
- [Common Mistakes](./guides/common-mistakes.md) - Common anti-patterns and preferred alternatives.
- [Troubleshooting](./guides/troubleshooting.md) - Common integration and runtime issues.
- [Testing Environment](./guides/testing-environment.md) - How RNTL simulates React Native under tests.
- [Understanding act](./guides/understanding-act.md) - How act warnings happen and how to resolve them.
- [Migration to 14.x](./guides/migration-v14.md) - Breaking changes and upgrade steps for RNTL v14.
- [API Overview](./api/overview.md) - Top-level API map.
- [render](./api/render.md) - Rendering components in tests.
- [screen](./api/screen.md) - Recommended global query surface.
- [Queries](./api/queries.md) - Query variants and predicates.
- [Jest Matchers](./api/jest-matchers.md) - Built-in RNTL assertions.
- [User Event](./api/user-event.md) - Realistic user interactions.
- [Fire Event](./api/fire-event.md) - Low-level event triggering.
- [Async Utilities](./api/async-utilities.md) - Async queries and wait helpers.
- [renderHook](./api/render-hook.md) - Testing custom hooks.
- [Configuration](./api/configuration.md) - Runtime configuration options.
- [Accessibility](./api/accessibility.md) - Accessibility helpers and hidden elements.
- [Other Helpers](./api/other-helpers.md) - within, act, cleanup, and related helpers.
- [Custom Render](./cookbook/custom-render.md) - Reusable render wrappers.
- [Async Events](./cookbook/async-events.md) - Testing async interactions.
- [Network Requests](./cookbook/network-requests.md) - Testing components that make network requests.
26 changes: 26 additions & 0 deletions docs/api/accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Accessibility

## `isHiddenFromAccessibility`

```ts
function isHiddenFromAccessibility(instance: TestInstance | null): boolean {}
```

Also available as `isInaccessible()` alias for React Testing Library compatibility.

Checks if given element is hidden from assistive technology, e.g. screen readers.

> [!NOTE]
> Like [`isInaccessible`](https://testing-library.com/docs/dom-testing-library/api-accessibility/#isinaccessible) function from DOM Testing Library this function considers both accessibility elements and presentational elements (regular `View`s) to be accessible, unless they are hidden in terms of host platform.
>
> This covers only part of [ARIA notion of Accessibility Tree](https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion), as ARIA excludes both hidden and presentational elements from the Accessibility Tree.

For the scope of this function, element is inaccessible when it, or any of its ancestors, meets any of the following conditions:

- it has `display: none` style
- it has [`aria-hidden`](https://reactnative.dev/docs/accessibility#aria-hidden) prop set to `true`
- it has [`accessibilityElementsHidden`](https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios) prop set to `true`
- it has [`importantForAccessibility`](https://reactnative.dev/docs/accessibility#importantforaccessibility-android) prop set to `no-hide-descendants`
- it has sibling host element with either [`aria-modal`](https://reactnative.dev/docs/accessibility#aria-modal-ios) or [`accessibilityViewIsModal`](https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios) prop set to `true`

Specifying `accessible={false}`, `role="none"`, `accessibilityRole="none"`, or `importantForAccessibility="no"` props does not cause the element to become inaccessible.
137 changes: 137 additions & 0 deletions docs/api/async-utilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Async utilities

## `findBy*` queries

The `findBy*` queries are used to find elements that are not instantly available but will be added as a result of some asynchronous action. Learn more details [here](./queries.md#find-by).

## `waitFor`

```tsx
function waitFor<T>(
expectation: () => T,
options?: {
timeout?: number;
interval?: number;
onTimeout?: (error: Error) => Error;
},
): Promise<T>;
```

Waits for the `expectation` callback to pass. `waitFor` runs the callback multiple times until timeout is reached, as specified by the `timeout` and `interval` options. The callback must throw an error when the expectation is not met. Returning any value, including a falsy one, is treated as meeting the expectation, and the callback result is returned to the caller.

```tsx
await waitFor(() => expect(mockFunction).toHaveBeenCalledWith());
```

`waitFor` executes the `expectation` callback every `interval` (default: 50 ms) until `timeout` (default: 1000 ms) is reached. Execution stops as soon as the callback doesn't throw an error, and the callback's return value is returned to the caller. If timeout is reached, `waitFor` re-throws the final error thrown by `expectation`.

```tsx
// ❌ `waitFor` will return immediately because callback does not throw
await waitFor(() => false);
```

`waitFor` is an async function so you need to `await` the result to pause test execution.

```jsx
// ❌ missing `await`: `waitFor` will just return Promise that will be rejected when the timeout is reached
waitFor(() => expect(1).toBe(2));
```

> [!NOTE]
> You can enforce awaiting `waitFor` by using the [await-async-utils](https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md) rule from [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library).

Since `waitFor` runs the `expectation` callback multiple times, [avoid performing side effects](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#performing-side-effects-in-waitfor) in `waitFor`.

```jsx
await waitFor(async () => {
// ❌ button will be pressed on each waitFor iteration
await fireEvent.press(screen.getByText('press me'));
expect(mockOnPress).toHaveBeenCalled();
});
```

> [!NOTE]
> Avoiding side effects in `expectation` callback can be partially enforced with the [`no-wait-for-side-effects` rule](https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md).

Use a [single assertion per `waitFor`](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#having-multiple-assertions-in-a-single-waitfor-callback) for consistency and faster failing tests. For multiple assertions, use separate `waitFor` calls. Often you won't need to wrap the second assertion in `waitFor` since the first one waits for the asynchronous change.

`waitFor` checks whether Jest fake timers are enabled and adapts its behavior in such case. The following snippet is a simplified version of how it behaves when fake timers are enabled:

```tsx
let fakeTimeRemaining = timeout;
let lastError;

while (fakeTimeRemaining > 0) {
fakeTimeRemaining = fakeTimeRemaining - interval;
jest.advanceTimersByTime(interval);
try {
// resolve
return expectation();
} catch (error) {
lastError = error;
}
}

// reject
throw lastError;
```

In the following example we test that a function is called after 10 seconds using fake timers. With fake timers, the test doesn't depend on real time passing, making it faster and more reliable. We don't need to advance fake timers through Jest's API because `waitFor` handles this.

```tsx
// in component
setTimeout(() => {
someFunction();
}, 10000);

// in test
jest.useFakeTimers();

await waitFor(
() => {
expect(someFunction).toHaveBeenCalledWith();
},
{ timeout: 10000 },
);
```

> [!NOTE]
> If you receive warnings related to `act()` function consult our [Understanding Act](../guides/understanding-act.md) function document.

### Options

- `timeout`: How long to wait for, in ms. Defaults to 1000 ms (configured by `asyncUtilTimeout` option).
- `interval`: How often to check, in ms. Defaults to 50 ms.
- `onTimeout`: Callback to transform the error before it's thrown. Useful for debugging, e.g., `onTimeout: () => { screen.debug(); }`.

## `waitForElementToBeRemoved`

```ts
function waitForElementToBeRemoved<T>(
expectation: () => T,
options?: {
timeout?: number;
interval?: number;
onTimeout?: (error: Error) => Error;
},
): Promise<T>;
```

Waits for non-deterministic periods of time until queried element is removed or times out. `waitForElementToBeRemoved` periodically calls `expectation` every `interval` milliseconds to determine whether the element has been removed or not.

```jsx
import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';

test('waiting for an Banana to be removed', async () => {
await render(<Banana />);

await waitForElementToBeRemoved(() => screen.getByText('Banana ready'));
});
```

This method expects that the element is initially present in the render tree and then is removed from it. If the element is not present when you call this method it throws an error.

You can use any of `getBy`, `getAllBy`, `queryBy` and `queryAllBy` queries for `expectation` parameter.

> [!NOTE]
> If you receive warnings related to `act()` function consult our [Understanding Act](../guides/understanding-act.md) function document.
61 changes: 61 additions & 0 deletions docs/api/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Configuration

## `configure`

```ts
type Config = {
/** Default timeout, in ms, for `waitFor` and `findBy*` queries. */
asyncUtilTimeout: number;

/** Default value for `includeHiddenElements` query option. */
defaultIncludeHiddenElements: boolean;

/** Default options for `debug` helper. */
defaultDebugOptions?: Partial<DebugOptions>;
};

type ConfigAliasOptions = {
/** RTL-compatibility alias for `defaultIncludeHiddenElements`. */
defaultHidden: boolean;
};

function configure(options: Partial<Config & ConfigAliasOptions>) {}
```

### `asyncUtilTimeout` option

Default timeout, in ms, for async helper functions (`waitFor`, `waitForElementToBeRemoved`) and `findBy*` queries. Defaults to 1000 ms.

### `defaultIncludeHiddenElements` option

Default value for [includeHiddenElements](./queries.md#includehiddenelements-option) query option for all queries. The default value is set to `false`, so all queries will not match [elements hidden from accessibility](#ishiddenfromaccessibility). This is because the users of the app would not be able to see such elements.

This option is also available as `defaultHidden` alias for compatibility with [React Testing Library](https://testing-library.com/docs/dom-testing-library/api-configuration/#defaulthidden).

### `defaultDebugOptions` option

Default [debug options](#debug) to be used when calling `debug()`. These default options will be overridden by the ones you specify directly when calling `debug()`.

## `resetToDefaults()`

```ts
function resetToDefaults() {}
```

## Environment variables

### `RNTL_SKIP_AUTO_CLEANUP`

Set to `true` to disable automatic `cleanup()` after each test. It works the same as importing `react-native-testing-library/dont-cleanup-after-each` or using `react-native-testing-library/pure`.

```shell
$ RNTL_SKIP_AUTO_CLEANUP=true jest
```

### `RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`

Set to `true` to disable auto-detection of fake timers. This might be useful in rare cases when you want to use non-Jest fake timers. See [issue #886](https://github.com/callstack/react-native-testing-library/issues/886) for more details.

```shell
$ RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS=true jest
```
Loading
Loading