@@ -7,9 +7,12 @@ import { TimeGraphChart } from '../time-graph-chart';
77
88// Mock the chart layer
99function createMockChart ( states : any [ ] = [ ] ) {
10+ const rowComponents = new Map ( ) ;
1011 return {
1112 getStatesAtTimestamp : jest . fn ( ) . mockReturnValue ( states ) ,
12- rowComponents : new Map ( )
13+ getRowComponent : ( id : number ) => rowComponents . get ( id ) ,
14+ getRowComponents : ( ) => rowComponents ,
15+ rowComponents
1316 } as unknown as TimeGraphChart ;
1417}
1518
@@ -50,13 +53,13 @@ describe('TimeGraphChartRichCursor', () => {
5053 it ( 'registers mousemove and mouseleave handlers' , ( ) => {
5154 const { cursor } = createSetup ( ) ;
5255 expect ( ( cursor as any ) . _mouseMoveHandler ) . toBeDefined ( ) ;
53- expect ( ( cursor as any ) . _mouseLeaveHandler ) . toBeDefined ( ) ;
56+ expect ( ( cursor as any ) . _pointerLeaveHandler ) . toBeDefined ( ) ;
5457 } ) ;
5558
56- it ( 'adds graphics and tooltip container to stage ' , ( ) => {
57- const { stage } = createSetup ( ) ;
58- // stage has layer + graphics + tooltipContainer
59- expect ( stage . children . length ) . toBeGreaterThanOrEqual ( 3 ) ;
59+ it ( 'adds graphics and tooltip container to layer ' , ( ) => {
60+ const { cursor } = createSetup ( ) ;
61+ // layer has graphics + tooltipContainer
62+ expect ( ( cursor as any ) . layer . children . length ) . toBeGreaterThanOrEqual ( 2 ) ;
6063 } ) ;
6164 } ) ;
6265
@@ -136,7 +139,8 @@ describe('TimeGraphChartRichCursor', () => {
136139 ( chartLayer as any ) . rowComponents . set ( 1 , { position : { y : 10 } } ) ;
137140
138141 ( cursor as any ) . drawCursor ( 100 ) ;
139- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBeGreaterThan ( 0 ) ;
142+ const visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
143+ expect ( visibleChildren . length ) . toBeGreaterThan ( 0 ) ;
140144 } ) ;
141145
142146 it ( 'falls back to row name when state has no label' , ( ) => {
@@ -148,7 +152,8 @@ describe('TimeGraphChartRichCursor', () => {
148152
149153 ( cursor as any ) . drawCursor ( 100 ) ;
150154 // Should still create tooltip children (bg + text)
151- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 2 ) ;
155+ const visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
156+ expect ( visibleChildren . length ) . toBe ( 2 ) ;
152157 } ) ;
153158
154159 it ( 'does not create tooltip when no label and no row name' , ( ) => {
@@ -159,7 +164,8 @@ describe('TimeGraphChartRichCursor', () => {
159164 ( chartLayer as any ) . rowComponents . set ( 1 , { position : { y : 10 } } ) ;
160165
161166 ( cursor as any ) . drawCursor ( 100 ) ;
162- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 0 ) ;
167+ const visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
168+ expect ( visibleChildren . length ) . toBe ( 0 ) ;
163169 } ) ;
164170
165171 it ( 'flips tooltip to left when near right edge' , ( ) => {
@@ -171,9 +177,10 @@ describe('TimeGraphChartRichCursor', () => {
171177
172178 // Draw near right edge (canvas is 800px wide)
173179 ( cursor as any ) . drawCursor ( 790 ) ;
174- const bg = ( cursor as any ) . tooltipContainer . children [ 0 ] as PIXI . Graphics ;
175- // The tooltip box should be positioned to the left of cursor
176- expect ( bg ) . toBeTruthy ( ) ;
180+ const textObj = ( cursor as any ) . tooltipContainer . children [ 1 ] as PIXI . Text ;
181+ // The tooltip text should be positioned to the left of cursor
182+ expect ( textObj ) . toBeTruthy ( ) ;
183+ expect ( textObj . x ) . toBeLessThan ( 790 ) ;
177184 } ) ;
178185
179186 it ( 'clears tooltips on each redraw' , ( ) => {
@@ -184,11 +191,13 @@ describe('TimeGraphChartRichCursor', () => {
184191 ( chartLayer as any ) . rowComponents . set ( 1 , { position : { y : 10 } } ) ;
185192
186193 ( cursor as any ) . drawCursor ( 100 ) ;
187- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 2 ) ;
194+ let visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
195+ expect ( visibleChildren . length ) . toBe ( 2 ) ;
188196
189197 ( cursor as any ) . drawCursor ( 200 ) ;
190- // Should still be 2 (cleared old, added new)
191- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 2 ) ;
198+ // Should still be 2 visible (cleared old, reused for new)
199+ visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
200+ expect ( visibleChildren . length ) . toBe ( 2 ) ;
192201 } ) ;
193202
194203 it ( 'creates multiple tooltips for multiple hits' , ( ) => {
@@ -204,7 +213,8 @@ describe('TimeGraphChartRichCursor', () => {
204213
205214 ( cursor as any ) . drawCursor ( 100 ) ;
206215 // 3 tooltips × 2 children each (bg + text)
207- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 6 ) ;
216+ const visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
217+ expect ( visibleChildren . length ) . toBe ( 6 ) ;
208218 } ) ;
209219 } ) ;
210220
@@ -217,25 +227,29 @@ describe('TimeGraphChartRichCursor', () => {
217227 ( chartLayer as any ) . rowComponents . set ( 1 , { position : { y : 10 } } ) ;
218228
219229 ( cursor as any ) . drawCursor ( 100 ) ;
220- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 2 ) ;
230+ let visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
231+ expect ( visibleChildren . length ) . toBe ( 2 ) ;
221232
222233 // Simulate mouseleave
223- ( cursor as any ) . _mouseLeaveHandler ( ) ;
224- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 0 ) ;
234+ ( cursor as any ) . _pointerLeaveHandler ( ) ;
235+ visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
236+ expect ( visibleChildren . length ) . toBe ( 0 ) ;
225237 } ) ;
226238 } ) ;
227239
228240 describe ( 'update' , ( ) => {
229- it ( 'clears graphics and tooltips on update' , ( ) => {
241+ it ( 'redraws tooltips on update when mouse is in canvas ' , ( ) => {
230242 const hits = [
231243 { row : { id : 1 , name : 'R' } , state : { label : 'S' , range : { start : BigInt ( 0 ) , end : BigInt ( 100 ) } } }
232244 ] ;
233245 const { cursor, chartLayer } = createSetup ( hits ) ;
234246 ( chartLayer as any ) . rowComponents . set ( 1 , { position : { y : 10 } } ) ;
235247
236- ( cursor as any ) . drawCursor ( 100 ) ;
248+ ( cursor as any ) . isMouseInCanvas = true ;
249+ ( cursor as any ) . lastMouseX = 100 ;
237250 cursor . update ( ) ;
238- expect ( ( cursor as any ) . tooltipContainer . children . length ) . toBe ( 0 ) ;
251+ const visibleChildren = ( cursor as any ) . tooltipContainer . children . filter ( ( c : any ) => c . visible ) ;
252+ expect ( visibleChildren . length ) . toBe ( 2 ) ;
239253 } ) ;
240254 } ) ;
241255
@@ -244,8 +258,8 @@ describe('TimeGraphChartRichCursor', () => {
244258 const { cursor, canvas } = createSetup ( ) ;
245259 const removeSpy = jest . spyOn ( canvas , 'removeEventListener' ) ;
246260 cursor . destroy ( ) ;
247- expect ( removeSpy ) . toHaveBeenCalledWith ( 'mousemove ' , expect . any ( Function ) ) ;
248- expect ( removeSpy ) . toHaveBeenCalledWith ( 'mouseleave ' , expect . any ( Function ) ) ;
261+ expect ( removeSpy ) . toHaveBeenCalledWith ( 'pointermove ' , expect . any ( Function ) ) ;
262+ expect ( removeSpy ) . toHaveBeenCalledWith ( 'pointerleave ' , expect . any ( Function ) ) ;
249263 } ) ;
250264 } ) ;
251265
0 commit comments