Skip to content

Commit 5a41f40

Browse files
committed
feat: predicate query POC implementation
1 parent 64ff2d2 commit 5a41f40

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react';
2+
import { View, Text, TextInput, Button } from 'react-native';
3+
import { ReactTestInstance } from 'react-test-renderer';
4+
import { render } from '../..';
5+
6+
test('getByPredicate returns only native elements', () => {
7+
const testIdPredicate = (testID: string) => (node: ReactTestInstance) => {
8+
return node.props.testID === testID;
9+
};
10+
11+
const { getByPredicate, getAllByPredicate } = render(
12+
<View>
13+
<Text testID="text">Text</Text>
14+
<TextInput testID="textInput" />
15+
<View testID="view" />
16+
<Button testID="button" title="Button" onPress={jest.fn()} />
17+
</View>
18+
);
19+
20+
expect(getByPredicate(testIdPredicate('text'))).toBeTruthy();
21+
expect(getByPredicate(testIdPredicate('textInput'))).toBeTruthy();
22+
expect(getByPredicate(testIdPredicate('view'))).toBeTruthy();
23+
expect(getByPredicate(testIdPredicate('button'))).toBeTruthy();
24+
25+
expect(getAllByPredicate(testIdPredicate('text'))).toHaveLength(1);
26+
expect(getAllByPredicate(testIdPredicate('textInput'))).toHaveLength(1);
27+
expect(getAllByPredicate(testIdPredicate('view'))).toHaveLength(1);
28+
expect(getAllByPredicate(testIdPredicate('button'))).toHaveLength(1);
29+
30+
expect(() => getByPredicate(testIdPredicate('myComponent'))).toThrowError(
31+
/^Unable to find an element matching predicate: /i
32+
);
33+
expect(() => getAllByPredicate(testIdPredicate('myComponent'))).toThrowError(
34+
/^Unable to find an element matching predicate: /i
35+
);
36+
});

src/queries/predicate.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { ReactTestInstance } from 'react-test-renderer';
2+
import { makeQueries } from './makeQueries';
3+
import type {
4+
FindAllByQuery,
5+
FindByQuery,
6+
GetAllByQuery,
7+
GetByQuery,
8+
QueryAllByQuery,
9+
QueryByQuery,
10+
} from './makeQueries';
11+
12+
type PredicateFn = (instance: ReactTestInstance) => boolean;
13+
// Not used so far
14+
type PredicateQueryOptions = void;
15+
16+
const queryAllByPredicate = (
17+
instance: ReactTestInstance
18+
): ((
19+
predicate: PredicateFn,
20+
options?: PredicateQueryOptions
21+
) => Array<ReactTestInstance>) =>
22+
function queryAllByTestIdFn(predicate) {
23+
const results = instance.findAll(
24+
(node) => typeof node.type === 'string' && predicate(node)
25+
);
26+
27+
return results;
28+
};
29+
30+
const getMultipleError = (predicate: PredicateFn) =>
31+
`Found multiple elements matching predicate: ${predicate}`;
32+
33+
const getMissingError = (predicate: PredicateFn) =>
34+
`Unable to find an element matching predicate: ${predicate}`;
35+
36+
const { getBy, getAllBy, queryBy, queryAllBy, findBy, findAllBy } = makeQueries(
37+
queryAllByPredicate,
38+
getMissingError,
39+
getMultipleError
40+
);
41+
42+
export type ByTestIdQueries = {
43+
getByPredicate: GetByQuery<PredicateFn, PredicateQueryOptions>;
44+
getAllByPredicate: GetAllByQuery<PredicateFn, PredicateQueryOptions>;
45+
queryByPredicate: QueryByQuery<PredicateFn, PredicateQueryOptions>;
46+
queryAllByPredicate: QueryAllByQuery<PredicateFn, PredicateQueryOptions>;
47+
findByPredicate: FindByQuery<PredicateFn, PredicateQueryOptions>;
48+
findAllByPredicate: FindAllByQuery<PredicateFn, PredicateQueryOptions>;
49+
};
50+
51+
export const bindByPredicateQueries = (
52+
instance: ReactTestInstance
53+
): ByTestIdQueries => ({
54+
getByPredicate: getBy(instance),
55+
getAllByPredicate: getAllBy(instance),
56+
queryByPredicate: queryBy(instance),
57+
queryAllByPredicate: queryAllBy(instance),
58+
findByPredicate: findBy(instance),
59+
findAllByPredicate: findAllBy(instance),
60+
});

src/within.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import { bindByDisplayValueQueries } from './queries/displayValue';
66
import { bindByPlaceholderTextQueries } from './queries/placeholderText';
77
import { bindUnsafeByTypeQueries } from './queries/unsafeType';
88
import { bindUnsafeByPropsQueries } from './queries/unsafeProps';
9+
import { bindByPredicateQueries } from './queries/predicate';
910

1011
export function within(instance: ReactTestInstance) {
1112
return {
1213
...bindByTextQueries(instance),
1314
...bindByTestIdQueries(instance),
1415
...bindByDisplayValueQueries(instance),
1516
...bindByPlaceholderTextQueries(instance),
17+
...bindByPredicateQueries(instance),
1618
...bindUnsafeByTypeQueries(instance),
1719
...bindUnsafeByPropsQueries(instance),
1820
...a11yAPI(instance),

0 commit comments

Comments
 (0)