Simple and complete React Native testing utilities that encourage good testing practices
—
Comprehensive system for finding elements in the rendered component tree using various strategies including text content, accessibility properties, test IDs, and component roles. All queries follow the getBy/getAllBy/queryBy/queryAllBy/findBy/findAllBy pattern.
Find elements by their text content - the most user-centric way to locate elements.
/**
* Find elements by text content
* @param text - Text content to search for (string or RegExp)
* @param options - Text matching options
* @returns Single element or array of elements
*/
function getByText(text: string | RegExp, options?: TextMatchOptions): ReactTestInstance;
function getAllByText(text: string | RegExp, options?: TextMatchOptions): ReactTestInstance[];
function queryByText(text: string | RegExp, options?: TextMatchOptions): ReactTestInstance | null;
function queryAllByText(text: string | RegExp, options?: TextMatchOptions): ReactTestInstance[];
function findByText(text: string | RegExp, options?: TextMatchOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByText(text: string | RegExp, options?: TextMatchOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface TextMatchOptions {
/** Whether to match exact text (default: true) */
exact?: boolean;
/** Function to normalize text before matching */
normalizer?: NormalizerFn;
/** Include elements hidden from accessibility (default: false) */
includeHiddenElements?: boolean;
}
type NormalizerFn = (text: string) => string;Usage Examples:
import { render, screen } from "@testing-library/react-native";
test("text queries", () => {
render(
<View>
<Text>Hello World</Text>
<Text>Welcome User</Text>
<Text>Submit</Text>
</View>
);
// Exact text match
const hello = screen.getByText("Hello World");
// Partial text match
const welcome = screen.getByText("Welcome", { exact: false });
// RegExp match
const submit = screen.getByText(/submit/i);
// Get all elements with text
const allTexts = screen.getAllByText(/Hello|Welcome/);
// Query without throwing
const missing = screen.queryByText("Not Found"); // returns null
// Async finding
const asyncText = await screen.findByText("Loaded Content");
});Find elements by their testID prop - reliable for testing purposes.
/**
* Find elements by testID prop
* @param testId - TestID to search for (string or RegExp)
* @param options - TestID matching options
* @returns Single element or array of elements
*/
function getByTestId(testId: string | RegExp, options?: TestIdOptions): ReactTestInstance;
function getAllByTestId(testId: string | RegExp, options?: TestIdOptions): ReactTestInstance[];
function queryByTestId(testId: string | RegExp, options?: TestIdOptions): ReactTestInstance | null;
function queryAllByTestId(testId: string | RegExp, options?: TestIdOptions): ReactTestInstance[];
function findByTestId(testId: string | RegExp, options?: TestIdOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByTestId(testId: string | RegExp, options?: TestIdOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface TestIdOptions {
exact?: boolean;
normalizer?: NormalizerFn;
includeHiddenElements?: boolean;
}Usage Examples:
test("testID queries", () => {
render(
<View>
<Pressable testID="submit-button">
<Text>Submit</Text>
</Pressable>
<TextInput testID="email-input" placeholder="Email" />
<View testID="user-card-1">
<Text>User 1</Text>
</View>
</View>
);
// Find by exact testID
const button = screen.getByTestId("submit-button");
const input = screen.getByTestId("email-input");
// Find by RegExp
const userCard = screen.getByTestId(/user-card-\d+/);
// Get all matching testIDs
const allUserCards = screen.getAllByTestId(/user-card/);
});Find elements by their accessibility role - follows ARIA patterns adapted for React Native.
/**
* Find elements by accessibility role
* @param role - Accessibility role to search for
* @param options - Role matching options
* @returns Single element or array of elements
*/
function getByRole(role: string, options?: RoleOptions): ReactTestInstance;
function getAllByRole(role: string, options?: RoleOptions): ReactTestInstance[];
function queryByRole(role: string, options?: RoleOptions): ReactTestInstance | null;
function queryAllByRole(role: string, options?: RoleOptions): ReactTestInstance[];
function findByRole(role: string, options?: RoleOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByRole(role: string, options?: RoleOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface RoleOptions {
/** Filter by accessible name */
name?: string | RegExp;
/** Include elements hidden from accessibility */
includeHiddenElements?: boolean;
/** Whether to match name exactly */
exact?: boolean;
/** Function to normalize accessible name */
normalizer?: NormalizerFn;
}Usage Examples:
test("role queries", () => {
render(
<View>
<Pressable role="button" accessibilityLabel="Submit Form">
<Text>Submit</Text>
</Pressable>
<TextInput
role="textbox"
accessibilityLabel="Email Address"
placeholder="Email"
/>
<View role="alert">
<Text>Error: Invalid email</Text>
</View>
</View>
);
// Find by role
const button = screen.getByRole("button");
const textbox = screen.getByRole("textbox");
const alert = screen.getByRole("alert");
// Find by role with name
const submitButton = screen.getByRole("button", { name: "Submit Form" });
const emailInput = screen.getByRole("textbox", { name: /email/i });
// Get all buttons
const allButtons = screen.getAllByRole("button");
});Find elements by their accessibility label - essential for accessible testing.
/**
* Find elements by accessibility label
* @param text - Label text to search for (string or RegExp)
* @param options - Label text matching options
* @returns Single element or array of elements
*/
function getByLabelText(text: string | RegExp, options?: LabelTextOptions): ReactTestInstance;
function getAllByLabelText(text: string | RegExp, options?: LabelTextOptions): ReactTestInstance[];
function queryByLabelText(text: string | RegExp, options?: LabelTextOptions): ReactTestInstance | null;
function queryAllByLabelText(text: string | RegExp, options?: LabelTextOptions): ReactTestInstance[];
function findByLabelText(text: string | RegExp, options?: LabelTextOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByLabelText(text: string | RegExp, options?: LabelTextOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface LabelTextOptions {
exact?: boolean;
normalizer?: NormalizerFn;
includeHiddenElements?: boolean;
}Usage Examples:
test("label text queries", () => {
render(
<View>
<TextInput
accessibilityLabel="Email Address"
placeholder="Enter email"
/>
<Pressable accessibilityLabel="Submit Form">
<Text>Submit</Text>
</Pressable>
<Switch accessibilityLabel="Enable Notifications" />
</View>
);
// Find by accessibility label
const emailInput = screen.getByLabelText("Email Address");
const submitButton = screen.getByLabelText("Submit Form");
const toggle = screen.getByLabelText("Enable Notifications");
// Partial label match
const emailField = screen.getByLabelText("Email", { exact: false });
// RegExp match
const formButton = screen.getByLabelText(/submit/i);
});Find elements by their accessibility hint with multiple aliases for convenience.
/**
* Find elements by accessibility hint
* @param text - Hint text to search for (string or RegExp)
* @param options - Hint text matching options
* @returns Single element or array of elements
*/
function getByHintText(text: string | RegExp, options?: HintTextOptions): ReactTestInstance;
function getAllByHintText(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function queryByHintText(text: string | RegExp, options?: HintTextOptions): ReactTestInstance | null;
function queryAllByHintText(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function findByHintText(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByHintText(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance[]>;
// Convenience aliases
function getByA11yHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance;
function getAllByA11yHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function queryByA11yHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance | null;
function queryAllByA11yHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function findByA11yHint(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByA11yHint(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance[]>;
function getByAccessibilityHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance;
function getAllByAccessibilityHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function queryByAccessibilityHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance | null;
function queryAllByAccessibilityHint(text: string | RegExp, options?: HintTextOptions): ReactTestInstance[];
function findByAccessibilityHint(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByAccessibilityHint(text: string | RegExp, options?: HintTextOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface HintTextOptions {
exact?: boolean;
normalizer?: NormalizerFn;
includeHiddenElements?: boolean;
}Usage Examples:
test("hint text queries", () => {
render(
<View>
<TextInput
accessibilityHint="Enter your email address for login"
placeholder="Email"
/>
<Pressable accessibilityHint="Tap to submit the form">
<Text>Submit</Text>
</Pressable>
</View>
);
// All three forms are equivalent
const emailInput1 = screen.getByHintText("Enter your email address for login");
const emailInput2 = screen.getByA11yHint("Enter your email address for login");
const emailInput3 = screen.getByAccessibilityHint("Enter your email address for login");
// Partial hint match
const submitButton = screen.getByHintText("Tap to submit", { exact: false });
// RegExp match
const formButton = screen.getByHintText(/submit.*form/i);
});Find form elements by their placeholder text.
/**
* Find elements by placeholder text
* @param text - Placeholder text to search for (string or RegExp)
* @param options - Placeholder text matching options
* @returns Single element or array of elements
*/
function getByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions): ReactTestInstance;
function getAllByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions): ReactTestInstance[];
function queryByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions): ReactTestInstance | null;
function queryAllByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions): ReactTestInstance[];
function findByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByPlaceholderText(text: string | RegExp, options?: PlaceholderTextOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface PlaceholderTextOptions {
exact?: boolean;
normalizer?: NormalizerFn;
includeHiddenElements?: boolean;
}Usage Examples:
test("placeholder text queries", () => {
render(
<View>
<TextInput placeholder="Enter your email" />
<TextInput placeholder="Password" />
<TextInput placeholder="Search users..." />
</View>
);
// Find by exact placeholder
const emailInput = screen.getByPlaceholderText("Enter your email");
const passwordInput = screen.getByPlaceholderText("Password");
// Partial match
const searchInput = screen.getByPlaceholderText("Search", { exact: false });
// RegExp match
const userSearch = screen.getByPlaceholderText(/search.*users/i);
// Get all inputs with placeholders
const allInputs = screen.getAllByPlaceholderText(/.+/);
});Find form elements by their current display value.
/**
* Find elements by their current display value
* @param value - Display value to search for (string or RegExp)
* @param options - Display value matching options
* @returns Single element or array of elements
*/
function getByDisplayValue(value: string | RegExp, options?: DisplayValueOptions): ReactTestInstance;
function getAllByDisplayValue(value: string | RegExp, options?: DisplayValueOptions): ReactTestInstance[];
function queryByDisplayValue(value: string | RegExp, options?: DisplayValueOptions): ReactTestInstance | null;
function queryAllByDisplayValue(value: string | RegExp, options?: DisplayValueOptions): ReactTestInstance[];
function findByDisplayValue(value: string | RegExp, options?: DisplayValueOptions & WaitForOptions): Promise<ReactTestInstance>;
function findAllByDisplayValue(value: string | RegExp, options?: DisplayValueOptions & WaitForOptions): Promise<ReactTestInstance[]>;
interface DisplayValueOptions {
exact?: boolean;
normalizer?: NormalizerFn;
includeHiddenElements?: boolean;
}Usage Examples:
test("display value queries", () => {
render(
<View>
<TextInput value="john@example.com" />
<TextInput value="123-456-7890" />
<Text>Current User: John Doe</Text>
</View>
);
// Find by exact value
const emailInput = screen.getByDisplayValue("john@example.com");
const phoneInput = screen.getByDisplayValue("123-456-7890");
// Find text by display value
const userText = screen.getByDisplayValue("Current User: John Doe");
// Partial match
const emailField = screen.getByDisplayValue("john", { exact: false });
// RegExp match
const phoneField = screen.getByDisplayValue(/\d{3}-\d{3}-\d{4}/);
});Advanced queries for finding elements by component type or props - use with caution as they test implementation details.
/**
* Find elements by component type - UNSAFE: tests implementation details
* @param type - Component type or string
* @param options - Type matching options
* @returns Single element or array of elements
*/
function UNSAFE_getByType(type: React.ComponentType | string, options?: TypeOptions): ReactTestInstance;
function UNSAFE_getAllByType(type: React.ComponentType | string, options?: TypeOptions): ReactTestInstance[];
function UNSAFE_queryByType(type: React.ComponentType | string, options?: TypeOptions): ReactTestInstance | null;
function UNSAFE_queryAllByType(type: React.ComponentType | string, options?: TypeOptions): ReactTestInstance[];
/**
* Find elements by props - UNSAFE: tests implementation details
* @param props - Props object to match
* @param options - Props matching options
* @returns Single element or array of elements
*/
function UNSAFE_getByProps(props: object, options?: PropsOptions): ReactTestInstance;
function UNSAFE_getAllByProps(props: object, options?: PropsOptions): ReactTestInstance[];
function UNSAFE_queryByProps(props: object, options?: PropsOptions): ReactTestInstance | null;
function UNSAFE_queryAllByProps(props: object, options?: PropsOptions): ReactTestInstance[];
interface TypeOptions {
includeHiddenElements?: boolean;
}
interface PropsOptions {
includeHiddenElements?: boolean;
}Usage Examples (Use Sparingly):
import { View, Text, TextInput } from "react-native";
test("unsafe queries - use with caution", () => {
render(
<View>
<TextInput style={{ fontSize: 16 }} />
<Text>Hello</Text>
<MyCustomComponent customProp="value" />
</View>
);
// Find by component type
const textInput = screen.UNSAFE_getByType(TextInput);
const textElement = screen.UNSAFE_getByType(Text);
const customComponent = screen.UNSAFE_getByType(MyCustomComponent);
// Find by props
const styledInput = screen.UNSAFE_getByProps({ style: { fontSize: 16 } });
const customPropComponent = screen.UNSAFE_getByProps({ customProp: "value" });
// Get all of specific type
const allTexts = screen.UNSAFE_getAllByType(Text);
});Scope queries to a specific element subtree for more targeted testing.
/**
* Create scoped queries for a specific element
* @param element - Element to scope queries to
* @returns Object with all query methods scoped to the element
*/
function within(element: ReactTestInstance): BoundQueries;
function getQueriesForElement(element: ReactTestInstance): BoundQueries; // Alias
interface BoundQueries {
// All the same query methods as screen/render result
// but scoped to the provided element
getByText: (text: string | RegExp, options?: TextMatchOptions) => ReactTestInstance;
getAllByText: (text: string | RegExp, options?: TextMatchOptions) => ReactTestInstance[];
// ... all other query methods
}Usage Examples:
import { render, screen, within } from "@testing-library/react-native";
test("scoped queries with within", () => {
render(
<View>
<View testID="user-card-1">
<Text>John Doe</Text>
<Text>john@example.com</Text>
<Pressable>
<Text>Edit</Text>
</Pressable>
</View>
<View testID="user-card-2">
<Text>Jane Smith</Text>
<Text>jane@example.com</Text>
<Pressable>
<Text>Edit</Text>
</Pressable>
</View>
</View>
);
// Scope queries to first user card
const userCard1 = screen.getByTestId("user-card-1");
const withinCard1 = within(userCard1);
// Find elements only within the first card
const johnName = withinCard1.getByText("John Doe");
const johnEmail = withinCard1.getByText("john@example.com");
const johnEditButton = withinCard1.getByText("Edit");
// Scope to second card
const userCard2 = screen.getByTestId("user-card-2");
const janeEditButton = within(userCard2).getByText("Edit");
});Common options and utilities used across all query types.
/**
* Get default text normalizer function
* @returns Default normalizer that trims whitespace and collapses spaces
*/
function getDefaultNormalizer(): NormalizerFn;
// Common interfaces used across queries
interface WaitForOptions {
/** Timeout in milliseconds (default from config) */
timeout?: number;
/** Polling interval in milliseconds (default: 50) */
interval?: number;
/** Custom timeout error handler */
onTimeout?: (error: Error) => Error;
}
type NormalizerFn = (text: string) => string;Usage Examples:
import { getDefaultNormalizer } from "@testing-library/react-native";
test("custom text normalization", () => {
const customNormalizer = (text: string) =>
text.toLowerCase().replace(/\s+/g, " ").trim();
render(<Text> Hello World </Text>);
// Using custom normalizer
const text = screen.getByText("hello world", {
exact: false,
normalizer: customNormalizer
});
// Using default normalizer explicitly
const defaultNormalizer = getDefaultNormalizer();
const text2 = screen.getByText("Hello World", {
normalizer: defaultNormalizer
});
});Install with Tessl CLI
npx tessl i tessl/npm-testing-library--react-native