@@ -7038,3 +7038,100 @@ describe('hover on traces with (x|y)hoverformat', function() {
70387038 . then ( done , done . fail ) ;
70397039 } ) ;
70407040} ) ;
7041+
7042+ describe ( 'hoverlabel.showarrow' , function ( ) {
7043+ 'use strict' ;
7044+
7045+ var gd ;
7046+
7047+ beforeEach ( function ( ) {
7048+ gd = createGraphDiv ( ) ;
7049+ } ) ;
7050+
7051+ afterEach ( destroyGraphDiv ) ;
7052+
7053+ function _hover ( x , y ) {
7054+ mouseEvent ( 'mousemove' , x , y ) ;
7055+ Lib . clearThrottle ( ) ;
7056+ }
7057+
7058+ function getHoverPath ( ) {
7059+ var hoverLabels = d3SelectAll ( 'g.hovertext' ) ;
7060+ if ( hoverLabels . size ( ) === 0 ) return null ;
7061+ return hoverLabels . select ( 'path' ) . attr ( 'd' ) ;
7062+ }
7063+
7064+ it ( 'should show hover arrow by default' , function ( done ) {
7065+ Plotly . newPlot ( gd , [ {
7066+ x : [ 1 , 2 , 3 ] ,
7067+ y : [ 1 , 2 , 1 ] ,
7068+ type : 'scatter' ,
7069+ mode : 'markers'
7070+ } ] , {
7071+ width : 400 ,
7072+ height : 400 ,
7073+ margin : { l : 50 , t : 50 , r : 50 , b : 50 }
7074+ } )
7075+ . then ( function ( ) {
7076+ _hover ( 200 , 200 ) ; // Hover over middle point
7077+ } )
7078+ . then ( delay ( HOVERMINTIME * 1.1 ) )
7079+ . then ( function ( ) {
7080+ var pathD = getHoverPath ( ) ;
7081+ expect ( pathD ) . not . toBeNull ( 'hover path should exist' ) ;
7082+ // Arrow paths contain 'L' commands for the triangular pointer
7083+ expect ( pathD ) . toMatch ( / M 0 , 0 L / , 'path should contain arrow (L command from origin)' ) ;
7084+ } )
7085+ . then ( done , done . fail ) ;
7086+ } ) ;
7087+
7088+ it ( 'should hide hover arrow when showarrow is false' , function ( done ) {
7089+ Plotly . newPlot ( gd , [ {
7090+ x : [ 1 , 2 , 3 ] ,
7091+ y : [ 1 , 2 , 1 ] ,
7092+ type : 'scatter' ,
7093+ mode : 'markers'
7094+ } ] , {
7095+ width : 400 ,
7096+ height : 400 ,
7097+ margin : { l : 50 , t : 50 , r : 50 , b : 50 } ,
7098+ hoverlabel : { showarrow : false }
7099+ } )
7100+ . then ( function ( ) {
7101+ _hover ( 200 , 200 ) ; // Hover over middle point
7102+ } )
7103+ . then ( delay ( HOVERMINTIME * 1.1 ) )
7104+ . then ( function ( ) {
7105+ var pathD = getHoverPath ( ) ;
7106+ expect ( pathD ) . not . toBeNull ( 'hover path should exist' ) ;
7107+ // No-arrow paths should be simple rectangles (no 'L' commands from origin)
7108+ expect ( pathD ) . not . toMatch ( / M 0 , 0 L / , 'path should not contain arrow' ) ;
7109+ expect ( pathD ) . toMatch ( / ^ M - / , 'path should start with rectangle (M- for left edge)' ) ;
7110+ } )
7111+ . then ( done , done . fail ) ;
7112+ } ) ;
7113+
7114+ it ( 'should work at trace level' , function ( done ) {
7115+ Plotly . newPlot ( gd , [ {
7116+ x : [ 1 , 2 , 3 ] ,
7117+ y : [ 1 , 2 , 1 ] ,
7118+ type : 'scatter' ,
7119+ mode : 'markers' ,
7120+ hoverlabel : { showarrow : false }
7121+ } ] , {
7122+ width : 400 ,
7123+ height : 400 ,
7124+ margin : { l : 50 , t : 50 , r : 50 , b : 50 }
7125+ } )
7126+ . then ( function ( ) {
7127+ _hover ( 200 , 200 ) ; // Hover over middle point
7128+ } )
7129+ . then ( delay ( HOVERMINTIME * 1.1 ) )
7130+ . then ( function ( ) {
7131+ var pathD = getHoverPath ( ) ;
7132+ expect ( pathD ) . not . toBeNull ( 'hover path should exist' ) ;
7133+ expect ( pathD ) . not . toMatch ( / M 0 , 0 L / , 'trace-level showarrow:false should hide arrow' ) ;
7134+ } )
7135+ . then ( done , done . fail ) ;
7136+ } ) ;
7137+ } ) ;
0 commit comments