@@ -56,3 +56,94 @@ export function withReplacedMethod(
5656export function toArray ( obj : any ) {
5757 return Array . isArray ( obj ) ? obj : [ obj ] ;
5858}
59+
60+ /**
61+ * @param node The node to start searching for a host node
62+ * @returns The first host node in the children of the passed in node. Will
63+ * return the passed in node if it is a host node
64+ */
65+ export function nodeToHostNode ( node : RSTNode | string | null ) : Node | null {
66+ if ( node == null || typeof node == 'string' ) {
67+ // Returning `null` here causes `wrapper.text()` to return nothing for a
68+ // wrapper around a `Text` node. That's not intuitive perhaps, but it
69+ // matches the React adapters' behaviour.
70+ return null ;
71+ } else if ( node . nodeType === 'host' ) {
72+ return node . instance ;
73+ } else if ( node . rendered . length > 0 ) {
74+ for ( let child of node . rendered ) {
75+ let childHostNode = nodeToHostNode ( child ) ;
76+ if ( childHostNode ) {
77+ return childHostNode ;
78+ }
79+ }
80+ }
81+
82+ return null ;
83+ }
84+
85+ // Copied from enzyme-adapter-utils. We don't include that package because it depends on React
86+ const nativeToReactEventMap : Record < string , string > = {
87+ compositionend : 'compositionEnd' ,
88+ compositionstart : 'compositionStart' ,
89+ compositionupdate : 'compositionUpdate' ,
90+ keydown : 'keyDown' ,
91+ keyup : 'keyUp' ,
92+ keypress : 'keyPress' ,
93+ contextmenu : 'contextMenu' ,
94+ dblclick : 'doubleClick' ,
95+ doubleclick : 'doubleClick' ,
96+ dragend : 'dragEnd' ,
97+ dragenter : 'dragEnter' ,
98+ dragexist : 'dragExit' ,
99+ dragleave : 'dragLeave' ,
100+ dragover : 'dragOver' ,
101+ dragstart : 'dragStart' ,
102+ mousedown : 'mouseDown' ,
103+ mousemove : 'mouseMove' ,
104+ mouseout : 'mouseOut' ,
105+ mouseover : 'mouseOver' ,
106+ mouseup : 'mouseUp' ,
107+ touchcancel : 'touchCancel' ,
108+ touchend : 'touchEnd' ,
109+ touchmove : 'touchMove' ,
110+ touchstart : 'touchStart' ,
111+ canplay : 'canPlay' ,
112+ canplaythrough : 'canPlayThrough' ,
113+ durationchange : 'durationChange' ,
114+ loadeddata : 'loadedData' ,
115+ loadedmetadata : 'loadedMetadata' ,
116+ loadstart : 'loadStart' ,
117+ ratechange : 'rateChange' ,
118+ timeupdate : 'timeUpdate' ,
119+ volumechange : 'volumeChange' ,
120+ beforeinput : 'beforeInput' ,
121+ mouseenter : 'mouseEnter' ,
122+ mouseleave : 'mouseLeave' ,
123+ transitionend : 'transitionEnd' ,
124+ animationstart : 'animationStart' ,
125+ animationiteration : 'animationIteration' ,
126+ animationend : 'animationEnd' ,
127+ pointerdown : 'pointerDown' ,
128+ pointermove : 'pointerMove' ,
129+ pointerup : 'pointerUp' ,
130+ pointercancel : 'pointerCancel' ,
131+ gotpointercapture : 'gotPointerCapture' ,
132+ lostpointercapture : 'lostPointerCapture' ,
133+ pointerenter : 'pointerEnter' ,
134+ pointerleave : 'pointerLeave' ,
135+ pointerover : 'pointerOver' ,
136+ pointerout : 'pointerOut' ,
137+ auxclick : 'auxClick' ,
138+ } ;
139+
140+ export function mapNativeEventNames ( event : string ) : string {
141+ return nativeToReactEventMap [ event ] || event ;
142+ }
143+
144+ // 'click' => 'onClick'
145+ // 'mouseEnter' => 'onMouseEnter'
146+ export function propFromEvent ( event : string ) : string {
147+ const nativeEvent = mapNativeEventNames ( event ) ;
148+ return `on${ nativeEvent [ 0 ] . toUpperCase ( ) } ${ nativeEvent . slice ( 1 ) } ` ;
149+ }
0 commit comments