diff --git a/src/__tests__/to-be-visible.tsx b/src/__tests__/to-be-visible.tsx
index 281c02a..cffe95e 100644
--- a/src/__tests__/to-be-visible.tsx
+++ b/src/__tests__/to-be-visible.tsx
@@ -124,7 +124,7 @@ describe('.toBeVisible', () => {
expect(() => expect(null).toBeVisible()).toThrowErrorMatchingInlineSnapshot(`
"expect(received).toBeVisible()
- received value must be a React Element.
+ received value must be a host element or composite Text/TextInput element
Received has value: null"
`);
});
diff --git a/src/__tests__/to-have-text-content.tsx b/src/__tests__/to-have-text-content.tsx
index 3770d56..2893abf 100644
--- a/src/__tests__/to-have-text-content.tsx
+++ b/src/__tests__/to-have-text-content.tsx
@@ -74,8 +74,8 @@ describe('.toHaveTextContent', () => {
test('can handle multiple levels with no explicit children prop', () => {
const NoChildren = ({ text }: { text: string }) => {text};
const answer = 'Answer';
- const { container } = render(
-
+ const { getByTestId } = render(
+
{answer}
{': '}
@@ -86,7 +86,7 @@ describe('.toHaveTextContent', () => {
,
);
- expect(container).toHaveTextContent(/^Answer: 42$/);
+ expect(getByTestId('subject')).toHaveTextContent(/^Answer: 42$/);
});
test('throws when no match is found', () => {
diff --git a/src/__tests__/utils.ts b/src/__tests__/utils.ts
index 298b492..29c622e 100644
--- a/src/__tests__/utils.ts
+++ b/src/__tests__/utils.ts
@@ -1,25 +1,67 @@
+import { View, Text, TextInput, Pressable, TouchableOpacity } from 'react-native';
import { checkReactElement, isEmpty } from '../utils';
describe('checkReactElement', () => {
- test('it does not throw an error for valid native primitives', () => {
- expect(() => {
- // @ts-expect-error Argument of type '{ type: "text"; }' is not assignable to parameter of type 'ReactTestInstance'. Type '{ type: "text"; }' is missing the following properties from type 'ReactTestInstance': instance, props, parent, children, and 6 more.ts(2345)
- checkReactElement({ type: 'Text' }, () => {}, null);
- }).not.toThrow();
+ test('ReactTestInstance does not throw for host elements', () => {
+ expect(() =>
+ // @ts-expect-error Passing incorrect Jest Matcher data
+ checkReactElement({ type: 'View' }, () => {}, {}),
+ ).not.toThrow();
+ expect(() =>
+ // @ts-expect-error Passing incorrect Jest Matcher data
+ checkReactElement({ type: 'TextInput' }, () => {}, {}),
+ ).not.toThrow();
+ expect(() =>
+ // @ts-expect-error Passing incorrect Jest Matcher data
+ checkReactElement({ type: 'View' }, () => {}, {}),
+ ).not.toThrow();
});
- test('ReactTestInstance does not throw', () => {
- expect(() => {
- // @ts-expect-error Argument of type '{ _fiber: {}; }' is not assignable to parameter of type 'ReactTestInstance'. Object literal may only specify known properties, and '_fiber' does not exist in type 'ReactTestInstance'.ts(2345)
- checkReactElement({ _fiber: {} }, () => {}, null);
- }).not.toThrow();
+ test('ReactTestInstance does not throw for composite Text elements', () => {
+ expect(() =>
+ // @ts-expect-error Passing incorrect Jest Matcher data
+ checkReactElement({ type: Text }, () => {}, {}),
+ ).not.toThrow();
});
- test('it does throw an error for invalid native primitives', () => {
- expect(() => {
- // @ts-expect-error Argument of type '{ type: "button"; }' is not assignable to parameter of type 'ReactTestInstance'. Type '{ type: "button"; }' is missing the following properties from type 'ReactTestInstance': instance, props, parent, children, and 6 more.ts(2345)
- checkReactElement({ type: 'Button' }, () => {}, null);
- }).toThrow();
+ test('ReactTestInstance does not throw for composite TextInput elements', () => {
+ expect(() =>
+ // @ts-expect-error Passing incorrect Jest Matcher data
+ checkReactElement({ type: TextInput }, () => {}, {}),
+ ).not.toThrow();
+ });
+
+ test('it does throw for composite elements', () => {
+ expect(() =>
+ // @ts-expect-error Incorrect Test Renderer typings
+ checkReactElement({ type: View }, () => {}, {}),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ "expect(received).()
+
+ received value must be a host element or composite Text/TextInput element
+ Received has type: object
+ Received has value: {"type": [Function Component]}"
+ `);
+ expect(() =>
+ // @ts-expect-error Incorrect Test Renderer typings
+ checkReactElement({ type: Pressable }, () => {}, {}),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ "expect(received).()
+
+ received value must be a host element or composite Text/TextInput element
+ Received has type: object
+ Received has value: {"type": {"$$typeof": Symbol(react.memo), "compare": null, "type": {"$$typeof": Symbol(react.forward_ref), "render": [Function Pressable]}}}"
+ `);
+ expect(() =>
+ // @ts-expect-error Incorrect Test Renderer typings
+ checkReactElement({ type: TouchableOpacity }, () => {}, {}),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ "expect(received).()
+
+ received value must be a host element or composite Text/TextInput element
+ Received has type: object
+ Received has value: {"type": {"$$typeof": Symbol(react.forward_ref), "render": [Function anonymous]}}"
+ `);
});
});
diff --git a/src/utils.ts b/src/utils.ts
index f591dba..b83b07d 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,3 +1,5 @@
+import { Text, TextInput } from 'react-native';
+import type { ReactTestInstance } from 'react-test-renderer';
import redent from 'redent';
import {
RECEIVED_COLOR as receivedColor,
@@ -8,23 +10,10 @@ import {
stringify,
} from 'jest-matcher-utils';
import prettyFormat, { plugins } from 'pretty-format';
-import type { ReactTestInstance } from 'react-test-renderer';
+import { isHostElement } from './component-tree';
const { ReactTestComponent, ReactElement } = plugins;
-const VALID_ELEMENTS = [
- 'Image',
- 'Text',
- 'TextInput',
- 'Modal',
- 'View',
- 'RefreshControl',
- 'ScrollView',
- 'ActivityIndicator',
- 'ListView',
- 'ListViewDataSource',
-];
-
class ReactElementTypeError extends Error {
constructor(received: unknown, matcherFn: jest.CustomMatcher, context: jest.MatcherContext) {
super();
@@ -44,7 +33,9 @@ class ReactElementTypeError extends Error {
this.message = [
matcherHint(`${context.isNot ? '.not' : ''}.${matcherFn.name}`, 'received', ''),
'',
- `${receivedColor('received')} value must be a React Element.`,
+ `${receivedColor(
+ 'received',
+ )} value must be a host element or composite Text/TextInput element`,
withType,
].join('\n');
}
@@ -59,8 +50,7 @@ function checkReactElement(
throw new ReactElementTypeError(element, matcherFn, context);
}
- // @ts-expect-error internal _fiber property of ReactTestInstance
- if (!element._fiber && !VALID_ELEMENTS.includes(element.type.toString())) {
+ if (!isHostElement(element) && element.type !== Text && element.type !== TextInput) {
throw new ReactElementTypeError(element, matcherFn, context);
}
}