diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 3265e103d1a..dcf4bd00b2b 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -301,7 +301,6 @@ export default class Scale extends Element { * @since 3.0 */ getMinMax(canStack) { - // eslint-disable-next-line prefer-const let {min, max, minDefined, maxDefined} = this.getUserBounds(); let range; diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index e76b1479e06..b39681ce2ca 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -38,6 +38,11 @@ const positioners = { } } + // No visible items where found, return false so we don't have to divide by 0 which reduces in NaN + if (count === 0 || xSet.size === 0) { + return false; + } + const xAverage = [...xSet].reduce((a, b) => a + b) / xSet.size; return { diff --git a/test/specs/plugin.tooltip.tests.js b/test/specs/plugin.tooltip.tests.js index 69e8c7f64c9..94ae45b7246 100644 --- a/test/specs/plugin.tooltip.tests.js +++ b/test/specs/plugin.tooltip.tests.js @@ -1144,6 +1144,15 @@ describe('Plugin.Tooltip', function() { expect(tooltipModel.caretX).not.toBe(xPositionArrayAverage); expect(tooltipModel.caretX).toBe(xPositionSetAverage); }); + + it('Should not fail with all hiden data elements on the average positioner', function() { + const averagePositioner = tooltipPlugin.positioners.average; + + // Simulate `hasValue` returns false + expect(() => averagePositioner([{x: 'invalidNumber', y: 'invalidNumber'}])).not.toThrow(); + const result = averagePositioner([{x: 'invalidNumber', y: 'invalidNumber'}]); + expect(result).toBe(false); + }); }); it('Should avoid tooltip truncation in x axis if there is enough space to show tooltip without truncation', async function() {