@@ -107,18 +107,21 @@ describe('Mouse hover hook', () => {
107107 expect ( customProps . highlightX ) . toHaveBeenCalledTimes ( 1 ) ;
108108 } ) ;
109109
110- test ( 'does not clear highlighted X on mouseOut if moving within popover' , ( ) => {
110+ test ( 'does not clear highlighted X on mouseOut if moving into popover' , ( ) => {
111111 const SvgElementDummy = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'svg' ) ;
112112 const lineElement = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'line' ) ;
113113
114114 SvgElementDummy . appendChild ( lineElement ) ;
115- const popoverWrapper = document . createElement ( 'div' ) ;
116- const popoverDiv = document . createElement ( 'div' ) ;
117- popoverWrapper . appendChild ( popoverDiv ) ;
115+ // Simulate the real DOM structure: transition wrapper > popover element > popover content
116+ const transitionWrapper = document . createElement ( 'div' ) ;
117+ const popoverElement = document . createElement ( 'div' ) ;
118+ const popoverContent = document . createElement ( 'div' ) ;
119+ transitionWrapper . appendChild ( popoverElement ) ;
120+ popoverElement . appendChild ( popoverContent ) ;
118121
119122 const customProps = {
120123 highlightX : jest . fn ( ) ,
121- popoverRef : { current : popoverWrapper } ,
124+ popoverRef : { current : popoverElement } ,
122125 plotRef : { current : { svg : SvgElementDummy , focusApplication : jest . fn ( ) , focusPlot : jest . fn ( ) } } ,
123126 } ;
124127 const { hook } = renderMouseHoverHook ( customProps ) ;
@@ -135,57 +138,75 @@ describe('Mouse hover hook', () => {
135138 expect ( customProps . highlightX ) . toHaveBeenCalledWith ( { scaledX : 100 , label : 0 } ) ;
136139 expect ( customProps . highlightX ) . toHaveBeenCalledTimes ( 1 ) ;
137140
141+ // relatedTarget is inside the popover DOM tree (child of popover)
138142 const mouseOutEvent = {
139- relatedTarget : popoverWrapper ,
140- clientX : 10 ,
141- clientY : 10 ,
143+ relatedTarget : popoverContent ,
142144 } as any ;
143145
144146 act ( ( ) => hook . current . onSVGMouseOut ( mouseOutEvent ) ) ;
145147 expect ( customProps . highlightX ) . toHaveBeenCalledTimes ( 1 ) ;
146148 } ) ;
147149
148- test ( 'clears highlightX when onPopoverLeave is called ' , ( ) => {
150+ test ( 'does not clear highlighted X on mouseOut if moving into popover transition wrapper ' , ( ) => {
149151 const SvgElementDummy = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'svg' ) ;
150- const lineElement = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'line' ) ;
151- SvgElementDummy . appendChild ( lineElement ) ;
152+
153+ // Simulate: transition wrapper > popover element
154+ const transitionWrapper = document . createElement ( 'div' ) ;
155+ const popoverElement = document . createElement ( 'div' ) ;
156+ transitionWrapper . appendChild ( popoverElement ) ;
157+
158+ const customProps = {
159+ highlightX : jest . fn ( ) ,
160+ popoverRef : { current : popoverElement } ,
161+ plotRef : { current : { svg : SvgElementDummy , focusApplication : jest . fn ( ) , focusPlot : jest . fn ( ) } } ,
162+ } ;
163+ const { hook } = renderMouseHoverHook ( customProps ) ;
164+
165+ // relatedTarget is the transition wrapper (parent of popoverRef)
166+ const mouseOutEvent = {
167+ relatedTarget : transitionWrapper ,
168+ } as any ;
169+
170+ act ( ( ) => hook . current . onSVGMouseOut ( mouseOutEvent ) ) ;
171+ expect ( customProps . highlightX ) . not . toHaveBeenCalled ( ) ;
172+ } ) ;
173+
174+ test ( 'clears highlighted X on mouseOut when leaving SVG near popover but not into it' , ( ) => {
175+ const SvgElementDummy = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'svg' ) ;
176+
177+ // Simulate: transition wrapper > popover element
178+ const transitionWrapper = document . createElement ( 'div' ) ;
179+ const popoverElement = document . createElement ( 'div' ) ;
180+ transitionWrapper . appendChild ( popoverElement ) ;
152181
153182 const customProps = {
154183 highlightX : jest . fn ( ) ,
155184 clearHighlightedSeries : jest . fn ( ) ,
185+ popoverRef : { current : popoverElement } ,
156186 plotRef : { current : { svg : SvgElementDummy , focusApplication : jest . fn ( ) , focusPlot : jest . fn ( ) } } ,
157187 } ;
158188 const { hook } = renderMouseHoverHook ( customProps ) ;
159- const event = {
160- relatedTarget : lineElement ,
189+
190+ // relatedTarget is an element outside both SVG and popover (e.g. y-axis area, page body)
191+ const outsideElement = document . createElement ( 'div' ) ;
192+ const mouseOutEvent = {
193+ relatedTarget : outsideElement ,
161194 } as any ;
162- act ( ( ) => hook . current . onPopoverLeave ( event ) ) ;
195+
196+ act ( ( ) => hook . current . onSVGMouseOut ( mouseOutEvent ) ) ;
163197 expect ( customProps . highlightX ) . toHaveBeenCalledWith ( null ) ;
164198 expect ( customProps . clearHighlightedSeries ) . toHaveBeenCalledTimes ( 1 ) ;
165199 } ) ;
166200
167- test ( 'does not clear highlightX when onPopoverLeave is called (pointing device exited from the svg)' , ( ) => {
168- const svgMock = { contains : ( ) => true } as unknown as SVGSVGElement ;
201+ test ( 'clears highlightX when onPopoverLeave is called' , ( ) => {
169202 const customProps = {
170203 highlightX : jest . fn ( ) ,
171204 clearHighlightedSeries : jest . fn ( ) ,
172- isHandlersDisabled : true ,
173- plotRef : {
174- current : {
175- svg : svgMock ,
176- focusApplication : jest . fn ( ) ,
177- focusPlot : jest . fn ( ) ,
178- } ,
179- } ,
180205 } ;
181-
182206 const { hook } = renderMouseHoverHook ( customProps ) ;
183- const event = {
184- relatedTarget : null ,
185- } as any ;
186- act ( ( ) => hook . current . onPopoverLeave ( event ) ) ;
187- expect ( customProps . highlightX ) . not . toHaveBeenCalled ( ) ;
188- expect ( customProps . clearHighlightedSeries ) . not . toHaveBeenCalled ( ) ;
207+ act ( ( ) => hook . current . onPopoverLeave ( ) ) ;
208+ expect ( customProps . highlightX ) . toHaveBeenCalledWith ( null ) ;
209+ expect ( customProps . clearHighlightedSeries ) . toHaveBeenCalledTimes ( 1 ) ;
189210 } ) ;
190211
191212 test ( 'does not clear highlightX when onPopoverLeave is called if isHandlersDisabled is true' , ( ) => {
@@ -195,10 +216,7 @@ describe('Mouse hover hook', () => {
195216 isHandlersDisabled : true ,
196217 } ;
197218 const { hook } = renderMouseHoverHook ( customProps ) ;
198- const event = {
199- relatedTarget : null ,
200- } as any ;
201- act ( ( ) => hook . current . onPopoverLeave ( event ) ) ;
219+ act ( ( ) => hook . current . onPopoverLeave ( ) ) ;
202220 expect ( customProps . highlightX ) . not . toHaveBeenCalled ( ) ;
203221 expect ( customProps . clearHighlightedSeries ) . not . toHaveBeenCalled ( ) ;
204222 } ) ;
0 commit comments