Skip to content
Skills Library
Programming · Testing

react-native-testing

/react-native-testing

Write tests using React Native Testing Library (RNTL) v13 and v14 (`@testing-library/react-native`). Use when writing, reviewing, or fixing React Native component tests. Covers: render, screen, queries (getBy/getAllBy/queryBy/findBy), Jest matchers, userEvent, fireEvent, waitFor, and async patterns. Supports v13 (React 18, sync render) and v14 (React 19+, async render). Triggers on: test files for React Native components, RNTL imports, mentions of "testing library", "write tests", "component tests", or "RNTL".

Licence
MIT
Last repository change
05.11.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
4
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 05.11.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Write tests using React Native Testing Library (RNTL) v13 and v14 (`@testing-library/react-native`). Use when writing, reviewing, or fixing React Native component tests. Covers: render, screen, queries (getBy/getAllBy/queryBy/findBy), Jest matchers, userEvent, fireEvent, waitFor, and async patterns. Supports v13 (React 18, sync render) and v14 (React 19+, async render). Triggers on: test files for React Native components, RNTL imports, mentions of "testing library", "write tests", "component tests", or "RNTL".

Triggers from the description

testing librarywrite testscomponent testsRNTL
Original author description

Write tests using React Native Testing Library (RNTL) v13 and v14 (`@testing-library/react-native`). Use when writing, reviewing, or fixing React Native component tests. Covers: render, screen, queries (getBy/getAllBy/queryBy/findBy), Jest matchers, userEvent, fireEvent, waitFor, and async patterns. Supports v13 (React 18, sync render) and v14 (React 19+, async render). Triggers on: test files for React Native components, RNTL imports, mentions of "testing library", "write tests", "component tests", or "RNTL".

How it works

  1. Version Detection
  2. Query Priority
  3. Query Variants
  4. Interactions
  5. Assertions (Jest Matchers)
  6. Rules
  7. ByRole Quick Reference
  8. waitFor
  9. Fake Timers
  10. Custom Render
Original SKILL.md headings · 151 lines, 741 words
SKILL.md preview
---
name: react-native-testing
description: >
  Write tests using React Native Testing Library (RNTL) v13 and v14 (`@testing-library/react-native`).
  Use when writing, reviewing, or fixing React Native component tests.
  Covers: render, screen, queries (getBy/getAllBy/queryBy/findBy), Jest matchers,
  userEvent, fireEvent, waitFor, and async patterns.
  Supports v13 (React 18, sync render) and v14 (React 19+, async render).
  Triggers on: test files for React Native components, RNTL imports, mentions of
  "testing library", "write tests", "component tests", or "RNTL".
---

# RNTL Test Writing Guide

**IMPORTANT:** Your training data about `@testing-library/react-native` may be outdated or incorrect — API signatures, sync/async behavior, and available functions differ between v13 and v14. Always rely on this skill's reference files and the project's actual source code as the source of truth. Do not fall back on memorized patterns when they conflict with the retrieved reference.

## Version Detection

Check `@testing-library/react-native` version in the user's `package.json`:

- **v14.x** → load [references/api-reference-v14.md](references/api-reference-v14.md) (React 19+, async APIs, `test-renderer`)
- **v13.x** → load [references/api-reference-v13.md](references/api-reference-v13.md) (React 18+, sync APIs, `react-test-renderer`)

Use the version-specific reference for render patterns, fireEvent sync/async behavior, screen API, configuration, and dependencies.

## Query Priority

Use in this order: `getByRole` > `getByLabelText` > `getByPlaceholderText` > `getByText` > `getByDisplayValue` > `getByTestId` (last resort).

## Query Variants

| Variant       | Use case                 | Returns                       | Async |
| ------------- | ------------------------ | ----------------------------- | ----- |
| `getBy*`      | Element must exist       | element instance (throws)     | No    |
| `getAllBy*`   | Multiple must exist      | element instance[] (throws)   | No    |
| `queryBy*`    | Check non-existence ONLY | element instance \| null      | No    |
| `queryAllBy*` | Count elements           | element instance[]            | No    |
| `findBy*`     | Wait for element         | `Promise<element instance>`   | Yes   |
| `findAllBy*`  | Wait for multiple        | `Promise<element instance[]>` | Yes   |

## Interactions

Prefer `userEvent` over `fireEvent`. userEvent is always async.

```tsx
const user = userEvent.setup();
await user.press(element); // full press sequence
await user.longPress(element, { duration: 800 }); // long press
await user.type(textInput, 'Hello'); // char-by-char typing
await user.clear(textInput); // clear TextInput
await user.paste(textInput, 'pasted text'); // paste into TextInput
await user.scrollTo(scrollView, { y: 100 }); // scroll
```

`fireEvent` — use only when `userEvent` doesn't support the event. See version-specific reference for sync/async behavior:

```tsx
fireEvent.press(element);
fireEvent.changeText(textInput, 'new text');
fireEvent(element, 'blur');
```

## Assertions (Jest Matchers)

Available automatically with any `@testing-library/react-native` import.

