RNTL exposes the render function as the primary entry point for tests. If you make complex, repeating setups for your tests, consider creating a custom render function. The idea is to encapsulate common setup steps and test wiring inside a render function suitable for your tests.
// ...
interface RenderWithProvidersProps {
user?: User | null;
theme?: Theme;
}
export async function renderWithProviders<T>(
ui: React.ReactElement<T>,
options?: RenderWithProvidersProps
) {
return await render(
<UserProvider.Provider value={options?.user ?? null}>
<ThemeProvider.Provider value={options?.theme ?? 'light'}>{ui}</ThemeProvider.Provider>
</UserProvider.Provider>
);
}import { screen } from '@testing-library/react-native';
import { renderWithProviders } from '../test-utils';
// ...
test('renders WelcomeScreen with user', async () => {
await renderWithProviders(<WelcomeScreen />, { user: { name: 'Jar-Jar' } });
expect(screen.getByText(/hello Jar-Jar/i)).toBeOnTheScreen();
});
test('renders WelcomeScreen without user', async () => {
await renderWithProviders(<WelcomeScreen />, { user: null });
expect(screen.getByText(/hello stranger/i)).toBeOnTheScreen();
});Example full source code.
A custom render function might accept additional parameters to allow for setting up different start conditions for a test, e.g., the initial state for global state management.
test('renders SomeScreen for logged in user', async () => {
await renderScreen(<SomeScreen />, { state: loggedInState });
// ...
});Depending on the situation, you may declare more than one custom render function. For example, you have one function for testing application flows and a second for testing individual screens.
function renderNavigator(ui, options);
function renderScreen(ui, options);Since render is async, your custom render function should be marked as async and use await render(). This pattern also makes it easy to add additional async setup if needed:
async function renderWithData<T>(ui: React.ReactElement<T>) {
const data = await fetchTestData();
return await render(<DataProvider value={data}>{ui}</DataProvider>);
}
test('renders SomeScreen', async () => {
await renderWithData(<SomeScreen />);
// ...
});