@@ -7038,3 +7038,100 @@ describe('hover on traces with (x|y)hoverformat', function() {
7038
7038
. then ( done , done . fail ) ;
7039
7039
} ) ;
7040
7040
} ) ;
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