Skip to content

Commit d55ea0b

Browse files
authored
feat: RegExp support for *ByTestId queries (#535)
* getAllByTestId supports a regex matcher * update typings * docs: update * refactor types * refactor. remove unnecessary try/catch * refactor test assertions
1 parent e0359c6 commit d55ea0b

File tree

7 files changed

+41
-16
lines changed

7 files changed

+41
-16
lines changed

src/__tests__/getByApi.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,18 @@ test('getByTestId returns only native elements', () => {
3535
'No instances found with testID: myComponent'
3636
);
3737
});
38+
39+
test('supports a regex matcher', () => {
40+
const { getByTestId, getAllByTestId } = render(
41+
<View>
42+
<Text testID="text">Text</Text>
43+
<TextInput testID="textInput" />
44+
<View testID="view" />
45+
<Button testID="button" title="Button" onPress={jest.fn()} />
46+
<MyComponent testID="myComponent" />
47+
</View>
48+
);
49+
50+
expect(getByTestId(/view/)).toBeTruthy();
51+
expect(getAllByTestId(/text/)).toHaveLength(2);
52+
});

src/helpers/findByAPI.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ const makeFindQuery = <Text, Result>(
2121
): Promise<Result> => waitFor(() => getQuery(instance)(text), waitForOptions);
2222

2323
export const findByTestId = (instance: ReactTestInstance) => (
24-
testId: string,
24+
testId: string | RegExp,
2525
waitForOptions: WaitForOptions = {}
2626
) => makeFindQuery(instance, getByTestId, testId, waitForOptions);
2727

2828
export const findAllByTestId = (instance: ReactTestInstance) => (
29-
testId: string,
29+
testId: string | RegExp,
3030
waitForOptions: WaitForOptions = {}
3131
) => makeFindQuery(instance, getAllByTestId, testId, waitForOptions);
3232

src/helpers/getByAPI.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ const getTextInputNodeByDisplayValue = (node, value) => {
8989
}
9090
};
9191

