Custom jest matchers to test the state of React Native.
[](https://travis-ci.org/testing-library/jest-native)
[](https://codecov.io/github/testing-library/jest-native)
[](https://www.npmjs.com/package/@testing-library/jest-native)
[](http://www.npmtrends.com/@testing-library/jest-native)
[](https://github.com/testing-library/jest-native/blob/main/LICENSE)
[](#contributors)
[](http://makeapullrequest.com)
[](https://github.com/testing-library/jest-native/blob/main/CODE_OF_CONDUCT.md)
[](https://discord.gg/testing-library)
[](https://github.com/testing-library/jest-native/watchers)
[](https://github.com/testing-library/jest-native/stargazers)
## Table of Contents
- [The problem](#the-problem)
- [This solution](#this-solution)
- [Compatibility](#compatibility)
- [Installation](#installation)
- [Usage](#usage)
- [Matchers](#matchers)
- [`toBeDisabled`](#tobedisabled)
- [`toBeEnabled`](#tobeenabled)
- [`toBeEmptyElement`](#tobeemptyelement)
- [`toContainElement`](#tocontainelement)
- [`toBeOnTheScreen`](#tobeonthescreen)
- [`toHaveProp`](#tohaveprop)
- [`toHaveTextContent`](#tohavetextcontent)
- [`toHaveStyle`](#tohavestyle)
- [`toBeVisible`](#tobevisible)
- [`toHaveAccessibilityState`](#tohaveaccessibilitystate)
- [`toHaveAccessibilityValue`](#tohaveaccessibilityvalue)
- [Inspiration](#inspiration)
- [Other solutions](#other-solutions)
- [Contributors](#contributors)
## The problem
You want to use [jest](https://facebook.github.io/jest/) to write tests that assert various things
about the state of a React Native app. As part of that goal, you want to avoid all the repetitive
patterns that arise in doing so like checking for a native element's props, its text content, its
styles, and more.
## This solution
The `jest-native` library provides a set of custom jest matchers that you can use to extend jest.
These will make your tests more declarative, clear to read and to maintain.
## Compatibility
These matchers should, for the most part, be agnostic enough to work with any React Native testing
utilities, but they are primarily intended to be used with
[React Native Testing Library](https://github.com/callstack/react-native-testing-library). Any
issues raised with existing matchers or any newly proposed matchers must be viewed through
compatibility with that library and its guiding principles first.
## Installation
This module should be installed as one of your project's `devDependencies`:
#### Using `yarn`
```sh
yarn add --dev @testing-library/jest-native
```
#### Using `npm`
```sh
npm install --save-dev @testing-library/jest-native
```
You will need `react-test-renderer`, `react`, and `react-native` installed in order to use this
package.
## Usage
Import `@testing-library/jest-native/extend-expect` once (for instance in your
[tests setup file](https://jestjs.io/docs/configuration#setupfilesafterenv-array)) and you're good
to go:
```javascript
import '@testing-library/jest-native/extend-expect';
```
Alternatively, you can selectively import only the matchers you intend to use, and extend jest's
`expect` yourself:
```javascript
import { toBeEmptyElement, toHaveTextContent } from '@testing-library/jest-native';
expect.extend({ toBeEmptyElement, toHaveTextContent });
```
## Matchers
`jest-native` has only been tested to work with
[React Native Testing Library](https://github.com/callstack/react-native-testing-library). Keep in
mind that these queries are intended only to work with elements corresponding to
[host components](https://reactnative.dev/architecture/glossary#react-host-components-or-host-components).
### `toBeDisabled`
```javascript
toBeDisabled();
```
Check whether or not an element is disabled from a user perspective.
This matcher will check if the element or its parent has any of the following props :
- `disabled`
- `accessibilityState={{ disabled: true }}`
- `editable={false}` (for `TextInput` only)
#### Examples
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('button')).toBeDisabled();
expect(getByTestId('input')).toBeDisabled();
```
### `toBeEnabled`
```javascript
toBeEnabled();
```
Check whether or not an element is enabled from a user perspective.
Works similarly to `expect().not.toBeDisabled()`.
#### Examples
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('button')).toBeEnabled();
expect(getByTestId('input')).toBeEnabled();
```
### `toBeEmptyElement`
```javascript
toBeEmptyElement();
```
Check that the given element has no content.
#### Examples
```javascript
const { getByTestId } = render();
expect(getByTestId('empty')).toBeEmptyElement();
```
> **Note** This matcher has been previously named `toBeEmpty()`, but we changed that name in
> order to avoid conflict with Jest Extendend matcher with the
> [same name](https://github.com/jest-community/jest-extended#tobeempty).
### `toContainElement`
```typescript
toContainElement(element: ReactTestInstance | null);
```
Check if an element contains another element as a descendant. Again, will only work for native
elements.
#### Examples
```javascript
const { queryByTestId } = render(
,
);
const grandparent = queryByTestId('grandparent');
const parent = queryByTestId('parent');
const child = queryByTestId('child');
const textElement = queryByTestId('text-element');
expect(grandparent).toContainElement(parent);
expect(grandparent).toContainElement(child);
expect(grandparent).toContainElement(textElement);
expect(parent).toContainElement(child);
expect(parent).not.toContainElement(grandparent);
```
### `toBeOnTheScreen`
```ts
toBeOnTheScreen();
```
Check that the element is present in the element tree.
You can check that an already captured element has not been removed from the element tree.
> **Note** This matcher requires React Native Testing Library v10.1 or later, as it includes
> the `screen` object.
>
> **Note** If you're using React Native Testing Library v12 or later, you need to install Jest
> Native v5.4.2 or later.
#### Examples
```tsx
render(
,
);
const child = screen.getByTestId('child');
expect(child).toBeOnTheScreen();
screen.update();
expect(child).not.toBeOnTheScreen();
```
### `toHaveProp`
```typescript
toHaveProp(prop: string, value?: any);
```
Check that the element has a given prop.
You can optionally check that the attribute has a specific expected value.
#### Examples
```javascript
const { queryByTestId } = render(
text
,
);
expect(queryByTestId('button')).toHaveProp('accessible');
expect(queryByTestId('button')).not.toHaveProp('disabled');
expect(queryByTestId('button')).not.toHaveProp('title', 'ok');
```
### `toHaveTextContent`
```typescript
toHaveTextContent(text: string | RegExp, options?: { normalizeWhitespace: boolean });
```
Check if an element or its children have the supplied text.
This will perform a partial, case-sensitive match when a string match is provided. To perform a
case-insensitive match, you can use a `RegExp` with the `/i` modifier.
To enforce matching the complete text content, pass a `RegExp`.
#### Examples
```javascript
const { queryByTestId } = render(2);
expect(queryByTestId('count-value')).toHaveTextContent('2');
expect(queryByTestId('count-value')).toHaveTextContent(2);
expect(queryByTestId('count-value')).toHaveTextContent(/2/);
expect(queryByTestId('count-value')).not.toHaveTextContent('21');
```
### `toHaveStyle`
```typescript
toHaveStyle(style: object[] | object);
```
Check if an element has the supplied styles.
You can pass either an object of React Native style properties, or an array of objects with style
properties. You cannot pass properties from a React Native stylesheet.
#### Examples
```javascript
const styles = StyleSheet.create({ text: { fontSize: 16 } });
const { queryByText } = render(
Hello World
,
);
expect(getByText('Hello World')).toHaveStyle({ color: 'black' });
expect(getByText('Hello World')).toHaveStyle({ fontWeight: '600' });
expect(getByText('Hello World')).toHaveStyle({ fontSize: 16 });
expect(getByText('Hello World')).toHaveStyle([{ fontWeight: '600' }, { color: 'black' }]);
expect(getByText('Hello World')).toHaveStyle({ color: 'black', fontWeight: '600', fontSize: 16 });
expect(getByText('Hello World')).toHaveStyle({ transform: [{ scale: 2 }, { rotate: '45deg' }] });
expect(getByText('Hello World')).not.toHaveStyle({ color: 'white' });
expect(getByText('Hello World')).not.toHaveStyle({ transform: [{ scale: 2 }] });
expect(getByText('Hello World')).not.toHaveStyle({
transform: [{ rotate: '45deg' }, { scale: 2 }],
});
```
### `toBeVisible`
```typescript
toBeVisible();
```
Check that the given element is visible to the user.
An element is visible if **all** the following conditions are met:
- it does not have its style property `display` set to `none`.
- it does not have its style property `opacity` set to `0`.
- it is not a `Modal` component or it does not have the prop `visible` set to `false`.
- it is not hidden from accessibility as checked by
[`isHiddenFromAccessibility`](https://callstack.github.io/react-native-testing-library/docs/api/#ishiddenfromaccessibility)
function from React Native Testing Library
- its ancestor elements are also visible.
#### Examples
```javascript
const { getByTestId } = render();
expect(getByTestId('empty-view')).toBeVisible();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('view-with-opacity')).toBeVisible();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('empty-modal')).toBeVisible();
```
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('view-within-modal')).toBeVisible();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('invisible-view')).not.toBeVisible();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('display-none-view')).not.toBeVisible();
```
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('view-within-invisible-view')).not.toBeVisible();
```
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('view-within-display-none-view')).not.toBeVisible();
```
```javascript
const { getByTestId } = render(
,
);
// Children elements of not visible modals are not rendered.
expect(queryByTestId('view-within-modal')).toBeNull();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('not-visible-modal')).not.toBeVisible();
```
```javascript
const { getByTestId } = render();
expect(getByTestId('test')).not.toBeVisible();
```
```javascript
const { getByTestId } = render(
,
);
expect(getByTestId('test')).not.toBeVisible();
```
### `toHaveAccessibilityState`
```ts
toHaveAccessibilityState(state: {
disabled?: boolean;
selected?: boolean;
checked?: boolean | 'mixed';
busy?: boolean;
expanded?: boolean;
});
```
Check that the element has given accessibility state entries.
This check is based on `accessibilityState` prop but also takes into account the default entries
which have been found by experimenting with accessibility inspector and screen readers on both iOS
and Android.
Some state entries behave as if explicit `false` value is the same as not having given state entry,
so their default value is `false`:
- `disabled`
- `selected`
- `busy`
The remaining state entries behave as if explicit `false` value is different than not having given
state entry, so their default value is `undefined`:
- `checked`
- `expanded`
This matcher is compatible with `*ByRole` and `*ByA11State` queries from React Native Testing
Library.
#### Examples
```js
render();
// Single value match
expect(screen.getByTestId('view')).toHaveAccessibilityState({ expanded: true });
expect(screen.getByTestId('view')).toHaveAccessibilityState({ checked: true });
// Can match multiple entries
expect(screen.getByTestId('view')).toHaveAccessibilityState({ expanded: true, checked: true });
```
Default values handling:
```js
render();
// Matching states where default value is `false`
expect(screen.getByTestId('view')).toHaveAccessibilityState({ disabled: false });
expect(screen.getByTestId('view')).toHaveAccessibilityState({ selected: false });
expect(screen.getByTestId('view')).toHaveAccessibilityState({ busy: false });
// Matching states where default value is `undefined`
expect(screen.getByTestId('view')).not.toHaveAccessibilityState({ checked: false });
expect(screen.getByTestId('view')).not.toHaveAccessibilityState({ expanded: false });
```
### `toHaveAccessibilityValue`
```ts
toHaveAccessibilityValue(value: {
min?: number;
max?: number;
now?: number;
text?: string | RegExp;
});
```
Check that the element has given `accessibilityValue` prop entries.
This matcher is compatible with `*ByRole` and `*ByA11Value` queries from React Native Testing
Library.
#### Examples
```js
render();
const view = screen.getByTestId('view');
// Single value match
expect(view).toHaveAccessibilityValue({ now: 65 });
expect(view).toHaveAccessibilityValue({ max: 0 });
// Can match multiple entries
expect(view).toHaveAccessibilityValue({ min: 0, max: 100 });
expect(view).toHaveAccessibilityValue({ min: 0, max: 100, now: 65 });
// All specified entries need to match
expect(view).not.toHaveAccessibilityValue({ now: 45 });
expect(view).not.toHaveAccessibilityValue({ min: 20, max: 100, now: 65 });
```
```js
render();
const view = screen.getByTestId('view');
expect(view).toHaveAccessibilityValue({ text: 'Almost full' });
expect(view).toHaveAccessibilityValue({ text: /full/ });
```
## Inspiration
This library was made to be a companion for
[React Native Testing Library](https://github.com/callstack/react-native-testing-library).
It was inspired by [jest-dom](https://github.com/gnapse/jest-dom/), the companion library for
[DTL](https://github.com/kentcdodds/dom-testing-library/). We emulated as many of those helpers as
we could while keeping in mind the guiding principles.
## Other solutions
None known, [you can add the first](http://makeapullrequest.com)!
## Contributors
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):