Custom jest matchers to test the state of React Native
npx @tessl/cli install tessl/npm-testing-library--jest-native@5.4.0Jest Native provides custom Jest matchers specifically designed for testing React Native components and applications. It extends Jest's assertion capabilities with React Native-specific matchers that understand component states, accessibility properties, and React Native-specific behaviors like visibility, styling, and component hierarchy relationships.
npm install --save-dev @testing-library/jest-nativeimport '@testing-library/jest-native/extend-expect';For selective imports:
import { toBeDisabled, toHaveTextContent, toHaveStyle } from '@testing-library/jest-native';
expect.extend({ toBeDisabled, toHaveTextContent, toHaveStyle });import { render } from '@testing-library/react-native';
import '@testing-library/jest-native/extend-expect';
const MyComponent = () => (
<View>
<Text testID="greeting">Hello World</Text>
<TextInput testID="input" value="test" editable={false} />
<Button title="Submit" disabled={true} />
</View>
);
test('component rendering and states', () => {
const { getByTestId, getByText } = render(<MyComponent />);
// Text content assertion
expect(getByTestId('greeting')).toHaveTextContent('Hello World');
// Disabled state assertion
expect(getByTestId('input')).toBeDisabled();
expect(getByText('Submit')).toBeDisabled();
// Visibility assertion
expect(getByTestId('greeting')).toBeVisible();
});Jest Native extends Jest's expect object with custom matchers that work with ReactTestInstance objects from react-test-renderer. The matchers are designed to:
Test whether React Native elements are enabled or disabled based on component props and accessibility states.
/**
* Tests if a React Native element is disabled
*/
toBeDisabled(): jest.MatcherResult;
/**
* Tests if a React Native element is enabled (opposite of disabled)
*/
toBeEnabled(): jest.MatcherResult;Usage Examples:
// Button disabled state
expect(getByText('Submit')).toBeDisabled();
expect(getByText('Cancel')).toBeEnabled();
// TextInput editable state
expect(getByTestId('readonly-input')).toBeDisabled();
expect(getByTestId('editable-input')).toBeEnabled();
// Accessibility-based disabled state
expect(getByLabelText('Disabled Button')).toBeDisabled();Test whether React Native elements have specific content or are empty.
/**
* Tests if a React Native element has no children
*/
toBeEmptyElement(): jest.MatcherResult;
/**
* Tests if a React Native element has specific text content
* @param text - Text to match (string or regex)
*/
toHaveTextContent(text: string | RegExp): jest.MatcherResult;
/**
* @deprecated Use toBeEmptyElement instead
*/
toBeEmpty(): jest.MatcherResult;Usage Examples:
// Text content matching
expect(getByTestId('title')).toHaveTextContent('Welcome');
expect(getByTestId('description')).toHaveTextContent(/Hello.*World/);
// Empty element testing
expect(getByTestId('empty-container')).toBeEmptyElement();Test whether React Native elements are visible or present on the screen.
/**
* Tests if a React Native element is visible
*/
toBeVisible(): jest.MatcherResult;
/**
* Tests if a React Native element is present on the screen
*/
toBeOnTheScreen(): jest.MatcherResult;Usage Examples:
// Visibility testing
expect(getByTestId('modal')).toBeVisible();
expect(getByTestId('hidden-element')).not.toBeVisible();
// Screen presence testing
expect(getByTestId('rendered-component')).toBeOnTheScreen();Test parent-child relationships between React Native elements.
/**
* Tests if a React Native element contains another element
* @param element - The element to check for containment
*/
toContainElement(element: ReactTestInstance | null): jest.MatcherResult;Usage Examples:
// Element containment
const container = getByTestId('container');
const child = getByTestId('child');
expect(container).toContainElement(child);
// Nested component testing
const form = getByTestId('form');
const submitButton = getByText('Submit');
expect(form).toContainElement(submitButton);Test React Native element props and styling.
/**
* Tests if a React Native element has a specific prop with optional value check
* @param attr - Property name to check
* @param value - Expected value of the property (optional)
*/
toHaveProp(attr: string, value?: unknown): jest.MatcherResult;
/**
* Tests if a React Native element has specific styles
* @param style - Style object to match
*/
toHaveStyle(style: StyleProp<ViewStyle | TextStyle | ImageStyle>): jest.MatcherResult;Usage Examples:
// Prop testing
expect(getByTestId('input')).toHaveProp('placeholder', 'Enter text');
expect(getByTestId('image')).toHaveProp('source');
// Style testing
expect(getByTestId('title')).toHaveStyle({
fontSize: 24,
fontWeight: 'bold',
color: '#333'
});
expect(getByTestId('container')).toHaveStyle({
flexDirection: 'row',
justifyContent: 'center'
});Test React Native accessibility states and values.
/**
* Tests if a React Native element has specific accessibility state
* @param state - Expected accessibility state object
*/
toHaveAccessibilityState(state: AccessibilityState): jest.MatcherResult;
/**
* Tests if a React Native element has specific accessibility value
* @param value - Expected accessibility value matcher
*/
toHaveAccessibilityValue(value: AccessibilityValueMatcher): jest.MatcherResult;Usage Examples:
// Accessibility state testing
expect(getByLabelText('Toggle')).toHaveAccessibilityState({
disabled: false,
selected: true
});
expect(getByTestId('checkbox')).toHaveAccessibilityState({
checked: true
});
// Accessibility value testing
expect(getByLabelText('Volume')).toHaveAccessibilityValue({
min: 0,
max: 100,
now: 50
});
expect(getByLabelText('Progress')).toHaveAccessibilityValue({
text: '50% complete'
});/**
* Accessibility value matcher interface
*/
interface AccessibilityValueMatcher {
min?: number;
max?: number;
now?: number;
text?: string | RegExp;
}
/**
* Jest Native matchers interface
*/
interface JestNativeMatchers<R> {
toBeDisabled(): R;
toBeEmptyElement(): R;
toBeEnabled(): R;
toBeOnTheScreen(): R;
toBeVisible(): R;
toContainElement(element: ReactTestInstance | null): R;
toHaveTextContent(text: string | RegExp): R;
toHaveProp(attr: string, value?: unknown): R;
toHaveStyle(style: StyleProp<ViewStyle | TextStyle | ImageStyle>): R;
toHaveAccessibilityState(state: AccessibilityState): R;
toHaveAccessibilityValue(value: AccessibilityValueMatcher): R;
/** @deprecated Use toBeEmptyElement instead */
toBeEmpty(): R;
}// jest-setup.ts
import '@testing-library/jest-native/extend-expect';For compatibility with older Jest versions or specific configurations:
// jest-setup.ts
import '@testing-library/jest-native/legacy-extend-expect';This adds matchers with legacy_ prefix (e.g., legacy_toBeDisabled).
Add to declarations.d.ts:
/// <reference types="@testing-library/jest-native" />Or use the TypeScript Jest setup file approach shown above.
All matchers provide detailed error messages with:
.not)