From 6e1b62441b63bd450442c2cd050e7e592d1b012d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= <etienne@plot.ly>
Date: Mon, 17 Dec 2018 15:37:16 -0500
Subject: [PATCH] fix #3330 - fix hoverChanged for traces with pointNumbers

... and w/o pointNumber (n.b. singular).
---
 src/components/fx/hover.js             |  5 +++-
 test/jasmine/tests/hover_label_test.js | 40 ++++++++++++++++++++------
 2 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js
index 94598806085..daa77e3700d 100644
--- a/src/components/fx/hover.js
+++ b/src/components/fx/hover.js
@@ -1565,8 +1565,11 @@ function hoverChanged(gd, evt, oldhoverdata) {
     for(var i = oldhoverdata.length - 1; i >= 0; i--) {
         var oldPt = oldhoverdata[i];
         var newPt = gd._hoverdata[i];
+
         if(oldPt.curveNumber !== newPt.curveNumber ||
-                String(oldPt.pointNumber) !== String(newPt.pointNumber)) {
+            String(oldPt.pointNumber) !== String(newPt.pointNumber) ||
+            String(oldPt.pointNumbers) !== String(newPt.pointNumbers)
+        ) {
             return true;
         }
     }
diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js
index 5e0ea9a037b..d2cc007bac6 100644
--- a/test/jasmine/tests/hover_label_test.js
+++ b/test/jasmine/tests/hover_label_test.js
@@ -942,7 +942,6 @@ describe('hover info', function() {
     describe('histogram hover info', function() {
         it('shows the data range when bins have multiple values', function(done) {
             var gd = createGraphDiv();
-            var pts;
 
             Plotly.plot(gd, [{
                 x: [0, 2, 3, 4, 5, 6, 7],
@@ -954,18 +953,15 @@ describe('hover info', function() {
                 margin: {l: 0, t: 0, r: 0, b: 0}
             })
             .then(function() {
-                gd.on('plotly_hover', function(e) { pts = e.points; });
+                var pts = null;
+                gd.once('plotly_hover', function(e) { pts = e.points; });
 
                 _hoverNatural(gd, 250, 200);
-                assertHoverLabelContent({
-                    nums: '3',
-                    axis: '3 - 5'
-                });
-            })
-            .then(function() {
+                assertHoverLabelContent({nums: '3', axis: '3 - 5'});
+                if(pts === null) fail('no hover evt triggered');
                 expect(pts.length).toBe(1);
-                var pt = pts[0];
 
+                var pt = pts[0];
                 expect(pt.curveNumber).toBe(0);
                 expect(pt.binNumber).toBe(1);
                 expect(pt.pointNumbers).toEqual([2, 3, 4]);
@@ -976,6 +972,32 @@ describe('hover info', function() {
                 expect(pt.xaxis).toBe(gd._fullLayout.xaxis);
                 expect(pt.yaxis).toBe(gd._fullLayout.yaxis);
             })
+            .then(function() {
+                var pts = null;
+                gd.once('plotly_hover', function(e) { pts = e.points; });
+
+                _hoverNatural(gd, 250, 200);
+                expect(pts).toBe(null, 'should not emit hover event on same pt');
+            })
+            .then(function() {
+                var pts = null;
+                gd.once('plotly_hover', function(e) { pts = e.points; });
+
+                _hoverNatural(gd, 350, 200);
+                assertHoverLabelContent({nums: '2', axis: '6 - 8'});
+                expect(pts.length).toBe(1);
+
+                var pt = pts[0];
+                expect(pt.curveNumber).toBe(0);
+                expect(pt.binNumber).toBe(2);
+                expect(pt.pointNumbers).toEqual([5, 6]);
+                expect(pt.x).toBe(7);
+                expect(pt.y).toBe(2);
+                expect(pt.data).toBe(gd.data[0]);
+                expect(pt.fullData).toBe(gd._fullData[0]);
+                expect(pt.xaxis).toBe(gd._fullLayout.xaxis);
+                expect(pt.yaxis).toBe(gd._fullLayout.yaxis);
+            })
             .catch(failTest)
             .then(done);
         });