React Native Testing Library 2.0 - What’s New?

We are happy to announce the release of version 2.0 of React Native Testing Library. For the last couple of weeks, we've been working really hard to bring you useful new features and to polish our APIs and their documentation, as well as improve compatibility with other Testing Library implementations.

We also use this release as a chance to remove a small number of deprecated APIs, in accordance with semver, to encourage more robust test writing.

If you’re looking for the migration guide only, it’s right at the bottom of this post.

What is React Native Testing Library?

The React Native Testing Library, or RNTL in short, is a lightweight solution for testing your React Native components. It provides helpful utility functions on top of official <rte-code>react-test-renderer<rte-code> letting you always be up to date with the latest React features. Its opinionated API aims to prevent developers from testing implementation details of their React components while focusing on user experience and accessibility.

So, what's new in the new version of the React Native Testing Library?

We bid farewell to Node 8 and shallow rendering

Node 8 is long past its support date, which ended with the year 2019. We moved to Node 10 like the rest of the ecosystem. You should too!

Also, we decided to remove <rte-code>shallow<rte-code> rendering because this way of rendering React components is usually not a good idea, as it frequently fails to detect application errors.

However, if you find it useful or need to support legacy tests we’ve got you covered. The <rte-code>shallow<rte-code> helper is quite simple to implement by yourself. Feel free to use the code snippet provided in our migration guide.

Fixing getByTestId query behavior

Previous version of <rte-code>getByTestId<rte-code> (and <rte-code>queryByTestId<rte-code>) had a bug that allowed the queries to find custom components that would not pass <rte-code>testID<rte-code> to the native (host) components. This resulted in finding more <rte-code>testID<rte-code>s than there was in the native hierarchy. Curiously, this bug was absent in their plural implementation <rte-code>getAllByTestId<rte-code> (and <rte-code>queryAllByTestId<rte-code>).

As some users might have relied on this invalid behavior, the bug has intentionally not been fixed in version <rte-code>1.x<rte-code>.

Automatic cleanup after each test

Following the path of React Testing Library we are now automatically calling <rte-code>cleanup<rte-code> after each test if your testing framework supports <rte-code>afterEach<rte-code> hook (which jest, mocha, and jasmine do). Therefore, you should be able to remove any <rte-code>afterEach(cleanup)<rte-code> calls in your test files.

This generally should not break any of your tests, unless so of them are not isolated. Which basically means calling <rte-code>render<rte-code> outside for <rte-code>test<rte-code> block.

Generally, you should keep your tests isolated, but if you can't or don't want to do this right away you can easily prevent this behavior in one for three ways:

  • by importing <rte-code>react-native-testing-library/pure<rte-code> instead of <rte-code>react-native-testing-library<rte-code>
  • by importing <rte-code>react-native-testing-library/dont-cleanup-after-each<rte-code> before your <rte-code>react-native-testing-library<rte-code> import (or in <rte-code>setupFiles<rte-code> in your jest configuration file)
  • be setting the <rte-code>RNTL_SKIP_AUTO_CLEANUP<rte-code> env variable.

waitFor and findBy automatically wrapped in act

Your <rte-code>waitFor<rte-code> and hence <rte-code>findBy<rte-code> calls are now automatically wrapped in act utility. This helps you avoid dreaded act warning in tests involving asynchronous state mutation, e.g., when simulating fetch data from API or using animations.

This feature is active only if you use React Native >= 0.61 or React >= 16.9.0, because asynchronous <rte-code>act<rte-code> was added then.

Other breaking changes

Marking the byType and byProps queries as unsafe

These queries families have been prefixed with <rte-code>UNSAFE_<rte-code> to indicate that you generally should avoid using them. They often result in fragile and less reliable tests. They also make it easy to write tests that hide unexpected behavior that affects users, if not backed by sufficient code coverage.

Even though marked unsafe, we’re still keeping these APIs, because there are users who invested a lot of time in writing their tests and we, as library maintainers, would not be able to provide them with a simple migration path. These queries may also be helpful if you prefer to unit-test your components, instead of integration-test them.

Removal of byName queries and debug export

These queries have been removed after being long deprecated. Using them tied your component tests really closely to their implementation details and e.g. could easily break your tests when upgrading React Native versions, making tests fragile and not really reliable.

<rte-code>debug<rte-code> export was a leftover from the initial implementation of RNTL, which was later superseded by the <rte-code>debug<rte-code> function returned from <rte-code>render<rte-code>.

New APIs

Even though you don’t need to upgrade to v2 to benefit these APIs, we still wanted to mention them here because why not.

findBy queries

These queries are the simple, yet useful combination of <rte-code>waitFor<rte-code> and <rte-code>getBy<rte-code> queries. Available queries and their basic arguments are the same as respective <rte-code>getBy<rte-code> queries. However, they return <rte-code>Promise<rte-code> instead of the actual element. Optionally they accept custom values for <rte-code>timeout<rte-code> and query <rte-code>interval<rte-code>. These queries are useful for situations you have to wait for a particular UI element to appear or to change its state.

Example code:

```js
await expect(findByText('Some Text')).resolves.toBeTruthy();
await expect(findByText('Some Text', { timeout: 1000 })).resolves.toBeTruthy();
```
view raw gistfile1.txt hosted with ❤ by GitHub

within operator

<rte-code>within<rte-code> operator enables you to perform queries scoped to given element and its children. Its main use cases are querying elements for a particular list of repeating items, e.g. inside a <rte-code>FlatList<rte-code> or querying elements inside given screen components for tests involving screen transitions.

