@@ -77,8 +77,13 @@ const mockSvg = {
7777 style : jest . fn ( ) . mockReturnThis ( ) ,
7878} ;
7979
80+ // Store the last Datamap config for assertions
81+ let lastDatamapConfig : Record < string , unknown > | null = null ;
82+
8083jest . mock ( 'datamaps/dist/datamaps.all.min' , ( ) =>
8184 jest . fn ( ) . mockImplementation ( config => {
85+ // Store config for test assertions
86+ lastDatamapConfig = config ;
8287 // Call the done callback immediately to simulate Datamap initialization
8388 if ( config . done ) {
8489 config . done ( {
@@ -158,9 +163,11 @@ test('sets up mouseover and mouseout handlers on countries', () => {
158163 expect ( mockSvg . selectAll ) . toHaveBeenCalledWith ( '.datamaps-subunit' ) ;
159164 const onCalls = mockSvg . on . mock . calls ;
160165
161- // Find mouseover and mouseout handler registrations
162- const hasMouseover = onCalls . some ( call => call [ 0 ] === 'mouseover' ) ;
163- const hasMouseout = onCalls . some ( call => call [ 0 ] === 'mouseout' ) ;
166+ // Find mouseover and mouseout handler registrations (namespaced events)
167+ const hasMouseover = onCalls . some (
168+ call => call [ 0 ] === 'mouseover.fillPreserve' ,
169+ ) ;
170+ const hasMouseout = onCalls . some ( call => call [ 0 ] === 'mouseout.fillPreserve' ) ;
164171
165172 expect ( hasMouseover ) . toBe ( true ) ;
166173 expect ( hasMouseout ) . toBe ( true ) ;
@@ -199,9 +206,9 @@ test('stores original fill color on mouseover', () => {
199206
200207 jest . spyOn ( d3 as any , 'select' ) . mockReturnValue ( mockD3Selection as any ) ;
201208
202- // Capture the mouseover handler
209+ // Capture the mouseover handler (namespaced event)
203210 mockSvg . on . mockImplementation ( ( event : string , handler : MouseEventHandler ) => {
204- if ( event === 'mouseover' ) {
211+ if ( event === 'mouseover.fillPreserve ' ) {
205212 mouseoverHandler = handler ;
206213 }
207214 return mockSvg ;
@@ -254,9 +261,9 @@ test('restores original fill color on mouseout for country with data', () => {
254261
255262 jest . spyOn ( d3 as any , 'select' ) . mockReturnValue ( mockD3Selection as any ) ;
256263
257- // Capture the mouseout handler
264+ // Capture the mouseout handler (namespaced event)
258265 mockSvg . on . mockImplementation ( ( event : string , handler : MouseEventHandler ) => {
259- if ( event === 'mouseout' ) {
266+ if ( event === 'mouseout.fillPreserve ' ) {
260267 mouseoutHandler = handler ;
261268 }
262269 return mockSvg ;
@@ -310,8 +317,9 @@ test('restores default fill color on mouseout for country with no data', () => {
310317
311318 jest . spyOn ( d3 as any , 'select' ) . mockReturnValue ( mockD3Selection as any ) ;
312319
320+ // Capture the mouseout handler (namespaced event)
313321 mockSvg . on . mockImplementation ( ( event : string , handler : MouseEventHandler ) => {
314- if ( event === 'mouseout' ) {
322+ if ( event === 'mouseout.fillPreserve ' ) {
315323 mouseoutHandler = handler ;
316324 }
317325 return mockSvg ;
@@ -352,11 +360,12 @@ test('does not handle mouse events when inContextMenu is true', () => {
352360
353361 jest . spyOn ( d3 as any , 'select' ) . mockReturnValue ( mockD3Selection as any ) ;
354362
363+ // Capture namespaced event handlers
355364 mockSvg . on . mockImplementation ( ( event : string , handler : MouseEventHandler ) => {
356- if ( event === 'mouseover' ) {
365+ if ( event === 'mouseover.fillPreserve ' ) {
357366 mouseoverHandler = handler ;
358367 }
359- if ( event === 'mouseout' ) {
368+ if ( event === 'mouseout.fillPreserve ' ) {
360369 mouseoutHandler = handler ;
361370 }
362371 return mockSvg ;
@@ -430,3 +439,72 @@ test('calls onContextMenu when provided and right-click occurs', () => {
430439
431440 expect ( mockOnContextMenu ) . toHaveBeenCalledWith ( 100 , 200 , expect . any ( Object ) ) ;
432441} ) ;
442+
443+ test ( 'initializes Datamap with keyed object data for tooltip support' , ( ) => {
444+ WorldMap ( container , baseProps ) ;
445+
446+ // Verify data is an object (not an array) keyed by country codes
447+ expect ( Array . isArray ( lastDatamapConfig ?. data ) ) . toBe ( false ) ;
448+ expect ( typeof lastDatamapConfig ?. data ) . toBe ( 'object' ) ;
449+
450+ const data = lastDatamapConfig ?. data as Record < string , unknown > ;
451+
452+ // Verify the data is keyed by country code
453+ expect ( data ) . toHaveProperty ( 'USA' ) ;
454+ expect ( data ) . toHaveProperty ( 'CAN' ) ;
455+
456+ // Verify the keyed data contains the expected properties for tooltips
457+ expect ( data . USA ) . toMatchObject ( {
458+ country : 'USA' ,
459+ name : 'United States' ,
460+ m1 : 100 ,
461+ m2 : 200 ,
462+ } ) ;
463+ expect ( data . CAN ) . toMatchObject ( {
464+ country : 'CAN' ,
465+ name : 'Canada' ,
466+ m1 : 50 ,
467+ m2 : 100 ,
468+ } ) ;
469+ } ) ;
470+
471+ test ( 'popupTemplate returns tooltip HTML when country data exists' , ( ) => {
472+ WorldMap ( container , baseProps ) ;
473+
474+ const geographyConfig = lastDatamapConfig ?. geographyConfig as Record <
475+ string ,
476+ unknown
477+ > ;
478+ const popupTemplate = geographyConfig ?. popupTemplate as (
479+ geo : unknown ,
480+ d : unknown ,
481+ ) => string ;
482+
483+ const mockGeo = { properties : { name : 'United States' } } ;
484+ const mockCountryData = { name : 'United States' , m1 : 100 } ;
485+
486+ const tooltipHtml = popupTemplate ( mockGeo , mockCountryData ) ;
487+
488+ expect ( tooltipHtml ) . toContain ( 'United States' ) ;
489+ expect ( tooltipHtml ) . toContain ( 'hoverinfo' ) ;
490+ } ) ;
491+
492+ test ( 'popupTemplate handles null/undefined country data gracefully' , ( ) => {
493+ WorldMap ( container , baseProps ) ;
494+
495+ const geographyConfig = lastDatamapConfig ?. geographyConfig as Record <
496+ string ,
497+ unknown
498+ > ;
499+ const popupTemplate = geographyConfig ?. popupTemplate as (
500+ geo : unknown ,
501+ d : unknown ,
502+ ) => string | undefined ;
503+
504+ const mockGeo = { properties : { name : 'Antarctica' } } ;
505+
506+ // When hovering over a country with no data, 'd' will be undefined
507+ const tooltipHtml = popupTemplate ( mockGeo , undefined ) ;
508+
509+ expect ( tooltipHtml ) . toBeFalsy ( ) ;
510+ } ) ;
0 commit comments