fix: fire event should not throw for disabled handler (#470)

* updated tests

* feat: implement behavior chage

* code review changes

* refactor: more strict test conditions
This commit is contained in:
Maciej Jastrzebski
2020-07-31 10:34:00 +02:00
committed by GitHub
parent a766905183
commit 00a50a89b3
2 changed files with 46 additions and 26 deletions
+12 -12
View File
@@ -168,28 +168,28 @@ test('event with multiple handler parameters', () => {
test('should not fire on disabled TouchableOpacity', () => {
const handlePress = jest.fn();
const screen = render(
<TouchableOpacity onPress={handlePress} disabled={true}>
<Text>Trigger</Text>
</TouchableOpacity>
<View>
<TouchableOpacity onPress={handlePress} disabled={true}>
<Text>Trigger</Text>
</TouchableOpacity>
</View>
);
expect(() => fireEvent.press(screen.getByText('Trigger'))).toThrow(
'No handler function found for event: "press"'
);
fireEvent.press(screen.getByText('Trigger'));
expect(handlePress).not.toHaveBeenCalled();
});
test('should not fire on disabled Pressable', () => {
const handlePress = jest.fn();
const screen = render(
<Pressable onPress={handlePress} disabled={true}>
<Text>Trigger</Text>
</Pressable>
<View>
<Pressable onPress={handlePress} disabled={true}>
<Text>Trigger</Text>
</Pressable>
</View>
);
expect(() => fireEvent.press(screen.getByText('Trigger'))).toThrow(
'No handler function found for event: "press"'
);
fireEvent.press(screen.getByText('Trigger'));
expect(handlePress).not.toHaveBeenCalled();
});
+34 -14
View File
@@ -6,30 +6,50 @@ const findEventHandler = (
element: ReactTestInstance,
eventName: string,
callsite?: any,
nearestHostDescendent?: ReactTestInstance
nearestHostDescendent?: ReactTestInstance,
hasDescendandHandler?: boolean
) => {
const handler = getEventHandler(element, eventName);
const hasHandler = handler != null || hasDescendandHandler;
const isHostComponent = typeof element.type === 'string';
const hostElement = isHostComponent ? element : nearestHostDescendent;
const isEventEnabled =
hostElement?.props.onStartShouldSetResponder?.() !== false;
const eventHandlerName = toEventHandlerName(eventName);
if (typeof element.props[eventHandlerName] === 'function' && isEventEnabled) {
return element.props[eventHandlerName];
} else if (typeof element.props[eventName] === 'function' && isEventEnabled) {
return element.props[eventName];
}
if (handler && isEventEnabled) return handler;
// Do not bubble event to the root element
if (element.parent === null || element.parent.parent === null) {
throw new ErrorWithStack(
`No handler function found for event: "${eventName}"`,
callsite || invokeEvent
);
if (hasHandler) {
return null;
} else {
throw new ErrorWithStack(
`No handler function found for event: "${eventName}"`,
callsite || invokeEvent
);
}
}
return findEventHandler(element.parent, eventName, callsite, hostElement);
return findEventHandler(
element.parent,
eventName,
callsite,
hostElement,
hasHandler
);
};
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 = (