```js
const detailsScreenQueries = within(getByA11yHint(‘Details Screen’));
```
view raw gistfile1.txt hosted with ❤ by GitHub

This operator provides the same query functions as <rte-code>render<rte-code> functions, so <rte-code>getBy<rte-code>, <rte-code>queryBy<rte-code>, <rte-code>findBy<rte-code> as well as <rte-code>getAllBy<rte-code>, <rte-code>queryAllBy<rte-code> and <rte-code>findAllBy<rte-code>. It does not, however,  provide other methods returned by <rte-code>render<rte-code> such as <rte-code>update<rte-code>/<rte-code>rerender<rte-code>, <rte-code>debug<rte-code>, or <rte-code>toJSON<rte-code>.

Improved documentation

We migrated our documentation to use Docusaurus v2, which comes with a refreshed design, improved accessibility and themes support (yes, there is a dark mode). We used new doc engine capabilities to sprinkle improvements in various places, like adding useful hints, cautions and warnings about using different parts of the API.

We’re also heavy at work to provide you with high-quality guides and examples of testing React Navigation, Redux, or JS side of native modules.

Community compatibility

We want RNTL to be as compatible with the Testing Library community as possible. That’s why we’ve put effort into making sure you can use some community projects known from other platforms.

@testing-library/jest-native matchers

You can improve some of your test assertions by using React Native-specific matchers from @testing-library/jest-native matchers project.

When using React Native Testing Library with Jest by default you only have access to generic Jest matchers that contain various general-purpose checks like <rte-code>toBeTruthy<rte-code>, <rte-code>toHaveLength<rte-code> or <rte-code>toHaveBeenCalled<rte-code>. 

By adding `@testing-library/jest-native` package you gain access to some React Native-specific matchers like <rte-code>toBeEnabled<rte-code>/<rte-code>toBeDisabled<rte-code>, <rte-code>toHaveStyle<rte-code>, <rte-code>toHaveProp<rte-code>, <rte-code>toHaveTextContent<rte-code>, <rte-code>toBeEmpty<rte-code> and <rte-code>toContainElement<rte-code>.

eslint-plugin-testing-library

We’ve made sure RNTL is compatible with eslint-plugin-testing-library, so you can freely use it in your project and benefit the collective testing wisdom of the Testing Library community. The only rule that’s not compatible is <rte-code>prefer-screen-queries<rte-code> since we’re not providing the <rte-code>screen<rte-code> object.

Migration guide

To ease the transition to the new version, we prepared a migration guide covering all of the breaking changes, and here's a full changelog for React Native Testing Library 2.0.

Summary

To wrap everything up, we are happy that you find our library helpful. Your recognition is the best price we can get for our effort. We hope that the aforementioned upgrades will make your daily work easier than ever before.

Also, special thanks to Maciej Jastrzębski and Kenneth Kwakye-Gyamfi for their help with making this release happen.

Insights

Learn more about Testing

How AI Agents Can Cut Manual QA by 30% — cover

Oct 30Article

How AI Agents Can Cut Manual QA by 30%

Explore an agentic QA workflow targeting 30% less manual effort across mobile, web, and TV, with test selection, failure triage, and validation.

Give QA Agents the Controls They Need With Appduct — cover

Oct 20Article

Give QA Agents the Controls They Need With Appduct

Use Appduct to give AI QA agents access to app functions for setting test conditions, triggering events, and checking results with UI automation.

cover

Oct 13Article

Agentic Mobile Testing With e2e and agent-device

See how e2e uses agent-device for AI-driven iOS and Android tests, combines exact assertions with agent actions, and replays cached steps without model calls.

Who Tests AI-Written Code? Inside TesterArmy With Szymon Rybczak — cover

Oct 12Podcast

Who Tests AI-Written Code? Inside TesterArmy With Szymon Rybczak

Szymon Rybczak explains how TesterArmy tests web and mobile apps with AI agents, creates test plans for pull requests, and fits into QA workflows.

cover

Aug 4Article

Automating Mobile QA With Cloud Agents

Code review and green CI checks do not prove a mobile app still works. Learn how cloud agents, agent-device, and runtime evidence can verify app behavior before merge.

cover

Jul 21Webinar

Behavior Review for AI-Native Delivery

AI can increase code output faster than teams can verify the real app. See why behavior review matters before merge.

cover

Jul 6Article

Introducing Sniffler: Run only the E2E tests your changes can affect

Sniffler maps changed files to affected E2E tests, so teams can avoid running the full suite on every pull request.

cover

Jun 17Talk

Automating Mobile QA with Cloud Agents

Michał Pierzchała will present Automating Mobile QA with Cloud Agents at Ship London on 17 June 2026.

cover

May 13Podcast

How AI Is Changing React Native Development and Testing

Zack Ebenfeld joins React Universe On Air to talk about how AI is changing React Native workflows, testing, QA, and day-to-day engineering work.

cover

Apr 14Article

Agent React DevTools: Give AI Agents Access to React Internals

Agent React DevTools gives AI agents access to the React component tree, state, and performance data, enabling deeper debugging and more reliable QA for React and React Native apps.

cover

Mar 19Live Stream

Agent Device, AI workflows, and mobile testing in practice

A discussion on Agent Device, AI-driven workflows, and testing mobile apps using simulators and accessibility data.

cover

Aug 23Podcast

Introducing E2E Tests to React Native Core

This episode of the React Native Show dives into the recent introduction of End-to-End (E2E) testing in RNTester. Join us as we unpack the thought process, technical considerations, and practical implementation of this new approach to testing in React Native.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.