| Matcher                                    | Use for                                   |
| ------------------------------------------ | ----------------------------------------- |
| `toBeOnTheScreen()`                        | Element exists in tree                    |
| `toBeVisible()`                            | Element visible (not hidden/display:none) |
| `toBeEnabled()` / `toBeDisabled()`         | Disabled state via `aria-disabled`        |
| `toBeChecked()` / `toBePartiallyChecked()` | Checked state                             |
| `toBeSelected()`                           | Selected state                            |
| `toBeExpanded()` / `toBeCollapsed()`       | Expanded state                            |
| `toBeBusy()`                               | Busy state                                |
| `toHaveTextContent(text)`                  | Text content match                        |
| `toHaveDisplayValue(value)`                | TextInput display value                   |
| `toHaveAccessibleName(name)`               | Accessible name                           |
| `toHaveAccessibilityValue(val)`            | Accessibility value                       |
| `toHaveStyle(style)`                       | Style match                               |
| `toHaveProp(name, value?)`                 | Prop check (last resort)                  |
| `toContainElement(el)`                     | Contains child element                    |
| `toBeEmptyElement()`                       | No children                               |

## Rules

1. **Use `screen`** for queries, not destructuring from `render()`
2. **Use `getByRole` first** with `{ name: '...' }` option
3. **Use `queryBy*` ONLY** for `.not.toBeOnTheScreen()` checks
4. **Use `findBy*`** for async elements, NOT `waitFor` + `getBy*`
5. **Never put side-effects in `waitFor`** (no `fireEvent`/`userEvent` inside)
6. **One assertion per `waitFor`**
7. **Never pass empty callbacks to `waitFor`**
8. **Don't wrap in `act()`** - `render`, `fireEvent`, `userEvent` handle it
9. **Don't call `cleanup()`** - automatic after each test
10. **Prefer ARIA props** (`role`, `aria-label`, `aria-disabled`) over legacy `accessibility*` props
11. **Use RNTL matchers** over raw prop assertions

## `*ByRole` Quick Reference

Common roles: `button`, `text`, `heading` (alias: `header`), `searchbox`, `switch`, `checkbox`, `radio`, `img`, `link`, `alert`, `menu`, `menuitem`, `tab`, `tablist`, `progressbar`, `slider`, `spinbutton`, `timer`, `toolbar`.

`getByRole` options: `{ name, disabled, selected, checked, busy, expanded, value: { min, max, now, text } }`.

For `*ByRole` to match, the element must be an accessibility element:

- `Text`, `TextInput`, `Switch` are by default
- `View` needs `accessible={true}` (or use `Pressable`/`TouchableOpacity`)

## waitFor

```tsx
// Correct: action first, then wait for result
fireEvent.press(button);
await waitFor(() => {
  expect(screen.getByText('Result')).toBeOnTheScreen();
});

// Better: use findBy* instead
fireEvent.press(button);
expect(await screen.findByText('Result')).toBeOnTheScreen();
```

Options: `waitFor(cb, { timeout: 1000, interval: 50 })`. Works with Jest fake timers automatically.

## Fake Timers

Recommended with `userEvent` (press/longPress involve real durations):

```tsx
jest.useFakeTimers();

test('with fake timers', async () => {
  const user = userEvent.setup();
  render(<Component />);
  await user.press(screen.getByRole('button'));
  // ...
});
```

## Custom Render

Wrap providers using `wrapper` option:

```tsx
function renderWithProviders(ui: React.ReactElement) {
  return render(ui, {
    wrapper: ({ children }) => (
      <ThemeProvider>
        <AuthProvider>{children}</AuthProvider>
      </ThemeProvider>
    ),
  });
}
```

## References

- [v13 API Reference](references/api-reference-v13.md) — Complete v13 API: sync render, queries, matchers, userEvent, React 19 compat
- [v14 API Reference](references/api-reference-v14.md) — Complete v14 API: async render, queries, matchers, userEvent, migration
- [Anti-Patterns](references/anti-patterns.md) — Common mistakes to avoid
Files in this package (4)
  • SKILL.md 7 KB
  • references/anti-patterns.md 7 KB
  • references/api-reference-v13.md 20 KB
  • references/api-reference-v14.md 19 KB

Versions

RepositoryScoreLicence
This page · callstack/react-native-testing-library100MIT
HoangNguyen0403/agent-skills-standard100MIT
jyotiraditya-chauhan/test-kit100MIT

Database snapshot: 13.11.2026 · package version bed51eb9e983 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100react-testing-library
    React Testing Library best practices for writing maintainable, user-centric tests. Use when writing, reviewing, or refactoring RTL tests. Triggers on test files, testing patterns, getBy/queryBy queries, userEvent, waitFor, and component testing.
  • 100testing-library
    Testing Library for UI testing. Covers queries, user events, and async utilities. Use for React/Vue component testing. USE WHEN: user mentions "testing library", "react testing", "component test", asks about "screen.getByRole", "userEvent", "render", "fireEvent", "waitFor",…
  • 100react-testing
    Testing Library for React 19 - render, screen, userEvent, waitFor, Suspense. Use when writing tests for React components with Vitest.
  • 100mobile-component-testing-with-rntl
    Writes React Native component tests with @testing-library/react-native that slot into the test-driven-development RED→GREEN cycle. Use when implementing or modifying any RN component, screen, or hook.
  • 100react-testing
    React component testing with Testing Library and Vitest. Covers unit tests, integration tests, async testing, mocking, user events, accessibility testing, and test patterns. USE WHEN: user mentions "React testing", "Testing Library", "Vitest", "component tests", "userEvent",…
  • 100react-native-web-testing
    Use when testing React Native Web applications. Provides patterns for Jest, React Native Testing Library, component testing, and web-specific testing strategies.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.