forked from callstack/react-native-testing-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfireEvent.js
127 lines (98 loc) · 3.37 KB
/
fireEvent.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// @flow
import act from './act';
const isHostElement = (element?: ReactTestInstance) => {
return typeof element?.type === 'string';
};
const isTextInput = (element?: ReactTestInstance) => {
const { TextInput } = require('react-native');
return element?.type === TextInput;
};
const isTouchResponder = (element?: ReactTestInstance) => {
if (!isHostElement(element)) return false;
return !!element?.props.onStartShouldSetResponder || isTextInput(element);
};
const isPointerEventEnabled = (
element?: ReactTestInstance,
isParent?: boolean
) => {
const parentCondition = isParent
? element?.props.pointerEvents === 'box-only'
: element?.props.pointerEvents === 'box-none';
if (element?.props.pointerEvents === 'none' || parentCondition) {
return false;
}
if (!element?.parent) return true;
return isPointerEventEnabled(element.parent, true);
};
const isEventEnabled = (
element?: ReactTestInstance,
touchResponder?: ReactTestInstance
) => {
if (isTextInput(element)) return element?.props.editable !== false;
if (!isPointerEventEnabled(element)) return false;
const touchStart = touchResponder?.props.onStartShouldSetResponder?.();
const touchMove = touchResponder?.props.onMoveShouldSetResponder?.();
if (touchStart || touchMove) return true;
return touchStart === undefined && touchMove === undefined;
};
const findEventHandler = (
element: ReactTestInstance,
eventName: string,
callsite?: any,
nearestTouchResponder?: ReactTestInstance
) => {
const touchResponder = isTouchResponder(element)
? element
: nearestTouchResponder;
const handler = getEventHandler(element, eventName);
if (handler && isEventEnabled(element, touchResponder)) return handler;
if (element.parent === null || element.parent.parent === null) {
return null;
}
return findEventHandler(element.parent, eventName, callsite, touchResponder);
};
const getEventHandler = (element: ReactTestInstance, eventName: string) => {
const eventHandlerName = toEventHandlerName(eventName);
if (typeof element.props[eventHandlerName] === 'function') {
return element.props[eventHandlerName];
}
if (typeof element.props[eventName] === 'function') {
return element.props[eventName];
}
return undefined;
};
const invokeEvent = (
element: ReactTestInstance,
eventName: string,
callsite?: any,
...data: Array<any>
) => {
const handler = findEventHandler(element, eventName, callsite);
if (!handler) {
return;
}
let returnValue;
act(() => {
returnValue = handler(...data);
});
return returnValue;
};
const toEventHandlerName = (eventName: string) =>
`on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`;
const pressHandler = (element: ReactTestInstance, ...data: Array<any>): void =>
invokeEvent(element, 'press', pressHandler, ...data);
const changeTextHandler = (
element: ReactTestInstance,
...data: Array<any>
): void => invokeEvent(element, 'changeText', changeTextHandler, ...data);
const scrollHandler = (element: ReactTestInstance, ...data: Array<any>): void =>
invokeEvent(element, 'scroll', scrollHandler, ...data);
const fireEvent = (
element: ReactTestInstance,
eventName: string,
...data: Array<any>
): void => invokeEvent(element, eventName, fireEvent, ...data);
fireEvent.press = pressHandler;
fireEvent.changeText = changeTextHandler;
fireEvent.scroll = scrollHandler;
export default fireEvent;