diff --git a/frontend/src/metabase/visualizations/lib/apply_tooltips.js b/frontend/src/metabase/visualizations/lib/apply_tooltips.js index 4ffa56dc764ba8908ac38aa8236a154283e203be..f787452614f2d20dddfcf4f643f20178b9e985f7 100644 --- a/frontend/src/metabase/visualizations/lib/apply_tooltips.js +++ b/frontend/src/metabase/visualizations/lib/apply_tooltips.js @@ -11,7 +11,16 @@ import { getFriendlyName } from "./utils"; export function getClickHoverObject( d, - { series, isNormalized, seriesIndex, seriesTitle, classList, event, element }, + { + series, + datas, + isNormalized, + seriesIndex, + seriesTitle, + classList, + event, + element, + }, ) { let { cols } = series[0].data; const { card } = series[seriesIndex]; @@ -74,18 +83,8 @@ export function getClickHoverObject( // We look through the rows to match up they key in d.data to the x value // from some row. - const row = seriesData.rows.find(([x]) => - moment.isMoment(key) - ? // for dates, we check two things: - // 1. does parsing x produce an equivalent moment value? - key.isSame(moment(x)) || - // 2. if not, we format the key using the column info - // this catches values like years that don't parse correctly above - formatValue(key, { column: rawCols[0] }) === String(x) - : // otherwise, we just check if the string value matches - // we also format null so it matches a key displayed as "(empty)" - // e.g. String("123") === String(123) - String(formatNull(x)) === String(key), + const row = datas[seriesIndex].find( + ([x]) => key === x || (moment.isMoment(key) && key.isSame(x)), ); // try to get row from _origin but fall back to the row we already have @@ -216,6 +215,7 @@ export function setupTooltips( seriesTitle, seriesIndex, series, + datas, isNormalized: normalized, isScalarSeries, isStacked: stacked, diff --git a/frontend/test/metabase/visualizations/lib/apply_tooltips.unit.spec.js b/frontend/test/metabase/visualizations/lib/apply_tooltips.unit.spec.js index 13f0ecae960121970e78371306d0ceb26db03975..b7629db05e522032ffa24542adb9739611cebc67 100644 --- a/frontend/test/metabase/visualizations/lib/apply_tooltips.unit.spec.js +++ b/frontend/test/metabase/visualizations/lib/apply_tooltips.unit.spec.js @@ -1,6 +1,7 @@ import moment from "moment"; import { getClickHoverObject } from "metabase/visualizations/lib/apply_tooltips"; +import { getDatas } from "metabase/visualizations/lib/renderer_utils"; import { getFormattedTooltips, @@ -16,7 +17,7 @@ describe("getClickHoverObject", () => { const cols = [StringColumn(), NumberColumn()]; const rows = [["foobar", 123]]; const otherArgs = { - series: [{ data: { cols, rows }, card: {} }], + ...seriesAndData({ cols, rows }), seriesIndex: 0, classList: [], event: {}, @@ -41,7 +42,28 @@ describe("getClickHoverObject", () => { ["2016-05-01T00:00:00.000Z", 3], ]; const otherArgs = { - series: [{ data: { cols, rows }, card: {} }], + ...seriesAndData({ cols, rows }), + seriesIndex: 0, + classList: [], + event: {}, + }; + + const obj = getClickHoverObject(d, otherArgs); + + expect(getFormattedTooltips(obj)).toEqual(["April, 2016", "2"]); + }); + + it("should show the correct tooltip for months", () => { + const d = { + data: { + key: moment("2016-04-01T00:00:00.000Z", "YYYY-MM-DDTHH:mm:ss.SSSSZ"), + value: 123, + }, + }; + const cols = [DateTimeColumn({ unit: "month" }), NumberColumn()]; + const rows = [["2016-03", 1], ["2016-04", 2], ["2016-05", 3]]; + const otherArgs = { + ...seriesAndData({ cols, rows }), seriesIndex: 0, classList: [], event: {}, @@ -60,7 +82,7 @@ describe("getClickHoverObject", () => { const cols = [StringColumn(), NumberColumn()]; const rows = [["foobar", 123]]; const otherArgs = { - series: [{ data: { cols, rows }, card: {} }], + ...seriesAndData({ cols, rows }), seriesIndex: 0, element: "DOM element", }; @@ -97,7 +119,7 @@ describe("getClickHoverObject", () => { ]; const rows = [["foobar", 123, "barfoo"]]; const otherArgs = { - series: [{ data: { cols, rows }, card: {} }], + ...seriesAndData({ cols, rows }), seriesIndex: 0, classList: [], event: {}, @@ -114,7 +136,7 @@ describe("getClickHoverObject", () => { const cols = [StringColumn(), BooleanColumn()]; const rows = [["foobar", "true"]]; const otherArgs = { - series: [{ data: { cols, rows }, card: {} }], + ...seriesAndData({ cols, rows }), seriesIndex: 0, classList: [], event: {}, @@ -129,4 +151,25 @@ describe("getClickHoverObject", () => { expect(dimValue).toBe(true); expect(dValue).toBe(true); }); + + it("should show correct tooltip for nulls", () => { + const d = { data: { key: "(empty)", value: "true" } }; + const cols = [StringColumn(), NumberColumn()]; + const rows = [["foobar", 1], [null, 2], ["barfoo", 3]]; + const otherArgs = { + ...seriesAndData({ cols, rows }), + seriesIndex: 0, + classList: [], + event: {}, + }; + + const obj = getClickHoverObject(d, otherArgs); + expect(getFormattedTooltips(obj)).toEqual(["(empty)", "2"]); + }); }); + +function seriesAndData({ cols, rows }) { + const series = [{ data: { cols, rows }, card: {} }]; + const datas = getDatas({ series, settings: {} }); + return { series, datas }; +}