92+
const getNodeByTestId = (node, testID) => {
93+
return typeof testID === 'string'
94+
? testID === node.props.testID
95+
: testID.test(node.props.testID);
96+
};
97+
9298
export const getByText = (instance: ReactTestInstance) =>
9399
function getByTextFn(text: string | RegExp) {
94100
try {
@@ -124,7 +130,7 @@ export const getByDisplayValue = (instance: ReactTestInstance) =>
124130
};
125131

126132
export const getByTestId = (instance: ReactTestInstance) =>
127-
function getByTestIdFn(testID: string) {
133+
function getByTestIdFn(testID: string | RegExp) {
128134
try {
129135
const results = getAllByTestId(instance)(testID);
130136
if (results.length === 1) {
@@ -183,9 +189,9 @@ export const getAllByDisplayValue = (instance: ReactTestInstance) =>
183189
};
184190

185191
export const getAllByTestId = (instance: ReactTestInstance) =>
186-
function getAllByTestIdFn(testID: string): ReactTestInstance[] {
192+
function getAllByTestIdFn(testID: string | RegExp): ReactTestInstance[] {
187193
const results = instance
188-
.findAllByProps({ testID })
194+
.findAll((node) => getNodeByTestId(node, testID))
189195
.filter((element) => typeof element.type === 'string');
190196

191197
if (results.length === 0) {

src/helpers/queryByAPI.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const queryByDisplayValue = (instance: ReactTestInstance) =>
4848
};
4949

5050
export const queryByTestId = (instance: ReactTestInstance) =>
51-
function queryByTestIdFn(testID: string) {
51+
function queryByTestIdFn(testID: string | RegExp) {
5252
try {
5353
return getByTestId(instance)(testID);
5454
} catch (error) {
@@ -87,7 +87,7 @@ export const queryAllByDisplayValue = (instance: ReactTestInstance) => (
8787
};
8888

8989
export const queryAllByTestId = (instance: ReactTestInstance) => (
90-
testID: string
90+
testID: string | RegExp
9191
) => {
9292
try {
9393
return getAllByTestId(instance)(testID);

typings/__tests__/index.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const getBy: ReactTestInstance[] = [
4141
tree.getByDisplayValue('my value'),
4242
tree.getByDisplayValue(/value/g),
4343
tree.getByTestId('test-id'),
44+
tree.getByTestId(/test-id/),
4445
tree.getByA11yLabel('label'),
4546
tree.getByLabelText('label'),
4647
tree.getByA11yHint('label'),
@@ -64,6 +65,7 @@ const getAllBy: ReactTestInstance[][] = [
6465
tree.getAllByDisplayValue('my value'),
6566
tree.getAllByDisplayValue(/value/g),
6667
tree.getAllByTestId('test-id'),
68+
tree.getAllByTestId(/value/g),
6769
tree.getAllByA11yLabel('label'),
6870
tree.getAllByLabelText('label'),
6971
tree.getAllByA11yHint('label'),
@@ -88,6 +90,7 @@ const queryBy: Array<ReactTestInstance | null> = [
8890
tree.queryByDisplayValue('my value'),
8991
tree.queryByDisplayValue(/value/g),
9092
tree.queryByTestId('test-id'),
93+
tree.queryByTestId(/test-id/),
9194
tree.queryByA11yHint('label'),
9295
tree.queryByHintText('label'),
9396
tree.queryByA11yLabel('label'),
@@ -111,6 +114,7 @@ const queryAllBy: ReactTestInstance[][] = [
111114
tree.queryAllByDisplayValue('my value'),
112115
tree.queryAllByDisplayValue(/value/g),
113116
tree.queryAllByTestId('test-id'),
117+
tree.queryAllByTestId(/test-id/),
114118
tree.queryAllByA11yLabel('label'),
115119
tree.queryAllByLabelText('label'),
116120
tree.queryAllByA11yHint('label'),
@@ -141,7 +145,7 @@ const findBy: Promise<ReactTestInstance>[] = [
141145
tree.findByDisplayValue(/value/g),
142146
tree.findByDisplayValue(/value/g, { timeout: 10, interval: 10 }),
143147
tree.findByTestId('test-id'),
144-
tree.findByTestId('test-id', { timeout: 10, interval: 10 }),
148+
tree.findByTestId(/test-id/, { timeout: 10, interval: 10 }),
145149
tree.findByA11yLabel('label'),
146150
tree.findByA11yLabel('label', { timeout: 10, interval: 10 }),
147151
tree.findByLabelText('label'),
@@ -177,7 +181,7 @@ const findAllBy: Promise<ReactTestInstance[]>[] = [
177181
tree.findAllByDisplayValue(/View/g),
178182
tree.findAllByDisplayValue(/View/g, { timeout: 10, interval: 10 }),
179183
tree.findAllByTestId('test-id'),
180-
tree.findAllByTestId('test-id', { timeout: 10, interval: 10 }),
184+
tree.findAllByTestId(/test-id/, { timeout: 10, interval: 10 }),
181185
tree.findAllByA11yLabel('label'),
182186
tree.findAllByA11yLabel('label', { timeout: 10, interval: 10 }),
183187
tree.findAllByLabelText('label'),

typings/index.d.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ interface GetByAPI {
1818
getByText: (text: string | RegExp) => ReactTestInstance;
1919
getByPlaceholderText: (placeholder: string | RegExp) => ReactTestInstance;
2020
getByDisplayValue: (value: string | RegExp) => ReactTestInstance;
21-
getByTestId: (testID: string) => ReactTestInstance;
22-
getAllByTestId: (testID: string) => Array<ReactTestInstance>;
21+
getByTestId: (testID: string | RegExp) => ReactTestInstance;
22+
getAllByTestId: (testID: string | RegExp) => Array<ReactTestInstance>;
2323
getAllByText: (text: string | RegExp) => Array<ReactTestInstance>;
2424
getAllByPlaceholderText: (
2525
placeholder: string | RegExp
@@ -69,8 +69,8 @@ interface QueryByAPI {
6969
placeholder: string | RegExp
7070
) => ReactTestInstance | null;
7171
queryByDisplayValue: (value: string | RegExp) => ReactTestInstance | null;
72-
queryByTestId: (testID: string) => ReactTestInstance | null;
73-
queryAllByTestId: (testID: string) => Array<ReactTestInstance> | [];
72+
queryByTestId: (testID: string | RegExp) => ReactTestInstance | null;
73+
queryAllByTestId: (testID: string | RegExp) => Array<ReactTestInstance> | [];
7474
queryAllByText: (text: string | RegExp) => Array<ReactTestInstance> | [];
7575
queryAllByPlaceholderText: (
7676
placeholder: string | RegExp
@@ -137,7 +137,7 @@ interface FindByAPI {
137137
value: string | RegExp,
138138
waitForOptions?: WaitForOptions
139139
) => FindReturn;
140-
findByTestId: (testID: string, waitForOptions?: WaitForOptions) => FindReturn;
140+
findByTestId: (testID: string | RegExp, waitForOptions?: WaitForOptions) => FindReturn;
141141
findAllByText: (
142142
text: string | RegExp,
143143
waitForOptions?: WaitForOptions
@@ -151,7 +151,7 @@ interface FindByAPI {
151151
waitForOptions?: WaitForOptions
152152
) => FindAllReturn;
153153
findAllByTestId: (
154-
testID: string,
154+
testID: string | RegExp,
155155
waitForOptions?: WaitForOptions
156156
) => FindAllReturn;
157157
}

website/docs/Queries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ const element = getByDisplayValue('username');
9898

9999
> getByTestId, getAllByTestId, queryByTestId, queryAllByTestId, findByTestId, findAllByTestId
100100
101-
Returns a `ReactTestInstance` with matching `testID` prop.
101+
Returns a `ReactTestInstance` with matching `testID` prop. `testID` – may be a string or a regular expression.
102102

103103
```jsx
104104
import { render } from '@testing-library/react-native';

0 commit comments

Comments
 (0)