diff --git a/src/helpers/__tests__/getTextContent.test.tsx b/src/helpers/__tests__/getTextContent.test.tsx
index e2f937c7d..76a9bd56c 100644
--- a/src/helpers/__tests__/getTextContent.test.tsx
+++ b/src/helpers/__tests__/getTextContent.test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Text } from 'react-native';
import render from '../../render';
-import { getTextContent } from '../getTextContent';
+import { getTextContent } from '../text-content';
test('getTextContent with simple content', () => {
const view = render(Hello world);
diff --git a/src/helpers/matchers/matchTextContent.ts b/src/helpers/matchers/matchTextContent.ts
index 4c025e6ac..182cb1469 100644
--- a/src/helpers/matchers/matchTextContent.ts
+++ b/src/helpers/matchers/matchTextContent.ts
@@ -1,6 +1,6 @@
import type { ReactTestInstance } from 'react-test-renderer';
import { matches, TextMatch, TextMatchOptions } from '../../matches';
-import { getTextContent } from '../getTextContent';
+import { getTextContent } from '../text-content';
/**
* Matches the given node's text content against string or regex matcher.
diff --git a/src/helpers/getTextContent.ts b/src/helpers/text-content.ts
similarity index 100%
rename from src/helpers/getTextContent.ts
rename to src/helpers/text-content.ts
diff --git a/src/matchers/__tests__/to-have-text-content.test.tsx b/src/matchers/__tests__/to-have-text-content.test.tsx
new file mode 100644
index 000000000..71e7b628b
--- /dev/null
+++ b/src/matchers/__tests__/to-have-text-content.test.tsx
@@ -0,0 +1,84 @@
+///
+
+import * as React from 'react';
+import { View, Text } from 'react-native';
+import { render, screen } from '../..';
+import '../extend-expect';
+
+test('toHaveTextContent() example test', () => {
+ render(
+
+ Hello World
+
+ );
+
+ const view = screen.getByTestId('view');
+ expect(view).toHaveTextContent('Hello World');
+ expect(view).not.toHaveTextContent('Hello there');
+});
+
+test('toHaveTextContent() handles positive test cases', () => {
+ render(Hello World);
+
+ const text = screen.getByTestId('text');
+ expect(text).toHaveTextContent('Hello World');
+ expect(text).toHaveTextContent('Hello', { exact: false });
+ expect(text).toHaveTextContent(/Hello World/);
+});
+
+test('toHaveTextContent() does exact match by default', () => {
+ render(Hello World);
+
+ const text = screen.getByTestId('text');
+ expect(text).toHaveTextContent('Hello World');
+ expect(text).not.toHaveTextContent('Hello');
+ expect(text).not.toHaveTextContent('World');
+});
+
+test('toHaveTextContent() handles nested text', () => {
+ render(
+
+ Hello React
+
+ );
+
+ const text = screen.getByTestId('text');
+ expect(text).toHaveTextContent('Hello React');
+});
+
+test('toHaveTextContent() negative test cases', () => {
+ render(Hello World);
+
+ const text = screen.getByTestId('text');
+ expect(text).not.toHaveTextContent(/Hello React/);
+ expect(() => expect(text).toHaveTextContent(/Hello React/))
+ .toThrowErrorMatchingInlineSnapshot(`
+ "expect(element).toHaveTextContent()
+
+ Expected element to have text content:
+ /Hello React/
+ Received:
+ Hello World"
+ `);
+
+ expect(text).not.toHaveTextContent('Yellow', { exact: false });
+ expect(() => expect(text).toHaveTextContent('Yellow', { exact: false }))
+ .toThrowErrorMatchingInlineSnapshot(`
+ "expect(element).toHaveTextContent()
+
+ Expected element to have text content:
+ Yellow
+ Received:
+ Hello World"
+ `);
+});
+
+test('toHaveTextContent() on null element', () => {
+ expect(() => expect(null).toHaveTextContent('Hello World'))
+ .toThrowErrorMatchingInlineSnapshot(`
+ "expect(received).toHaveTextContent()
+
+ received value must be a host element.
+ Received has value: null"
+ `);
+});
diff --git a/src/matchers/extend-expect.d.ts b/src/matchers/extend-expect.d.ts
index 16a31109e..d10520755 100644
--- a/src/matchers/extend-expect.d.ts
+++ b/src/matchers/extend-expect.d.ts
@@ -1,9 +1,10 @@
-import { TextMatch, TextMatchOptions } from '../matches';
+import type { TextMatch, TextMatchOptions } from '../matches';
export interface JestNativeMatchers {
toBeOnTheScreen(): R;
toBeEmptyElement(): R;
toHaveDisplayValue(expectedValue: TextMatch, options?: TextMatchOptions): R;
+ toHaveTextContent(expectedText: TextMatch, options?: TextMatchOptions): R;
}
// Implicit Jest global `expect`.
diff --git a/src/matchers/extend-expect.ts b/src/matchers/extend-expect.ts
index bf6b1bac5..188deaa6b 100644
--- a/src/matchers/extend-expect.ts
+++ b/src/matchers/extend-expect.ts
@@ -3,9 +3,11 @@
import { toBeOnTheScreen } from './to-be-on-the-screen';
import { toBeEmptyElement } from './to-be-empty-element';
import { toHaveDisplayValue } from './to-have-display-value';
+import { toHaveTextContent } from './to-have-text-content';
expect.extend({
toBeOnTheScreen,
toBeEmptyElement,
toHaveDisplayValue,
+ toHaveTextContent,
});
diff --git a/src/matchers/to-have-text-content.tsx b/src/matchers/to-have-text-content.tsx
new file mode 100644
index 000000000..373bfbff6
--- /dev/null
+++ b/src/matchers/to-have-text-content.tsx
@@ -0,0 +1,35 @@
+import type { ReactTestInstance } from 'react-test-renderer';
+import { matcherHint } from 'jest-matcher-utils';
+import { getTextContent } from '../helpers/text-content';
+import { TextMatch, TextMatchOptions, matches } from '../matches';
+import { checkHostElement, formatMessage } from './utils';
+
+export function toHaveTextContent(
+ this: jest.MatcherContext,
+ element: ReactTestInstance,
+ expectedText: TextMatch,
+ options?: TextMatchOptions
+) {
+ checkHostElement(element, toHaveTextContent, this);
+
+ const text = getTextContent(element);
+
+ return {
+ pass: matches(expectedText, text, options?.normalizer, options?.exact),
+ message: () => {
+ return [
+ formatMessage(
+ matcherHint(
+ `${this.isNot ? '.not' : ''}.toHaveTextContent`,
+ 'element',
+ ''
+ ),
+ `Expected element ${this.isNot ? 'not to' : 'to'} have text content`,
+ expectedText,
+ 'Received',
+ text
+ ),
+ ].join('\n');
+ },
+ };
+}