mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
ReactNativeBridgeEventPlugin supports lazily-registered event types (#10679)
* ReactNativeBridgeEventPlugin supports lazily-registered event types This accompanies changes on the native side to now specify which event types each view manager supports as part of its view config. Ultimately the goal is to lazily initialize view managers on the native side as well. * Bubbling and direct attributes are optional on view config This should help ease transition for pre-existing JS-only components.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ReactNativeBridgeEventPlugin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
||||
} = require('ReactNative');
|
||||
|
||||
module.exports =
|
||||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactNativeBridgeEventPlugin;
|
||||
@@ -11,28 +11,17 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var EventPropagators = require('EventPropagators');
|
||||
var SyntheticEvent = require('SyntheticEvent');
|
||||
var ReactNativeEventTypes = require('ReactNativeEventTypes');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
const EventPropagators = require('EventPropagators');
|
||||
const SyntheticEvent = require('SyntheticEvent');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
|
||||
var customBubblingEventTypes = ReactNativeEventTypes.customBubblingEventTypes;
|
||||
var customDirectEventTypes = ReactNativeEventTypes.customDirectEventTypes;
|
||||
const customBubblingEventTypes = {};
|
||||
const customDirectEventTypes = {};
|
||||
|
||||
if (__DEV__) {
|
||||
var warning = require('fbjs/lib/warning');
|
||||
import type {ReactNativeBaseComponentViewConfig} from 'ReactNativeTypes';
|
||||
|
||||
for (var directTypeName in customDirectEventTypes) {
|
||||
warning(
|
||||
!customBubblingEventTypes[directTypeName],
|
||||
'Event cannot be both direct and bubbling: %s',
|
||||
directTypeName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: {...customBubblingEventTypes, ...customDirectEventTypes},
|
||||
const ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: {},
|
||||
|
||||
/**
|
||||
* @see {EventPluginHub.extractEvents}
|
||||
@@ -43,14 +32,14 @@ var ReactNativeBridgeEventPlugin = {
|
||||
nativeEvent: Event,
|
||||
nativeEventTarget: Object,
|
||||
): ?Object {
|
||||
var bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
|
||||
var directDispatchConfig = customDirectEventTypes[topLevelType];
|
||||
const bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
|
||||
const directDispatchConfig = customDirectEventTypes[topLevelType];
|
||||
invariant(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
'Unsupported top level event type "%s" dispatched',
|
||||
topLevelType,
|
||||
);
|
||||
var event = SyntheticEvent.getPooled(
|
||||
const event = SyntheticEvent.getPooled(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
targetInst,
|
||||
nativeEvent,
|
||||
@@ -65,6 +54,46 @@ var ReactNativeBridgeEventPlugin = {
|
||||
}
|
||||
return event;
|
||||
},
|
||||
|
||||
processEventTypes: function(
|
||||
viewConfig: ReactNativeBaseComponentViewConfig,
|
||||
): void {
|
||||
const {bubblingEventTypes, directEventTypes} = viewConfig;
|
||||
|
||||
if (__DEV__) {
|
||||
if (bubblingEventTypes != null && directEventTypes != null) {
|
||||
for (const topLevelType in directEventTypes) {
|
||||
invariant(
|
||||
bubblingEventTypes[topLevelType] == null,
|
||||
'Event cannot be both direct and bubbling: %s',
|
||||
topLevelType,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bubblingEventTypes != null) {
|
||||
for (const topLevelType in bubblingEventTypes) {
|
||||
if (customBubblingEventTypes[topLevelType] == null) {
|
||||
ReactNativeBridgeEventPlugin.eventTypes[
|
||||
topLevelType
|
||||
] = customBubblingEventTypes[topLevelType] =
|
||||
bubblingEventTypes[topLevelType];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (directEventTypes != null) {
|
||||
for (const topLevelType in directEventTypes) {
|
||||
if (customDirectEventTypes[topLevelType] == null) {
|
||||
ReactNativeBridgeEventPlugin.eventTypes[
|
||||
topLevelType
|
||||
] = customDirectEventTypes[topLevelType] =
|
||||
directEventTypes[topLevelType];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = ReactNativeBridgeEventPlugin;
|
||||
|
||||
@@ -1,319 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ReactNativeEventTypes
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
|
||||
const emptyObject = require('fbjs/lib/emptyObject');
|
||||
|
||||
const COMMON_BUBBLING_EVENT_TYPES = {
|
||||
topBlur: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onBlurCapture',
|
||||
bubbled: 'onBlur',
|
||||
},
|
||||
},
|
||||
topChange: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onChangeCapture',
|
||||
bubbled: 'onChange',
|
||||
},
|
||||
},
|
||||
topEndEditing: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onEndEditingCapture',
|
||||
bubbled: 'onEndEditing',
|
||||
},
|
||||
},
|
||||
topFocus: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onFocusCapture',
|
||||
bubbled: 'onFocus',
|
||||
},
|
||||
},
|
||||
topSubmitEditing: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onSubmitEditingCapture',
|
||||
bubbled: 'onSubmitEditing',
|
||||
},
|
||||
},
|
||||
topTouchEnd: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onTouchEndCapture',
|
||||
bubbled: 'onTouchEnd',
|
||||
},
|
||||
},
|
||||
topTouchMove: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onTouchMoveCapture',
|
||||
bubbled: 'onTouchMove',
|
||||
},
|
||||
},
|
||||
topTouchStart: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onTouchStartCapture',
|
||||
bubbled: 'onTouchStart',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const COMMON_DIRECT_EVENT_TYPES = {
|
||||
topError: {
|
||||
registrationName: 'onError',
|
||||
},
|
||||
topLayout: {
|
||||
registrationName: 'onLayout',
|
||||
},
|
||||
topLoad: {
|
||||
registrationName: 'onLoad',
|
||||
},
|
||||
topLoadEnd: {
|
||||
registrationName: 'onLoadEnd',
|
||||
},
|
||||
topLoadStart: {
|
||||
registrationName: 'onLoadStart',
|
||||
},
|
||||
topLoadingError: {
|
||||
registrationName: 'onLoadingError',
|
||||
},
|
||||
topLoadingFinish: {
|
||||
registrationName: 'onLoadingFinish',
|
||||
},
|
||||
topLoadingStart: {
|
||||
registrationName: 'onLoadingStart',
|
||||
},
|
||||
topMessage: {
|
||||
registrationName: 'onMessage',
|
||||
},
|
||||
topMomentumScrollBegin: {
|
||||
registrationName: 'onMomentumScrollBegin',
|
||||
},
|
||||
topMomentumScrollEnd: {
|
||||
registrationName: 'onMomentumScrollEnd',
|
||||
},
|
||||
topRefresh: {
|
||||
registrationName: 'onRefresh',
|
||||
},
|
||||
topScroll: {
|
||||
registrationName: 'onScroll',
|
||||
},
|
||||
topScrollAnimationEnd: {
|
||||
registrationName: 'onScrollAnimationEnd',
|
||||
},
|
||||
topScrollBeginDrag: {
|
||||
registrationName: 'onScrollBeginDrag',
|
||||
},
|
||||
topScrollEndDrag: {
|
||||
registrationName: 'onScrollEndDrag',
|
||||
},
|
||||
topSelectionChange: {
|
||||
registrationName: 'onSelectionChange',
|
||||
},
|
||||
topShow: {
|
||||
registrationName: 'onShow',
|
||||
},
|
||||
};
|
||||
|
||||
const ANDROID_BUBBLING_EVENT_TYPES = {
|
||||
...COMMON_BUBBLING_EVENT_TYPES,
|
||||
topSelect: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onSelect',
|
||||
captured: 'onSelectCapture',
|
||||
},
|
||||
},
|
||||
topTextInput: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onTextInput',
|
||||
captured: 'onTextInputCapture',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const ANDROID_DIRECT_EVENT_TYPES = {
|
||||
...COMMON_DIRECT_EVENT_TYPES,
|
||||
topContentSizeChange: {
|
||||
registrationName: 'onContentSizeChange',
|
||||
},
|
||||
topDrawerClosed: {
|
||||
registrationName: 'onDrawerClose',
|
||||
},
|
||||
topDrawerOpened: {
|
||||
registrationName: 'onDrawerOpen',
|
||||
},
|
||||
topDrawerSlide: {
|
||||
registrationName: 'onDrawerSlide',
|
||||
},
|
||||
topDrawerStateChanged: {
|
||||
registrationName: 'onDrawerStateChanged',
|
||||
},
|
||||
topPageScroll: {
|
||||
registrationName: 'onPageScroll',
|
||||
},
|
||||
topPageScrollStateChanged: {
|
||||
registrationName: 'onPageScrollStateChanged',
|
||||
},
|
||||
topPageSelected: {
|
||||
registrationName: 'onPageSelected',
|
||||
},
|
||||
topRequestClose: {
|
||||
registrationName: 'onRequestClose',
|
||||
},
|
||||
topSlidingComplete: {
|
||||
registrationName: 'onSlidingComplete',
|
||||
},
|
||||
topVideoProgress: {
|
||||
registrationName: 'onProgress',
|
||||
},
|
||||
topVideoSizeDetected: {
|
||||
registrationName: 'onVideoSizeDetected',
|
||||
},
|
||||
topVideoStateChange: {
|
||||
registrationName: 'onStateChange',
|
||||
},
|
||||
topZoom: {
|
||||
registrationName: 'onZoom',
|
||||
},
|
||||
};
|
||||
|
||||
const IOS_BUBBLING_EVENT_TYPES = {
|
||||
...COMMON_BUBBLING_EVENT_TYPES,
|
||||
topAnnotationBlur: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onAnnotationBlurCapture',
|
||||
bubbled: 'onAnnotationBlur',
|
||||
},
|
||||
},
|
||||
topAnnotationDragStateChange: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onAnnotationDragStateChangeCapture',
|
||||
bubbled: 'onAnnotationDragStateChange',
|
||||
},
|
||||
},
|
||||
topAnnotationFocus: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onAnnotationFocusCapture',
|
||||
bubbled: 'onAnnotationFocus',
|
||||
},
|
||||
},
|
||||
topContentSizeChange: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onContentSizeChangeCapture',
|
||||
bubbled: 'onContentSizeChange',
|
||||
},
|
||||
},
|
||||
topKeyPress: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onKeyPressCapture',
|
||||
bubbled: 'onKeyPress',
|
||||
},
|
||||
},
|
||||
topLeftButtonPress: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onLeftButtonPressCapture',
|
||||
bubbled: 'onLeftButtonPress',
|
||||
},
|
||||
},
|
||||
topNavigationComplete: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onNavigationCompleteCapture',
|
||||
bubbled: 'onNavigationComplete',
|
||||
},
|
||||
},
|
||||
topPress: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onPressCapture',
|
||||
bubbled: 'onPress',
|
||||
},
|
||||
},
|
||||
topRightButtonPress: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onRightButtonPressCapture',
|
||||
bubbled: 'onRightButtonPress',
|
||||
},
|
||||
},
|
||||
topSlidingComplete: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onSlidingCompleteCapture',
|
||||
bubbled: 'onSlidingComplete',
|
||||
},
|
||||
},
|
||||
topTouchCancel: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onTouchCancelCapture',
|
||||
bubbled: 'onTouchCancel',
|
||||
},
|
||||
},
|
||||
topValueChange: {
|
||||
phasedRegistrationNames: {
|
||||
captured: 'onValueChangeCapture',
|
||||
bubbled: 'onValueChange',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const IOS_DIRECT_EVENT_TYPES = {
|
||||
...COMMON_DIRECT_EVENT_TYPES,
|
||||
topAccessibilityTap: {
|
||||
registrationName: 'onAccessibilityTap',
|
||||
},
|
||||
topMagicTap: {
|
||||
registrationName: 'onMagicTap',
|
||||
},
|
||||
topNavigationProgress: {
|
||||
registrationName: 'onNavigationProgress',
|
||||
},
|
||||
topOrientationChange: {
|
||||
registrationName: 'onOrientationChange',
|
||||
},
|
||||
topPartialLoad: {
|
||||
registrationName: 'onPartialLoad',
|
||||
},
|
||||
topProgress: {
|
||||
registrationName: 'onProgress',
|
||||
},
|
||||
topShouldStartLoadWithRequest: {
|
||||
registrationName: 'onShouldStartLoadWithRequest',
|
||||
},
|
||||
topSnapshotReady: {
|
||||
registrationName: 'onSnapshotReady',
|
||||
},
|
||||
topStateChange: {
|
||||
registrationName: 'onStateChange',
|
||||
},
|
||||
topTextInput: {
|
||||
registrationName: 'onTextInput',
|
||||
},
|
||||
topTextLayout: {
|
||||
registrationName: 'onTextLayout',
|
||||
},
|
||||
};
|
||||
|
||||
let ReactNativeEventTypes;
|
||||
if (Platform.OS === 'ios') {
|
||||
ReactNativeEventTypes = {
|
||||
customBubblingEventTypes: IOS_BUBBLING_EVENT_TYPES,
|
||||
customDirectEventTypes: IOS_DIRECT_EVENT_TYPES,
|
||||
};
|
||||
} else if (Platform.OS === 'android') {
|
||||
ReactNativeEventTypes = {
|
||||
customBubblingEventTypes: ANDROID_BUBBLING_EVENT_TYPES,
|
||||
customDirectEventTypes: ANDROID_DIRECT_EVENT_TYPES,
|
||||
};
|
||||
} else {
|
||||
ReactNativeEventTypes = {
|
||||
customBubblingEventTypes: emptyObject,
|
||||
customDirectEventTypes: emptyObject,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ReactNativeEventTypes;
|
||||
@@ -96,6 +96,7 @@ const ReactNativeFiber: ReactNativeType = {
|
||||
NativeMethodsMixin: require('NativeMethodsMixin'),
|
||||
|
||||
// Used by react-native-github/Libraries/ components
|
||||
ReactNativeBridgeEventPlugin: require('ReactNativeBridgeEventPlugin'), // requireNativeComponent
|
||||
ReactGlobalSharedState: require('ReactGlobalSharedState'), // Systrace
|
||||
ReactNativeComponentTree: require('ReactNativeComponentTree'), // InspectorUtils, ScrollResponder
|
||||
ReactNativePropRegistry: require('ReactNativePropRegistry'), // flattenStyle, Stylesheet
|
||||
|
||||
@@ -34,9 +34,22 @@ export type MeasureLayoutOnSuccessCallback = (
|
||||
height: number,
|
||||
) => void;
|
||||
|
||||
type BubblingEventType = {
|
||||
phasedRegistrationNames: {
|
||||
captured: string,
|
||||
bubbled: string,
|
||||
},
|
||||
};
|
||||
|
||||
type DirectEventType = {
|
||||
registrationName: string,
|
||||
};
|
||||
|
||||
export type ReactNativeBaseComponentViewConfig = {
|
||||
validAttributes: Object,
|
||||
uiViewClassName: string,
|
||||
bubblingEventTypes?: {[topLevelType: string]: BubblingEventType},
|
||||
directEventTypes?: {[topLevelType: string]: DirectEventType},
|
||||
propTypes?: Object,
|
||||
};
|
||||
|
||||
@@ -59,12 +72,17 @@ export type NativeMethodsMixinType = {
|
||||
setNativeProps(nativeProps: Object): void,
|
||||
};
|
||||
|
||||
type ReactNativeBridgeEventPlugin = {
|
||||
processEventTypes(viewConfig: ReactNativeBaseComponentViewConfig): void,
|
||||
};
|
||||
|
||||
type SecretInternalsType = {
|
||||
NativeMethodsMixin: NativeMethodsMixinType,
|
||||
createReactNativeComponentClass(
|
||||
name: string,
|
||||
callback: ViewConfigGetter,
|
||||
): any,
|
||||
ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin,
|
||||
ReactNativeComponentTree: any,
|
||||
ReactNativePropRegistry: any,
|
||||
// TODO (bvaughn) Decide which additional types to expose here?
|
||||
|
||||
@@ -15,10 +15,55 @@ var PropTypes;
|
||||
var RCTEventEmitter;
|
||||
var React;
|
||||
var ReactNative;
|
||||
var ReactNativeBridgeEventPlugin;
|
||||
var ResponderEventPlugin;
|
||||
var UIManager;
|
||||
var createReactNativeComponentClass;
|
||||
|
||||
// Parallels requireNativeComponent() in that it lazily constructs a view config,
|
||||
// And registers view manager event types with ReactNativeBridgeEventPlugin.
|
||||
const fakeRequireNativeComponent = (uiViewClassName, validAttributes) => {
|
||||
const getViewConfig = () => {
|
||||
const viewConfig = {
|
||||
uiViewClassName,
|
||||
validAttributes,
|
||||
bubblingEventTypes: {
|
||||
topTouchCancel: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onTouchCancel',
|
||||
captured: 'onTouchCancelCapture',
|
||||
},
|
||||
},
|
||||
topTouchEnd: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onTouchEnd',
|
||||
captured: 'onTouchEndCapture',
|
||||
},
|
||||
},
|
||||
topTouchMove: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onTouchMove',
|
||||
captured: 'onTouchMoveCapture',
|
||||
},
|
||||
},
|
||||
topTouchStart: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onTouchStart',
|
||||
captured: 'onTouchStartCapture',
|
||||
},
|
||||
},
|
||||
},
|
||||
directEventTypes: {},
|
||||
};
|
||||
|
||||
ReactNativeBridgeEventPlugin.processEventTypes(viewConfig);
|
||||
|
||||
return viewConfig;
|
||||
};
|
||||
|
||||
return createReactNativeComponentClass(uiViewClassName, getViewConfig);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
@@ -26,18 +71,37 @@ beforeEach(() => {
|
||||
RCTEventEmitter = require('RCTEventEmitter');
|
||||
React = require('react');
|
||||
ReactNative = require('react-native');
|
||||
ReactNativeBridgeEventPlugin = require('ReactNativeBridgeEventPlugin');
|
||||
ResponderEventPlugin = require('ResponderEventPlugin');
|
||||
UIManager = require('UIManager');
|
||||
createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
});
|
||||
|
||||
it('fails if unknown/unsupported event types are dispatched', () => {
|
||||
expect(RCTEventEmitter.register.mock.calls.length).toBe(1);
|
||||
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||
var View = fakeRequireNativeComponent('View', {});
|
||||
|
||||
ReactNative.render(<View onUnspecifiedEvent={() => {}} />, 1);
|
||||
|
||||
expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchSnapshot();
|
||||
expect(UIManager.createView.mock.calls.length).toBe(1);
|
||||
|
||||
const target = UIManager.createView.mock.calls[0][0];
|
||||
|
||||
expect(() => {
|
||||
EventEmitter.receiveTouches(
|
||||
'unspecifiedEvent',
|
||||
[{target, identifier: 17}],
|
||||
[0],
|
||||
);
|
||||
}).toThrow('Unsupported top level event type "unspecifiedEvent" dispatched');
|
||||
});
|
||||
|
||||
it('handles events', () => {
|
||||
expect(RCTEventEmitter.register.mock.calls.length).toBe(1);
|
||||
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||
var View = createReactNativeComponentClass('View', () => ({
|
||||
validAttributes: {foo: true},
|
||||
uiViewClassName: 'View',
|
||||
}));
|
||||
var View = fakeRequireNativeComponent('View', {foo: true});
|
||||
|
||||
var log = [];
|
||||
ReactNative.render(
|
||||
@@ -93,11 +157,7 @@ it('handles events', () => {
|
||||
it('handles events on text nodes', () => {
|
||||
expect(RCTEventEmitter.register.mock.calls.length).toBe(1);
|
||||
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||
|
||||
var Text = createReactNativeComponentClass('Text', () => ({
|
||||
validAttributes: {foo: true},
|
||||
uiViewClassName: 'Text',
|
||||
}));
|
||||
var Text = fakeRequireNativeComponent('Text', {});
|
||||
|
||||
class ContextHack extends React.Component {
|
||||
static childContextTypes = {isInAParentText: PropTypes.bool};
|
||||
@@ -179,10 +239,7 @@ it('handles events on text nodes', () => {
|
||||
|
||||
it('handles when a responder is unmounted while a touch sequence is in progress', () => {
|
||||
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||
var View = createReactNativeComponentClass('View', () => ({
|
||||
validAttributes: {id: true},
|
||||
uiViewClassName: 'View',
|
||||
}));
|
||||
var View = fakeRequireNativeComponent('View', {id: true});
|
||||
|
||||
function getViewById(id) {
|
||||
return UIManager.createView.mock.calls.find(
|
||||
@@ -273,10 +330,8 @@ it('handles when a responder is unmounted while a touch sequence is in progress'
|
||||
|
||||
it('handles events without target', () => {
|
||||
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||
var View = createReactNativeComponentClass('View', () => ({
|
||||
validAttributes: {id: true},
|
||||
uiViewClassName: 'View',
|
||||
}));
|
||||
|
||||
var View = fakeRequireNativeComponent('View', {id: true});
|
||||
|
||||
function getViewById(id) {
|
||||
return UIManager.createView.mock.calls.find(
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`fails if unknown/unsupported event types are dispatched 1`] = `
|
||||
"<native root> {}
|
||||
View null"
|
||||
`;
|
||||
|
||||
exports[`handles events 1`] = `
|
||||
"<native root> {}
|
||||
View {\\"foo\\":\\"outer\\"}
|
||||
|
||||
Reference in New Issue
Block a user