@testing-library/react-native 7.2.0 → 9.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -3
- package/build/fireEvent.js +5 -13
- package/build/fireEvent.js.flow +5 -22
- package/build/flushMicroTasks.js +3 -1
- package/build/flushMicroTasks.js.flow +1 -0
- package/build/helpers/byDisplayValue.js +10 -4
- package/build/helpers/byDisplayValue.js.flow +15 -5
- package/build/helpers/byPlaceholderText.js +10 -4
- package/build/helpers/byPlaceholderText.js.flow +15 -7
- package/build/helpers/byTestId.js +10 -4
- package/build/helpers/byTestId.js.flow +11 -7
- package/build/helpers/byText.js +13 -6
- package/build/helpers/byText.js.flow +25 -9
- package/build/helpers/errors.js +2 -1
- package/build/helpers/errors.js.flow +1 -0
- package/build/helpers/findByAPI.js.flow +9 -0
- package/build/helpers/getByAPI.js.flow +31 -8
- package/build/helpers/makeQueries.js +40 -10
- package/build/helpers/makeQueries.js.flow +61 -10
- package/build/helpers/queryByAPI.js.flow +23 -8
- package/build/helpers/timers.js +77 -0
- package/build/helpers/timers.js.flow +88 -0
- package/build/matches.js +33 -0
- package/build/matches.js.flow +41 -0
- package/build/pure.js +8 -0
- package/build/pure.js.flow +2 -0
- package/build/render.js +9 -2
- package/build/render.js.flow +7 -2
- package/build/waitFor.js +147 -21
- package/build/waitFor.js.flow +154 -20
- package/jest-preset/index.js +10 -0
- package/jest-preset/restore-promise.js +1 -0
- package/jest-preset/save-promise.js +1 -0
- package/package.json +16 -11
- package/typings/index.d.ts +106 -51
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
height="80"
|
|
5
5
|
width="80"
|
|
6
6
|
alt="owl"
|
|
7
|
-
src="https://raw.githubusercontent.com/callstack/react-native-testing-library/
|
|
7
|
+
src="https://raw.githubusercontent.com/callstack/react-native-testing-library/main/website/static/img/owl.png"
|
|
8
8
|
/>
|
|
9
9
|
<p>Simple and complete React Native testing utilities that encourage good testing practices.</P>
|
|
10
10
|
</div>
|
|
@@ -46,7 +46,7 @@ npm install --save-dev @testing-library/react-native
|
|
|
46
46
|
|
|
47
47
|
This library has a peerDependencies listing for `react-test-renderer` and, of course, `react`. Make sure to install them too!
|
|
48
48
|
|
|
49
|
-
> In order to properly use helpers for async tests (`findBy` queries and `waitFor`) you need at least React >=16.9.0 (featuring async `act`) or React Native >=0.
|
|
49
|
+
> In order to properly use helpers for async tests (`findBy` queries and `waitFor`) you need at least React >=16.9.0 (featuring async `act`) or React Native >=0.61 (which comes with React >=16.9.0).
|
|
50
50
|
|
|
51
51
|
### Additional Jest matchers
|
|
52
52
|
|
|
@@ -73,6 +73,24 @@ Then automatically add it to your jest tests by using `setupFilesAfterEnv` optio
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
### Custom Jest Preset
|
|
77
|
+
|
|
78
|
+
> **important** if you use "modern" Fake Timers
|
|
79
|
+
|
|
80
|
+
We generally advise to use the "react-native" preset when testing with this library. However, if you use ["modern" Fake Timers](https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers) (default since Jest 27), you'll need to apply our custom Jest preset or awaiting promises, like `waitFor`, will timeout.
|
|
81
|
+
|
|
82
|
+
This is a [known issue](https://github.com/facebook/react-native/issues/29303). It happens because React Native's Jest preset overrides native Promise. Our preset restores it to defaults, which is not a problem in most apps out there.
|
|
83
|
+
|
|
84
|
+
Here's how you apply a custom preset in your Jest config:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"preset": "@testing-library/react-native"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If this doesn't work for you, please fall back to using "legacy" fake timers.
|
|
93
|
+
|
|
76
94
|
### Flow
|
|
77
95
|
|
|
78
96
|
Note for [Flow](https://flow.org) users – you'll also need to install typings for `react-test-renderer`:
|
|
@@ -108,7 +126,7 @@ test('form submits two answers', () => {
|
|
|
108
126
|
});
|
|
109
127
|
```
|
|
110
128
|
|
|
111
|
-
You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/
|
|
129
|
+
You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/main/src/__tests__/questionsBoard.test.js).
|
|
112
130
|
|
|
113
131
|
## API / Usage
|
|
114
132
|
|
|
@@ -135,6 +153,8 @@ The [public API](https://callstack.github.io/react-native-testing-library/docs/a
|
|
|
135
153
|
|
|
136
154
|
React Native Testing Library is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Callstack](https://callstack.com) is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi!
|
|
137
155
|
|
|
156
|
+
Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
|
|
157
|
+
|
|
138
158
|
---
|
|
139
159
|
|
|
140
160
|
Supported and used by [Rally Health](https://www.rallyhealth.com/careers-home).
|
package/build/fireEvent.js
CHANGED
|
@@ -7,8 +7,6 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _act = _interopRequireDefault(require("./act"));
|
|
9
9
|
|
|
10
|
-
var _errors = require("./helpers/errors");
|
|
11
|
-
|
|
12
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
11
|
|
|
14
12
|
const isHostElement = element => {
|
|
@@ -50,22 +48,16 @@ const isEventEnabled = (element, touchResponder) => {
|
|
|
50
48
|
return touchStart === undefined && touchMove === undefined;
|
|
51
49
|
};
|
|
52
50
|
|
|
53
|
-
const findEventHandler = (element, eventName, callsite, nearestTouchResponder
|
|
51
|
+
const findEventHandler = (element, eventName, callsite, nearestTouchResponder) => {
|
|
54
52
|
const touchResponder = isTouchResponder(element) ? element : nearestTouchResponder;
|
|
55
53
|
const handler = getEventHandler(element, eventName);
|
|
56
|
-
if (handler && isEventEnabled(element, touchResponder)) return handler;
|
|
57
|
-
|
|
58
|
-
const hasHandler = handler != null || hasDescendandHandler;
|
|
54
|
+
if (handler && isEventEnabled(element, touchResponder)) return handler;
|
|
59
55
|
|
|
60
56
|
if (element.parent === null || element.parent.parent === null) {
|
|
61
|
-
|
|
62
|
-
return null;
|
|
63
|
-
} else {
|
|
64
|
-
throw new _errors.ErrorWithStack(`No handler function found for event: "${eventName}"`, callsite || invokeEvent);
|
|
65
|
-
}
|
|
57
|
+
return null;
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
return findEventHandler(element.parent, eventName, callsite, touchResponder
|
|
60
|
+
return findEventHandler(element.parent, eventName, callsite, touchResponder);
|
|
69
61
|
};
|
|
70
62
|
|
|
71
63
|
const getEventHandler = (element, eventName) => {
|
|
@@ -98,7 +90,7 @@ const invokeEvent = (element, eventName, callsite, ...data) => {
|
|
|
98
90
|
|
|
99
91
|
const toEventHandlerName = eventName => `on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`;
|
|
100
92
|
|
|
101
|
-
const pressHandler = element => invokeEvent(element, 'press', pressHandler);
|
|
93
|
+
const pressHandler = (element, ...data) => invokeEvent(element, 'press', pressHandler, ...data);
|
|
102
94
|
|
|
103
95
|
const changeTextHandler = (element, ...data) => invokeEvent(element, 'changeText', changeTextHandler, ...data);
|
|
104
96
|
|
package/build/fireEvent.js.flow
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import act from './act';
|
|
3
|
-
import { ErrorWithStack } from './helpers/errors';
|
|
4
3
|
|
|
5
4
|
const isHostElement = (element?: ReactTestInstance) => {
|
|
6
5
|
return typeof element?.type === 'string';
|
|
@@ -53,8 +52,7 @@ const findEventHandler = (
|
|
|
53
52
|
element: ReactTestInstance,
|
|
54
53
|
eventName: string,
|
|
55
54
|
callsite?: any,
|
|
56
|
-
nearestTouchResponder?: ReactTestInstance
|
|
57
|
-
hasDescendandHandler?: boolean
|
|
55
|
+
nearestTouchResponder?: ReactTestInstance
|
|
58
56
|
) => {
|
|
59
57
|
const touchResponder = isTouchResponder(element)
|
|
60
58
|
? element
|
|
@@ -63,26 +61,11 @@ const findEventHandler = (
|
|
|
63
61
|
const handler = getEventHandler(element, eventName);
|
|
64
62
|
if (handler && isEventEnabled(element, touchResponder)) return handler;
|
|
65
63
|
|
|
66
|
-
// Do not bubble event to the root element
|
|
67
|
-
const hasHandler = handler != null || hasDescendandHandler;
|
|
68
64
|
if (element.parent === null || element.parent.parent === null) {
|
|
69
|
-
|
|
70
|
-
return null;
|
|
71
|
-
} else {
|
|
72
|
-
throw new ErrorWithStack(
|
|
73
|
-
`No handler function found for event: "${eventName}"`,
|
|
74
|
-
callsite || invokeEvent
|
|
75
|
-
);
|
|
76
|
-
}
|
|
65
|
+
return null;
|
|
77
66
|
}
|
|
78
67
|
|
|
79
|
-
return findEventHandler(
|
|
80
|
-
element.parent,
|
|
81
|
-
eventName,
|
|
82
|
-
callsite,
|
|
83
|
-
touchResponder,
|
|
84
|
-
hasHandler
|
|
85
|
-
);
|
|
68
|
+
return findEventHandler(element.parent, eventName, callsite, touchResponder);
|
|
86
69
|
};
|
|
87
70
|
|
|
88
71
|
const getEventHandler = (element: ReactTestInstance, eventName: string) => {
|
|
@@ -122,8 +105,8 @@ const invokeEvent = (
|
|
|
122
105
|
const toEventHandlerName = (eventName: string) =>
|
|
123
106
|
`on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`;
|
|
124
107
|
|
|
125
|
-
const pressHandler = (element: ReactTestInstance): void =>
|
|
126
|
-
invokeEvent(element, 'press', pressHandler);
|
|
108
|
+
const pressHandler = (element: ReactTestInstance, ...data: Array<any>): void =>
|
|
109
|
+
invokeEvent(element, 'press', pressHandler, ...data);
|
|
127
110
|
const changeTextHandler = (
|
|
128
111
|
element: ReactTestInstance,
|
|
129
112
|
...data: Array<any>
|
package/build/flushMicroTasks.js
CHANGED
|
@@ -8,6 +8,8 @@ exports.flushMicroTasks = flushMicroTasks;
|
|
|
8
8
|
|
|
9
9
|
var _errors = require("./helpers/errors");
|
|
10
10
|
|
|
11
|
+
var _timers = require("./helpers/timers");
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* Wait for microtasks queue to flush
|
|
13
15
|
*/
|
|
@@ -21,7 +23,7 @@ function flushMicroTasks() {
|
|
|
21
23
|
// using "thenable" instead of a Promise, because otherwise it breaks when
|
|
22
24
|
// using "modern" fake timers
|
|
23
25
|
then(resolve) {
|
|
24
|
-
setImmediate(resolve);
|
|
26
|
+
(0, _timers.setImmediate)(resolve);
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
};
|
|
@@ -5,27 +5,33 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.queryByDisplayValue = exports.queryAllByDisplayValue = exports.getByDisplayValue = exports.getAllByDisplayValue = exports.findByDisplayValue = exports.findAllByDisplayValue = void 0;
|
|
7
7
|
|
|
8
|
+
var _matches = require("../matches");
|
|
9
|
+
|
|
8
10
|
var _makeQueries = require("./makeQueries");
|
|
9
11
|
|
|
10
12
|
var _filterNodeByType = require("./filterNodeByType");
|
|
11
13
|
|
|
12
14
|
var _errors = require("./errors");
|
|
13
15
|
|
|
14
|
-
const getTextInputNodeByDisplayValue = (node, value) => {
|
|
16
|
+
const getTextInputNodeByDisplayValue = (node, value, options = {}) => {
|
|
15
17
|
try {
|
|
16
18
|
const {
|
|
17
19
|
TextInput
|
|
18
20
|
} = require('react-native');
|
|
19
21
|
|
|
22
|
+
const {
|
|
23
|
+
exact,
|
|
24
|
+
normalizer
|
|
25
|
+
} = options;
|
|
20
26
|
const nodeValue = node.props.value !== undefined ? node.props.value : node.props.defaultValue;
|
|
21
|
-
return (0, _filterNodeByType.filterNodeByType)(node, TextInput) && (
|
|
27
|
+
return (0, _filterNodeByType.filterNodeByType)(node, TextInput) && (0, _matches.matches)(value, nodeValue, normalizer, exact);
|
|
22
28
|
} catch (error) {
|
|
23
29
|
throw (0, _errors.createLibraryNotSupportedError)(error);
|
|
24
30
|
}
|
|
25
31
|
};
|
|
26
32
|
|
|
27
|
-
const queryAllByDisplayValue = instance => function queryAllByDisplayValueFn(displayValue) {
|
|
28
|
-
return instance.findAll(node => getTextInputNodeByDisplayValue(node, displayValue));
|
|
33
|
+
const queryAllByDisplayValue = instance => function queryAllByDisplayValueFn(displayValue, queryOptions) {
|
|
34
|
+
return instance.findAll(node => getTextInputNodeByDisplayValue(node, displayValue, queryOptions));
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
exports.queryAllByDisplayValue = queryAllByDisplayValue;
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import { matches } from '../matches';
|
|
2
3
|
import { makeQueries } from './makeQueries';
|
|
3
4
|
import type { Queries } from './makeQueries';
|
|
4
5
|
import { filterNodeByType } from './filterNodeByType';
|
|
5
6
|
import { createLibraryNotSupportedError } from './errors';
|
|
7
|
+
import type { TextMatchOptions } from './byText';
|
|
6
8
|
|
|
7
|
-
const getTextInputNodeByDisplayValue = (
|
|
9
|
+
const getTextInputNodeByDisplayValue = (
|
|
10
|
+
node,
|
|
11
|
+
value,
|
|
12
|
+
options?: TextMatchOptions = {}
|
|
13
|
+
) => {
|
|
8
14
|
try {
|
|
9
15
|
const { TextInput } = require('react-native');
|
|
16
|
+
const { exact, normalizer } = options;
|
|
10
17
|
const nodeValue =
|
|
11
18
|
node.props.value !== undefined
|
|
12
19
|
? node.props.value
|
|
13
20
|
: node.props.defaultValue;
|
|
14
21
|
return (
|
|
15
22
|
filterNodeByType(node, TextInput) &&
|
|
16
|
-
(
|
|
23
|
+
matches(value, nodeValue, normalizer, exact)
|
|
17
24
|
);
|
|
18
25
|
} catch (error) {
|
|
19
26
|
throw createLibraryNotSupportedError(error);
|
|
@@ -22,10 +29,13 @@ const getTextInputNodeByDisplayValue = (node, value) => {
|
|
|
22
29
|
|
|
23
30
|
const queryAllByDisplayValue = (
|
|
24
31
|
instance: ReactTestInstance
|
|
25
|
-
): ((
|
|
26
|
-
|
|
32
|
+
): ((
|
|
33
|
+
displayValue: string | RegExp,
|
|
34
|
+
queryOptions?: TextMatchOptions
|
|
35
|
+
) => Array<ReactTestInstance>) =>
|
|
36
|
+
function queryAllByDisplayValueFn(displayValue, queryOptions) {
|
|
27
37
|
return instance.findAll((node) =>
|
|
28
|
-
getTextInputNodeByDisplayValue(node, displayValue)
|
|
38
|
+
getTextInputNodeByDisplayValue(node, displayValue, queryOptions)
|
|
29
39
|
);
|
|
30
40
|
};
|
|
31
41
|
|
|
@@ -5,26 +5,32 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.queryByPlaceholderText = exports.queryAllByPlaceholderText = exports.getByPlaceholderText = exports.getAllByPlaceholderText = exports.findByPlaceholderText = exports.findAllByPlaceholderText = void 0;
|
|
7
7
|
|
|
8
|
+
var _matches = require("../matches");
|
|
9
|
+
|
|
8
10
|
var _makeQueries = require("./makeQueries");
|
|
9
11
|
|
|
10
12
|
var _filterNodeByType = require("./filterNodeByType");
|
|
11
13
|
|
|
12
14
|
var _errors = require("./errors");
|
|
13
15
|
|
|
14
|
-
const getTextInputNodeByPlaceholderText = (node, placeholder) => {
|
|
16
|
+
const getTextInputNodeByPlaceholderText = (node, placeholder, options = {}) => {
|
|
15
17
|
try {
|
|
16
18
|
const {
|
|
17
19
|
TextInput
|
|
18
20
|
} = require('react-native');
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
const {
|
|
23
|
+
exact,
|
|
24
|
+
normalizer
|
|
25
|
+
} = options;
|
|
26
|
+
return (0, _filterNodeByType.filterNodeByType)(node, TextInput) && (0, _matches.matches)(placeholder, node.props.placeholder, normalizer, exact);
|
|
21
27
|
} catch (error) {
|
|
22
28
|
throw (0, _errors.createLibraryNotSupportedError)(error);
|
|
23
29
|
}
|
|
24
30
|
};
|
|
25
31
|
|
|
26
|
-
const queryAllByPlaceholderText = instance => function queryAllByPlaceholderFn(placeholder) {
|
|
27
|
-
return instance.findAll(node => getTextInputNodeByPlaceholderText(node, placeholder));
|
|
32
|
+
const queryAllByPlaceholderText = instance => function queryAllByPlaceholderFn(placeholder, queryOptions) {
|
|
33
|
+
return instance.findAll(node => getTextInputNodeByPlaceholderText(node, placeholder, queryOptions));
|
|
28
34
|
};
|
|
29
35
|
|
|
30
36
|
exports.queryAllByPlaceholderText = queryAllByPlaceholderText;
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import { matches } from '../matches';
|
|
2
3
|
import { makeQueries } from './makeQueries';
|
|
3
4
|
import type { Queries } from './makeQueries';
|
|
4
5
|
import { filterNodeByType } from './filterNodeByType';
|
|
5
6
|
import { createLibraryNotSupportedError } from './errors';
|
|
7
|
+
import type { TextMatchOptions } from './byText';
|
|
6
8
|
|
|
7
|
-
const getTextInputNodeByPlaceholderText = (
|
|
9
|
+
const getTextInputNodeByPlaceholderText = (
|
|
10
|
+
node,
|
|
11
|
+
placeholder,
|
|
12
|
+
options?: TextMatchOptions = {}
|
|
13
|
+
) => {
|
|
8
14
|
try {
|
|
9
15
|
const { TextInput } = require('react-native');
|
|
16
|
+
const { exact, normalizer } = options;
|
|
10
17
|
return (
|
|
11
18
|
filterNodeByType(node, TextInput) &&
|
|
12
|
-
(
|
|
13
|
-
? placeholder === node.props.placeholder
|
|
14
|
-
: placeholder.test(node.props.placeholder))
|
|
19
|
+
matches(placeholder, node.props.placeholder, normalizer, exact)
|
|
15
20
|
);
|
|
16
21
|
} catch (error) {
|
|
17
22
|
throw createLibraryNotSupportedError(error);
|
|
@@ -20,10 +25,13 @@ const getTextInputNodeByPlaceholderText = (node, placeholder) => {
|
|
|
20
25
|
|
|
21
26
|
const queryAllByPlaceholderText = (
|
|
22
27
|
instance: ReactTestInstance
|
|
23
|
-
): ((
|
|
24
|
-
|
|
28
|
+
): ((
|
|
29
|
+
placeholder: string | RegExp,
|
|
30
|
+
queryOptions?: TextMatchOptions
|
|
31
|
+
) => Array<ReactTestInstance>) =>
|
|
32
|
+
function queryAllByPlaceholderFn(placeholder, queryOptions) {
|
|
25
33
|
return instance.findAll((node) =>
|
|
26
|
-
getTextInputNodeByPlaceholderText(node, placeholder)
|
|
34
|
+
getTextInputNodeByPlaceholderText(node, placeholder, queryOptions)
|
|
27
35
|
);
|
|
28
36
|
};
|
|
29
37
|
|
|
@@ -5,14 +5,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.queryByTestId = exports.queryAllByTestId = exports.getByTestId = exports.getAllByTestId = exports.findByTestId = exports.findAllByTestId = void 0;
|
|
7
7
|
|
|
8
|
+
var _matches = require("../matches");
|
|
9
|
+
|
|
8
10
|
var _makeQueries = require("./makeQueries");
|
|
9
11
|
|
|
10
|
-
const getNodeByTestId = (node, testID) => {
|
|
11
|
-
|
|
12
|
+
const getNodeByTestId = (node, testID, options = {}) => {
|
|
13
|
+
const {
|
|
14
|
+
exact,
|
|
15
|
+
normalizer
|
|
16
|
+
} = options;
|
|
17
|
+
return (0, _matches.matches)(testID, node.props.testID, normalizer, exact);
|
|
12
18
|
};
|
|
13
19
|
|
|
14
|
-
const queryAllByTestId = instance => function queryAllByTestIdFn(testId) {
|
|
15
|
-
const results = instance.findAll(node => getNodeByTestId(node, testId)).filter(element => typeof element.type === 'string');
|
|
20
|
+
const queryAllByTestId = instance => function queryAllByTestIdFn(testId, queryOptions) {
|
|
21
|
+
const results = instance.findAll(node => getNodeByTestId(node, testId, queryOptions)).filter(element => typeof element.type === 'string');
|
|
16
22
|
return results;
|
|
17
23
|
};
|
|
18
24
|
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import { matches } from '../matches';
|
|
2
3
|
import { makeQueries } from './makeQueries';
|
|
3
4
|
import type { Queries } from './makeQueries';
|
|
5
|
+
import type { TextMatchOptions } from './byText';
|
|
4
6
|
|
|
5
|
-
const getNodeByTestId = (node, testID) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
: testID.test(node.props.testID);
|
|
7
|
+
const getNodeByTestId = (node, testID, options?: TextMatchOptions = {}) => {
|
|
8
|
+
const { exact, normalizer } = options;
|
|
9
|
+
return matches(testID, node.props.testID, normalizer, exact);
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
const queryAllByTestId = (
|
|
12
13
|
instance: ReactTestInstance
|
|
13
|
-
): ((
|
|
14
|
-
|
|
14
|
+
): ((
|
|
15
|
+
testId: string | RegExp,
|
|
16
|
+
queryOptions?: TextMatchOptions
|
|
17
|
+
) => Array<ReactTestInstance>) =>
|
|
18
|
+
function queryAllByTestIdFn(testId, queryOptions) {
|
|
15
19
|
const results = instance
|
|
16
|
-
.findAll((node) => getNodeByTestId(node, testId))
|
|
20
|
+
.findAll((node) => getNodeByTestId(node, testId, queryOptions))
|
|
17
21
|
.filter((element) => typeof element.type === 'string');
|
|
18
22
|
|
|
19
23
|
return results;
|
package/build/helpers/byText.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.queryByText = exports.queryAllByText = exports.getByText = exports.getAl
|
|
|
7
7
|
|
|
8
8
|
var React = _interopRequireWildcard(require("react"));
|
|
9
9
|
|
|
10
|
+
var _matches = require("../matches");
|
|
11
|
+
|
|
10
12
|
var _makeQueries = require("./makeQueries");
|
|
11
13
|
|
|
12
14
|
var _filterNodeByType = require("./filterNodeByType");
|
|
@@ -17,7 +19,8 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return
|
|
|
17
19
|
|
|
18
20
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
19
21
|
|
|
20
|
-
const getChildrenAsText = (children, TextComponent
|
|
22
|
+
const getChildrenAsText = (children, TextComponent) => {
|
|
23
|
+
const textContent = [];
|
|
21
24
|
React.Children.forEach(children, child => {
|
|
22
25
|
var _child$props;
|
|
23
26
|
|
|
@@ -40,13 +43,13 @@ const getChildrenAsText = (children, TextComponent, textContent = []) => {
|
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
getChildrenAsText(child.props.children, TextComponent
|
|
46
|
+
getChildrenAsText(child.props.children, TextComponent);
|
|
44
47
|
}
|
|
45
48
|
});
|
|
46
49
|
return textContent;
|
|
47
50
|
};
|
|
48
51
|
|
|
49
|
-
const getNodeByText = (node, text) => {
|
|
52
|
+
const getNodeByText = (node, text, options = {}) => {
|
|
50
53
|
try {
|
|
51
54
|
const {
|
|
52
55
|
Text
|
|
@@ -59,7 +62,11 @@ const getNodeByText = (node, text) => {
|
|
|
59
62
|
|
|
60
63
|
if (textChildren) {
|
|
61
64
|
const textToTest = textChildren.join('');
|
|
62
|
-
|
|
65
|
+
const {
|
|
66
|
+
exact,
|
|
67
|
+
normalizer
|
|
68
|
+
} = options;
|
|
69
|
+
return (0, _matches.matches)(text, textToTest, normalizer, exact);
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
|
|
@@ -69,8 +76,8 @@ const getNodeByText = (node, text) => {
|
|
|
69
76
|
}
|
|
70
77
|
};
|
|
71
78
|
|
|
72
|
-
const queryAllByText = instance => function queryAllByTextFn(text) {
|
|
73
|
-
const results = instance.findAll(node => getNodeByText(node, text));
|
|
79
|
+
const queryAllByText = instance => function queryAllByTextFn(text, queryOptions) {
|
|
80
|
+
const results = instance.findAll(node => getNodeByText(node, text, queryOptions));
|
|
74
81
|
return results;
|
|
75
82
|
};
|
|
76
83
|
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { matches } from '../matches';
|
|
4
|
+
import type { NormalizerFn } from '../matches';
|
|
3
5
|
import { makeQueries } from './makeQueries';
|
|
4
6
|
import type { Queries } from './makeQueries';
|
|
5
7
|
import { filterNodeByType } from './filterNodeByType';
|
|
6
8
|
import { createLibraryNotSupportedError } from './errors';
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
export type TextMatchOptions = {
|
|
11
|
+
exact?: boolean,
|
|
12
|
+
normalizer?: NormalizerFn,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getChildrenAsText = (children, TextComponent) => {
|
|
16
|
+
const textContent = [];
|
|
9
17
|
React.Children.forEach(children, (child) => {
|
|
10
18
|
if (typeof child === 'string') {
|
|
11
19
|
textContent.push(child);
|
|
@@ -26,14 +34,18 @@ const getChildrenAsText = (children, TextComponent, textContent = []) => {
|
|
|
26
34
|
return;
|
|
27
35
|
}
|
|
28
36
|
|
|
29
|
-
getChildrenAsText(child.props.children, TextComponent
|
|
37
|
+
getChildrenAsText(child.props.children, TextComponent);
|
|
30
38
|
}
|
|
31
39
|
});
|
|
32
40
|
|
|
33
41
|
return textContent;
|
|
34
42
|
};
|
|
35
43
|
|
|
36
|
-
const getNodeByText = (
|
|
44
|
+
const getNodeByText = (
|
|
45
|
+
node,
|
|
46
|
+
text: string | RegExp,
|
|
47
|
+
options?: TextMatchOptions = {}
|
|
48
|
+
) => {
|
|
37
49
|
try {
|
|
38
50
|
const { Text } = require('react-native');
|
|
39
51
|
const isTextComponent = filterNodeByType(node, Text);
|
|
@@ -41,9 +53,8 @@ const getNodeByText = (node, text: string | RegExp) => {
|
|
|
41
53
|
const textChildren = getChildrenAsText(node.props.children, Text);
|
|
42
54
|
if (textChildren) {
|
|
43
55
|
const textToTest = textChildren.join('');
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
: text.test(textToTest);
|
|
56
|
+
const { exact, normalizer } = options;
|
|
57
|
+
return matches(text, textToTest, normalizer, exact);
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
60
|
return false;
|
|
@@ -54,9 +65,14 @@ const getNodeByText = (node, text: string | RegExp) => {
|
|
|
54
65
|
|
|
55
66
|
const queryAllByText = (
|
|
56
67
|
instance: ReactTestInstance
|
|
57
|
-
): ((
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
): ((
|
|
69
|
+
text: string | RegExp,
|
|
70
|
+
queryOptions?: TextMatchOptions
|
|
71
|
+
) => Array<ReactTestInstance>) =>
|
|
72
|
+
function queryAllByTextFn(text, queryOptions) {
|
|
73
|
+
const results = instance.findAll((node) =>
|
|
74
|
+
getNodeByText(node, text, queryOptions)
|
|
75
|
+
);
|
|
60
76
|
|
|
61
77
|
return results;
|
|
62
78
|
};
|
package/build/helpers/errors.js
CHANGED
|
@@ -53,6 +53,7 @@ export function printDeprecationWarning(functionName: string) {
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
56
57
|
console.warn(`
|
|
57
58
|
Deprecation Warning:
|
|
58
59
|
Use of ${functionName} is not recommended and will be deleted in future versions of @testing-library/react-native.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import type { WaitForOptions } from '../waitFor';
|
|
3
|
+
import type { TextMatchOptions } from './byText';
|
|
3
4
|
import { findAllByTestId, findByTestId } from './byTestId';
|
|
4
5
|
import { findAllByText, findByText } from './byText';
|
|
5
6
|
import {
|
|
@@ -12,36 +13,44 @@ import { throwRenamedFunctionError } from './errors';
|
|
|
12
13
|
export type FindByAPI = {|
|
|
13
14
|
findAllByDisplayValue: (
|
|
14
15
|
value: string | RegExp,
|
|
16
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
15
17
|
waitForOptions?: WaitForOptions
|
|
16
18
|
) => Promise<Array<ReactTestInstance>>,
|
|
17
19
|
findAllByPlaceholder: () => void,
|
|
18
20
|
findAllByPlaceholderText: (
|
|
19
21
|
placeholder: string | RegExp,
|
|
22
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
20
23
|
waitForOptions?: WaitForOptions
|
|
21
24
|
) => Promise<Array<ReactTestInstance>>,
|
|
22
25
|
findAllByTestId: (
|
|
23
26
|
testId: string | RegExp,
|
|
27
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
24
28
|
waitForOptions?: WaitForOptions
|
|
25
29
|
) => Promise<Array<ReactTestInstance>>,
|
|
26
30
|
findAllByText: (
|
|
27
31
|
text: string | RegExp,
|
|
32
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
28
33
|
waitForOptions?: WaitForOptions
|
|
29
34
|
) => Promise<Array<ReactTestInstance>>,
|
|
30
35
|
findByDisplayValue: (
|
|
31
36
|
value: string | RegExp,
|
|
37
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
32
38
|
waitForOptions?: WaitForOptions
|
|
33
39
|
) => Promise<ReactTestInstance>,
|
|
34
40
|
findByPlaceholder: () => void,
|
|
35
41
|
findByPlaceholderText: (
|
|
36
42
|
placeholder: string | RegExp,
|
|
43
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
37
44
|
waitForOptions?: WaitForOptions
|
|
38
45
|
) => Promise<ReactTestInstance>,
|
|
39
46
|
findByTestId: (
|
|
40
47
|
testId: string | RegExp,
|
|
48
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
41
49
|
waitForOptions?: WaitForOptions
|
|
42
50
|
) => Promise<ReactTestInstance>,
|
|
43
51
|
findByText: (
|
|
44
52
|
text: string | RegExp,
|
|
53
|
+
queryOptions?: TextMatchOptions & WaitForOptions,
|
|
45
54
|
waitForOptions?: WaitForOptions
|
|
46
55
|
) => Promise<ReactTestInstance>,
|
|
47
56
|
|};
|
|
@@ -14,18 +14,41 @@ import {
|
|
|
14
14
|
getByPlaceholderText,
|
|
15
15
|
} from './byPlaceholderText';
|
|
16
16
|
import { getAllByDisplayValue, getByDisplayValue } from './byDisplayValue';
|
|
17
|
+
import type { TextMatchOptions } from './byText';
|
|
17
18
|
|
|
18
19
|
export type GetByAPI = {|
|
|
19
|
-
getByText: (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
getByText: (
|
|
21
|
+
text: string | RegExp,
|
|
22
|
+
queryOptions?: TextMatchOptions
|
|
23
|
+
) => ReactTestInstance,
|
|
24
|
+
getByPlaceholderText: (
|
|
25
|
+
placeholder: string | RegExp,
|
|
26
|
+
queryOptions?: TextMatchOptions
|
|
27
|
+
) => ReactTestInstance,
|
|
28
|
+
getByDisplayValue: (
|
|
29
|
+
value: string | RegExp,
|
|
30
|
+
queryOptions?: TextMatchOptions
|
|
31
|
+
) => ReactTestInstance,
|
|
32
|
+
getByTestId: (
|
|
33
|
+
testID: string | RegExp,
|
|
34
|
+
queryOptions?: TextMatchOptions
|
|
35
|
+
) => ReactTestInstance,
|
|
36
|
+
getAllByTestId: (
|
|
37
|
+
testID: string | RegExp,
|
|
38
|
+
queryOptions?: TextMatchOptions
|
|
39
|
+
) => Array<ReactTestInstance>,
|
|
40
|
+
getAllByText: (
|
|
41
|
+
text: string | RegExp,
|
|
42
|
+
queryOptions?: TextMatchOptions
|
|
43
|
+
) => Array<ReactTestInstance>,
|
|
25
44
|
getAllByPlaceholderText: (
|
|
26
|
-
placeholder: string | RegExp
|
|
45
|
+
placeholder: string | RegExp,
|
|
46
|
+
queryOptions?: TextMatchOptions
|
|
47
|
+
) => Array<ReactTestInstance>,
|
|
48
|
+
getAllByDisplayValue: (
|
|
49
|
+
value: string | RegExp,
|
|
50
|
+
queryOptions?: TextMatchOptions
|
|
27
51
|
) => Array<ReactTestInstance>,
|
|
28
|
-
getAllByDisplayValue: (value: string | RegExp) => Array<ReactTestInstance>,
|
|
29
52
|
|
|
30
53
|
// Unsafe aliases
|
|
31
54
|
UNSAFE_getByType: <P>(type: React.ComponentType<P>) => ReactTestInstance,
|