react-native-testing-library
🦉 Simple and complete React Native testing utilities that encourage good testing practices.
Top Related Projects
A framework for building native applications using React
Gray box end-to-end testing and automation framework for mobile apps
Lottie wrapper for React Native.
React Native Mapview component for iOS + Android
A complete native navigation solution for React Native
React Native's Animated library reimplemented
Quick Overview
React Native Testing Library is a lightweight solution for testing React Native components. It provides a set of utility functions that encourage better testing practices by working with actual DOM nodes rather than dealing with instances of rendered React components.
Pros
- Encourages writing tests that closely resemble how users interact with the app
- Provides a simple and intuitive API for querying and interacting with components
- Supports both React Native and Expo projects
- Actively maintained and has good community support
Cons
- Learning curve for developers used to enzyme or other testing libraries
- Limited support for certain complex React Native components
- May require additional setup for certain testing scenarios
- Performance can be slower compared to shallow rendering techniques
Code Examples
- Rendering a component and querying by text:
import { render, screen } from '@testing-library/react-native';
test('renders greeting', () => {
render(<Greeting name="World" />);
const greetingElement = screen.getByText('Hello, World!');
expect(greetingElement).toBeTruthy();
});
- Testing user interaction:
import { render, screen, fireEvent } from '@testing-library/react-native';
test('increments counter on button press', () => {
render(<Counter />);
const incrementButton = screen.getByText('Increment');
const counterText = screen.getByTestId('counter-value');
expect(counterText).toHaveTextContent('0');
fireEvent.press(incrementButton);
expect(counterText).toHaveTextContent('1');
});
- Testing asynchronous behavior:
import { render, screen, waitFor } from '@testing-library/react-native';
test('loads and displays data', async () => {
render(<DataFetcher />);
expect(screen.getByText('Loading...')).toBeTruthy();
await waitFor(() => {
expect(screen.getByText('Data loaded!')).toBeTruthy();
});
});
Getting Started
-
Install the library:
npm install --save-dev @testing-library/react-native
-
Write a test file (e.g.,
App.test.js
):import React from 'react'; import { render, screen } from '@testing-library/react-native'; import App from './App'; test('renders correctly', () => { render(<App />); expect(screen.getByText('Welcome to React Native!')).toBeTruthy(); });
-
Run your tests using Jest:
npx jest
Competitor Comparisons
A framework for building native applications using React
Pros of React Native
- Comprehensive framework for building cross-platform mobile apps
- Large ecosystem and community support
- Extensive documentation and official resources
Cons of React Native
- Steeper learning curve for beginners
- Larger project size and potential performance overhead
- More complex setup and configuration
Code Comparison
React Native (basic component):
import React from 'react';
import { View, Text } from 'react-native';
const MyComponent = () => (
<View>
<Text>Hello, React Native!</Text>
</View>
);
React Native Testing Library (test example):
import { render, screen } from '@testing-library/react-native';
import MyComponent from './MyComponent';
test('renders correctly', () => {
render(<MyComponent />);
expect(screen.getByText('Hello, React Native!')).toBeTruthy();
});
Key Differences
- React Native is a full-fledged framework, while React Native Testing Library is a testing utility
- React Native focuses on app development, whereas React Native Testing Library specializes in testing React Native components
- React Native has a broader scope and functionality, while React Native Testing Library is more focused and lightweight
Use Cases
- Use React Native for building cross-platform mobile applications
- Use React Native Testing Library for writing and running tests for React Native components and applications
Gray box end-to-end testing and automation framework for mobile apps
Pros of Detox
- End-to-end testing framework, allowing for more comprehensive app testing
- Supports both iOS and Android platforms natively
- Provides a gray box testing approach, offering more control over the app's internals
Cons of Detox
- Steeper learning curve due to its comprehensive nature
- Requires more setup and configuration compared to React Native Testing Library
- Can be slower to run tests, especially for large test suites
Code Comparison
Detox example:
describe('Login flow', () => {
it('should login successfully', async () => {
await element(by.id('email')).typeText('user@example.com');
await element(by.id('password')).typeText('password123');
await element(by.text('Login')).tap();
await expect(element(by.text('Welcome'))).toBeVisible();
});
});
React Native Testing Library example:
test('login form submits', () => {
const { getByTestId, getByText } = render(<LoginForm />);
fireEvent.changeText(getByTestId('email'), 'user@example.com');
fireEvent.changeText(getByTestId('password'), 'password123');
fireEvent.press(getByText('Login'));
expect(getByText('Welcome')).toBeTruthy();
});
Both libraries serve different purposes in the React Native testing ecosystem. Detox focuses on end-to-end testing, while React Native Testing Library is primarily for component and integration testing. The choice between them depends on the specific testing needs of your project.
Lottie wrapper for React Native.
Pros of Lottie React Native
- Enables the use of complex animations in React Native apps
- Supports both iOS and Android platforms
- Provides a simple API for controlling animations
Cons of Lottie React Native
- Larger bundle size due to animation capabilities
- May require more system resources for complex animations
- Limited to animations created with Adobe After Effects
Code Comparison
Lottie React Native:
import LottieView from 'lottie-react-native';
<LottieView
source={require('./animation.json')}
autoPlay
loop
/>
React Native Testing Library:
import { render, fireEvent } from '@testing-library/react-native';
test('button press', () => {
const { getByText } = render(<MyComponent />);
fireEvent.press(getByText('Press me'));
});
Summary
Lottie React Native is focused on adding high-quality animations to React Native apps, while React Native Testing Library is designed for testing React Native components. Lottie offers rich animation capabilities but may increase app size and resource usage. React Native Testing Library provides a lightweight testing solution but doesn't add visual enhancements to the app. The choice between these libraries depends on whether the primary need is for animations or testing in a React Native project.
React Native Mapview component for iOS + Android
Pros of react-native-maps
- Provides a comprehensive mapping solution specifically for React Native applications
- Offers a wide range of customization options for map markers, polygons, and overlays
- Supports both iOS and Android platforms with native map implementations
Cons of react-native-maps
- Larger package size and potential performance impact due to its comprehensive feature set
- May require additional setup and configuration compared to simpler mapping solutions
- Limited to mapping functionality, whereas react-native-testing-library is a general-purpose testing tool
Code Comparison
react-native-maps:
import MapView, { Marker } from 'react-native-maps';
<MapView
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
<Marker coordinate={{ latitude: 37.78825, longitude: -122.4324 }} />
</MapView>
react-native-testing-library:
import { render, fireEvent } from '@testing-library/react-native';
const { getByTestId } = render(<MyComponent />);
const button = getByTestId('my-button');
fireEvent.press(button);
While react-native-maps focuses on providing mapping functionality, react-native-testing-library is designed for testing React Native components. The code examples demonstrate their distinct purposes and usage patterns.
A complete native navigation solution for React Native
Pros of React Native Navigation
- Provides a native navigation solution with better performance and smoother transitions
- Offers more advanced navigation features like deep linking and custom transitions
- Supports both iOS and Android platforms with native implementations
Cons of React Native Navigation
- Steeper learning curve due to its more complex API and setup process
- Requires additional native code integration, which can be challenging for some developers
- May have compatibility issues with certain React Native versions or other libraries
Code Comparison
React Native Navigation:
Navigation.setRoot({
root: {
stack: {
children: [
{ component: { name: 'Home' } }
]
}
}
});
React Native Testing Library:
import { render, fireEvent } from '@testing-library/react-native';
test('renders correctly', () => {
const { getByText } = render(<MyComponent />);
const element = getByText('Hello, World!');
expect(element).toBeTruthy();
});
Summary
React Native Navigation is a powerful navigation solution for React Native apps, offering native performance and advanced features. However, it comes with a steeper learning curve and more complex setup compared to React Native Testing Library. The latter focuses on testing React Native components and is generally easier to integrate into existing projects. While React Native Navigation handles app navigation, React Native Testing Library provides tools for testing UI components and user interactions.
React Native's Animated library reimplemented
Pros of React Native Reanimated
- Provides a powerful and flexible animation system for React Native
- Offers better performance for complex animations by running them on the native thread
- Supports gesture-based animations and interactions
Cons of React Native Reanimated
- Steeper learning curve compared to React Native Testing Library
- Requires additional setup and configuration
- May introduce complexity for simple animation tasks
Code Comparison
React Native Reanimated:
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
const animatedStyles = useAnimatedStyle(() => {
return { transform: [{ translateX: withSpring(offset.value * 255) }] };
});
React Native Testing Library:
import { render, fireEvent } from '@testing-library/react-native';
test('button press increments counter', () => {
const { getByText } = render(<Counter />);
fireEvent.press(getByText('Increment'));
expect(getByText('Count: 1')).toBeTruthy();
});
While React Native Reanimated focuses on creating smooth and performant animations, React Native Testing Library is designed for testing React Native components. The code examples highlight their different purposes, with Reanimated demonstrating animation creation and Testing Library showing component interaction testing.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
React Native Testing Library
Developer-friendly and complete React Native testing utilities that encourage good testing practices.
The problem
You want to write maintainable tests for your React Native components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your tests to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down.
This solution
The React Native Testing Library (RNTL) is a comprehensive solution for testing React Native components. It provides React Native runtime simulation on top of react-test-renderer
, in a way that encourages better testing practices. Its primary guiding principle is:
The more your tests resemble the way your software is used, the more confidence they can give you.
This project is inspired by React Testing Library. Tested to work with Jest, but it should work with other test runners as well.
Installation
Open a Terminal in your project's folder and run:
# Yarn install:
yarn add --dev @testing-library/react-native
# NPM install
npm install --save-dev @testing-library/react-native
This library has a peerDependencies
listing for react-test-renderer
. Make sure that your react-test-renderer
version matches exactly the react
version, avoid using ^
in version number.
Additional Jest matchers
You can use the built-in Jest matchers by adding the following line to your jest-setup.ts
file (configured using setupFilesAfterEnv
):
import '@testing-library/react-native/extend-expect';
Example
import { render, screen, fireEvent } from '@testing-library/react-native';
import { QuestionsBoard } from '../QuestionsBoard';
// It is recommended to use userEvent with fake timers
// Some events involve duration so your tests may take a long time to run.
jest.useFakeTimers();
test('form submits two answers', async () => {
const questions = ['q1', 'q2'];
const onSubmit = jest.fn();
const user = userEvent.setup();
render(<QuestionsBoard questions={questions} onSubmit={onSubmit} />);
const answerInputs = screen.getAllByLabelText('answer input');
// simulates the user focusing on TextInput and typing text one char at a time
await user.type(answerInputs[0], 'a1');
await user.type(answerInputs[1], 'a2');
// simulates the user pressing on any pressable element
await user.press(screen.getByRole('button', { name: 'Submit' }));
expect(onSubmit).toHaveBeenCalledWith({
1: { q: 'q1', a: 'a1' },
2: { q: 'q2', a: 'a2' },
});
});
You can find the source of QuestionsBoard
component and this example here.
API / Usage
React Native Testing Library consists of following APIs:
render
function - render your UI components for testing purposesscreen
object - access rendered UI:- Jest matchers - validate assumptions about your UI
- User Event - simulate common user interactions like
press
ortype
in a realistic way - Fire Event - simulate any component event in a simplified way
renderHook
function - render hooks for testing purposes- Miscellaneous APIs:
- Async utils:
findBy*
queries,waitFor
,waitForElementToBeRemoved
- Configuration:
configure
,resetToDefaults
- Accessibility:
isHiddenFromAccessibility
- Other:
within
,act
,cleanup
- Async utils:
Migration Guides
Troubleshooting
Community Resources
Check out our list of Community Resources about RNTL.
Made with â¤ï¸ at Callstack
React Native Testing Library is an open source project and will always remain free to use. If you think it's cool, please star it ð. Callstack is a group of React and React Native geeks, contact us at hello@callstack.com if you need any help with these or just want to say hi!
Like the project? âï¸ Join the team who does amazing stuff for clients and drives React Native Open Source! ð¥
Supported and used by Rally Health.
Top Related Projects
A framework for building native applications using React
Gray box end-to-end testing and automation framework for mobile apps
Lottie wrapper for React Native.
React Native Mapview component for iOS + Android
A complete native navigation solution for React Native
React Native's Animated library reimplemented
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot