From 9eae62caa5c9fbcc19eddf546546c08cf520a2e1 Mon Sep 17 00:00:00 2001 From: "Adrien Minne (adrm)" Date: Fri, 20 Sep 2024 11:46:56 +0200 Subject: [PATCH] [IMP] charts: show single grid line for y-axis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a chart had 2 vertical axis (left & right), we showed grid lines for both, which made the cahrt messy. Now we show only the grid lines for the left axis (or the right axis if there is no left axis). Task: 4153935 Part-of: odoo/o-spreadsheet#5013 Signed-off-by: RĂ©mi Rahir (rar) --- src/helpers/figures/charts/bar_chart.ts | 56 +++++------------ src/helpers/figures/charts/chart_common.ts | 51 ++++++++++++++- .../charts/chart_common_line_scatter.ts | 55 +++------------- src/helpers/figures/charts/combo_chart.ts | 48 +++----------- .../__snapshots__/chart_plugin.test.ts.snap | 63 +++++++++++++++++++ tests/figures/chart/bar_chart_plugin.test.ts | 4 +- tests/figures/chart/chart_plugin.test.ts | 26 +++++--- tests/figures/chart/line_chart_plugin.test.ts | 8 +-- 8 files changed, 169 insertions(+), 142 deletions(-) diff --git a/src/helpers/figures/charts/bar_chart.ts b/src/helpers/figures/charts/bar_chart.ts index edcdb0d029..38a8fa0016 100644 --- a/src/helpers/figures/charts/bar_chart.ts +++ b/src/helpers/figures/charts/bar_chart.ts @@ -26,6 +26,7 @@ import { LegendPosition } from "../../../types/chart/common_chart"; import { CellErrorType } from "../../../types/errors"; import { Validator } from "../../../types/validator"; import { toXlsxHexColor } from "../../../xlsx/helpers/colors"; +import { removeFalsyAttributes } from "../../misc"; import { createValidRange } from "../../range"; import { AbstractChart } from "./abstract_chart"; import { @@ -38,7 +39,7 @@ import { copyLabelRangeWithNewSheetId, createDataSets, formatTickValue, - getChartAxisTitleRuntime, + getChartAxis, getChartColorsGenerator, getDefinedAxis, getTrendDatasetForBarChart, @@ -268,46 +269,20 @@ export function createBarChartRuntime(chart: BarChart, getters: Getters): BarCha config.options.indexAxis = chart.horizontal ? "y" : "x"; config.options.scales = {}; - const labelsAxis = { ticks: { padding: 5, color: fontColor } }; - const valuesAxis = { - beginAtZero: true, // the origin of the y axis is always zero - ticks: { - color: fontColor, - callback: formatTickValue(localeFormat), - }, - }; - - const xAxis = chart.horizontal ? valuesAxis : labelsAxis; - const yAxis = chart.horizontal ? labelsAxis : valuesAxis; - const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition()); + const definition = chart.getDefinition(); + const stacked = chart.stacked; - config.options.scales.x = { ...xAxis, title: getChartAxisTitleRuntime(chart.axesDesign?.x) }; - if (useLeftAxis) { - config.options.scales.y = { - ...yAxis, - position: "left", - title: getChartAxisTitleRuntime(chart.axesDesign?.y), - }; - } - if (useRightAxis) { - config.options.scales.y1 = { - ...yAxis, - position: "right", - title: getChartAxisTitleRuntime(chart.axesDesign?.y1), - }; - } - if (chart.stacked) { - // @ts-ignore chart.js type is broken - config.options.scales!.x!.stacked = true; - if (useLeftAxis) { - // @ts-ignore chart.js type is broken - config.options.scales!.y!.stacked = true; - } - if (useRightAxis) { - // @ts-ignore chart.js type is broken - config.options.scales!.y1!.stacked = true; - } + const valueAxisOptions = { ...localeFormat, stacked }; + const labelAxisOptions = { stacked, locale }; + if (chart.horizontal) { + config.options.scales.x = getChartAxis(definition, "bottom", "values", valueAxisOptions); + config.options.scales.y = getChartAxis(definition, "left", "labels", labelAxisOptions); + } else { + config.options.scales.x = getChartAxis(definition, "bottom", "labels", labelAxisOptions); + config.options.scales.y = getChartAxis(definition, "left", "values", valueAxisOptions); + config.options.scales.y1 = getChartAxis(definition, "right", "values", valueAxisOptions); } + config.options.scales = removeFalsyAttributes(config.options.scales); config.options.plugins!.chartShowValuesPlugin = { showValues: chart.showValues, @@ -316,7 +291,6 @@ export function createBarChartRuntime(chart: BarChart, getters: Getters): BarCha callback: formatTickValue(localeFormat), }; - const definition = chart.getDefinition(); const colors = getChartColorsGenerator(definition, dataSetsValues.length); const trendDatasets: any[] = []; for (const index in dataSetsValues) { @@ -355,7 +329,7 @@ export function createBarChartRuntime(chart: BarChart, getters: Getters): BarCha */ const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset.data.length)); config.options.scales[TREND_LINE_XAXIS_ID] = { - ...xAxis, + ...(config.options.scales!.x as any), labels: Array(maxLength).fill(""), offset: false, display: false, diff --git a/src/helpers/figures/charts/chart_common.ts b/src/helpers/figures/charts/chart_common.ts index b49d507107..036ae5bb8d 100644 --- a/src/helpers/figures/charts/chart_common.ts +++ b/src/helpers/figures/charts/chart_common.ts @@ -1,4 +1,5 @@ -import { ChartDataset } from "chart.js"; +import { ChartDataset, LinearScaleOptions } from "chart.js"; +import { DeepPartial } from "chart.js/dist/types/utils"; import { transformZone } from "../../../collaborative/ot/ot_helpers"; import { LINE_FILL_TRANSPARENCY } from "../../../constants"; import { @@ -450,6 +451,54 @@ export function getDefinedAxis(definition: ChartWithAxisDefinition): { return { useLeftAxis, useRightAxis }; } +export function getChartAxis( + definition: ChartWithAxisDefinition, + position: "left" | "right" | "bottom", + type: "values" | "labels", + options: LocaleFormat & { stacked?: boolean } +): DeepPartial | undefined { + const { useLeftAxis, useRightAxis } = getDefinedAxis(definition); + if ((position === "left" && !useLeftAxis) || (position === "right" && !useRightAxis)) { + return undefined; + } + + const fontColor = chartFontColor(definition.background); + let design: AxisDesign | undefined; + if (position === "bottom") { + design = definition.axesDesign?.x; + } else if (position === "left") { + design = definition.axesDesign?.y; + } else { + design = definition.axesDesign?.y1; + } + + if (type === "values") { + const displayGridLines = position === "left" || (position === "right" && !useLeftAxis); + return { + position: position, + title: getChartAxisTitleRuntime(design), + grid: { + display: displayGridLines, + }, + beginAtZero: true, + stacked: options?.stacked, + ticks: { + color: fontColor, + callback: formatTickValue(options), + }, + }; + } else { + return { + ticks: { + padding: 5, + color: fontColor, + }, + stacked: options?.stacked, + title: getChartAxisTitleRuntime(design), + }; + } +} + export function computeChartPadding({ displayTitle, displayLegend, diff --git a/src/helpers/figures/charts/chart_common_line_scatter.ts b/src/helpers/figures/charts/chart_common_line_scatter.ts index 2feb15de64..8837a5a3c4 100644 --- a/src/helpers/figures/charts/chart_common_line_scatter.ts +++ b/src/helpers/figures/charts/chart_common_line_scatter.ts @@ -12,16 +12,15 @@ import { import { getChartTimeOptions, timeFormatLuxonCompatible } from "../../chart_date"; import { colorToRGBA, rgbaToHex } from "../../color"; import { formatValue } from "../../format/format"; -import { deepCopy, findNextDefinedValue, range } from "../../misc"; +import { deepCopy, findNextDefinedValue, range, removeFalsyAttributes } from "../../misc"; import { isNumber } from "../../numbers"; import { TREND_LINE_XAXIS_ID, chartFontColor, computeChartPadding, formatTickValue, - getChartAxisTitleRuntime, + getChartAxis, getChartColorsGenerator, - getDefinedAxis, getFullTrendingLineDataSet, interpolateData, } from "./chart_common"; @@ -256,50 +255,15 @@ export function createLineOrScatterChartRuntime( }), }; - const xAxis = { - ticks: { - padding: 5, - color: fontColor, - }, - title: getChartAxisTitleRuntime(chart.axesDesign?.x), - }; - + const definition = chart.getDefinition(); + const stacked = "stacked" in chart && chart.stacked; config.options.scales = { - x: xAxis, + x: getChartAxis(definition, "bottom", "labels", { locale }), + y: getChartAxis(definition, "left", "values", { ...options, stacked }), + y1: getChartAxis(definition, "right", "values", { ...options, stacked }), }; + config.options.scales = removeFalsyAttributes(config.options.scales); - const yAxis = { - beginAtZero: true, // the origin of the y axis is always zero - ticks: { - color: fontColor, - callback: formatTickValue(options), - }, - }; - const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition()); - if (useLeftAxis) { - config.options.scales.y = { - ...yAxis, - position: "left", - title: getChartAxisTitleRuntime(chart.axesDesign?.y), - }; - } - if (useRightAxis) { - config.options.scales.y1 = { - ...yAxis, - position: "right", - title: getChartAxisTitleRuntime(chart.axesDesign?.y1), - }; - } - if ("stacked" in chart && chart.stacked) { - if (useLeftAxis) { - // @ts-ignore chart.js type is broken - config.options.scales!.y!.stacked = true; - } - if (useRightAxis) { - // @ts-ignore chart.js type is broken - config.options.scales!.y1!.stacked = true; - } - } config.options.plugins!.chartShowValuesPlugin = { showValues: chart.showValues, background: chart.background, @@ -346,7 +310,6 @@ export function createLineOrScatterChartRuntime( const stackedChart = "stacked" in chart ? chart.stacked : false; const cumulative = "cumulative" in chart ? chart.cumulative : false; - const definition = chart.getDefinition(); const colors = getChartColorsGenerator(definition, dataSetsValues.length); for (let [index, { label, data }] of dataSetsValues.entries()) { const color = colors.next(); @@ -412,7 +375,7 @@ export function createLineOrScatterChartRuntime( * set so that the second axis points match the classical x axis */ config.options.scales[TREND_LINE_XAXIS_ID] = { - ...xAxis, + ...(config.options.scales.x as any), type: "category", labels: range(0, maxLength).map((x) => x.toString()), offset: false, diff --git a/src/helpers/figures/charts/combo_chart.ts b/src/helpers/figures/charts/combo_chart.ts index 2034bb6c40..2928a6b377 100644 --- a/src/helpers/figures/charts/combo_chart.ts +++ b/src/helpers/figures/charts/combo_chart.ts @@ -29,6 +29,7 @@ import { import { CellErrorType } from "../../../types/errors"; import { Validator } from "../../../types/validator"; import { toXlsxHexColor } from "../../../xlsx/helpers/colors"; +import { removeFalsyAttributes } from "../../misc"; import { createValidRange } from "../../range"; import { AbstractChart } from "./abstract_chart"; import { @@ -41,7 +42,7 @@ import { copyLabelRangeWithNewSheetId, createDataSets, formatTickValue, - getChartAxisTitleRuntime, + getChartAxis, getChartColorsGenerator, getDefinedAxis, getTrendDatasetForBarChart, @@ -271,49 +272,14 @@ export function createComboChartRuntime(chart: ComboChart, getters: Getters): Co }), }; + const definition = chart.getDefinition(); config.options.scales = { - x: { - ticks: { - padding: 5, - color: fontColor, - }, - title: getChartAxisTitleRuntime(chart.axesDesign?.x), - }, + x: getChartAxis(definition, "bottom", "labels", { locale }), + y: getChartAxis(definition, "left", "values", { locale, format: mainDataSetFormat }), + y1: getChartAxis(definition, "right", "values", { locale, format: lineDataSetsFormat }), }; + config.options.scales = removeFalsyAttributes(config.options.scales); - const leftVerticalAxis = { - beginAtZero: true, // the origin of the y axis is always zero - ticks: { - color: fontColor, - callback: formatTickValue({ format: mainDataSetFormat, locale }), - }, - }; - const rightVerticalAxis = { - beginAtZero: true, // the origin of the y axis is always zero - ticks: { - color: fontColor, - callback: formatTickValue({ format: lineDataSetsFormat, locale }), - }, - }; - const definition = chart.getDefinition(); - const { useLeftAxis, useRightAxis } = getDefinedAxis(definition); - if (useLeftAxis) { - config.options.scales.y = { - ...leftVerticalAxis, - position: "left", - title: getChartAxisTitleRuntime(chart.axesDesign?.y), - }; - } - if (useRightAxis) { - config.options.scales.y1 = { - ...rightVerticalAxis, - position: "right", - grid: { - display: false, - }, - title: getChartAxisTitleRuntime(chart.axesDesign?.y1), - }; - } config.options.plugins!.chartShowValuesPlugin = { showValues: chart.showValues, background: chart.background, diff --git a/tests/figures/chart/__snapshots__/chart_plugin.test.ts.snap b/tests/figures/chart/__snapshots__/chart_plugin.test.ts.snap index 1c8cbd38dd..beef8c2246 100644 --- a/tests/figures/chart/__snapshots__/chart_plugin.test.ts.snap +++ b/tests/figures/chart/__snapshots__/chart_plugin.test.ts.snap @@ -89,6 +89,7 @@ exports[`Linear/Time charts font color is white with a dark background color 1`] "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "callback": [Function], "color": "#FFFFFF", @@ -99,7 +100,11 @@ exports[`Linear/Time charts font color is white with a dark background color 1`] }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#FFFFFF", @@ -233,6 +238,7 @@ exports[`Linear/Time charts snapshot test of chartJS configuration for date char "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "maxTicksLimit": 15, @@ -250,7 +256,11 @@ exports[`Linear/Time charts snapshot test of chartJS configuration for date char }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -387,6 +397,7 @@ exports[`Linear/Time charts snapshot test of chartJS configuration for linear ch "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "callback": [Function], "color": "#000000", @@ -397,7 +408,11 @@ exports[`Linear/Time charts snapshot test of chartJS configuration for linear ch }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -523,6 +538,9 @@ exports[`datasource tests create a chart with stacked bar 1`] = ` }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", "stacked": true, "ticks": { @@ -615,6 +633,7 @@ exports[`datasource tests create chart with a dataset of one cell (no title) 1`] "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -623,7 +642,11 @@ exports[`datasource tests create chart with a dataset of one cell (no title) 1`] }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -749,6 +772,7 @@ exports[`datasource tests create chart with column datasets 1`] = ` "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -757,7 +781,11 @@ exports[`datasource tests create chart with column datasets 1`] = ` }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -897,6 +925,7 @@ exports[`datasource tests create chart with column datasets with category title "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -905,7 +934,11 @@ exports[`datasource tests create chart with column datasets with category title }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1046,6 +1079,7 @@ exports[`datasource tests create chart with column datasets without series title "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1054,7 +1088,11 @@ exports[`datasource tests create chart with column datasets without series title }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1167,6 +1205,7 @@ exports[`datasource tests create chart with only the dataset title (no data) 1`] "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1175,7 +1214,11 @@ exports[`datasource tests create chart with only the dataset title (no data) 1`] }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1298,6 +1341,7 @@ exports[`datasource tests create chart with rectangle dataset 1`] = ` "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1306,7 +1350,11 @@ exports[`datasource tests create chart with rectangle dataset 1`] = ` }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1446,6 +1494,7 @@ exports[`datasource tests create chart with row datasets 1`] = ` "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1454,7 +1503,11 @@ exports[`datasource tests create chart with row datasets 1`] = ` }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1594,6 +1647,7 @@ exports[`datasource tests create chart with row datasets with category title 1`] "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1602,7 +1656,11 @@ exports[`datasource tests create chart with row datasets with category title 1`] }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", @@ -1743,6 +1801,7 @@ exports[`datasource tests create chart with row datasets without series title 1` "responsive": true, "scales": { "x": { + "stacked": undefined, "ticks": { "color": "#000000", "padding": 5, @@ -1751,7 +1810,11 @@ exports[`datasource tests create chart with row datasets without series title 1` }, "y": { "beginAtZero": true, + "grid": { + "display": true, + }, "position": "left", + "stacked": false, "ticks": { "callback": [Function], "color": "#000000", diff --git a/tests/figures/chart/bar_chart_plugin.test.ts b/tests/figures/chart/bar_chart_plugin.test.ts index 158db7bbb9..33f66257ed 100644 --- a/tests/figures/chart/bar_chart_plugin.test.ts +++ b/tests/figures/chart/bar_chart_plugin.test.ts @@ -49,8 +49,8 @@ describe("bar chart", () => { test("Stacked bar", () => { const model = new Model(); createChart(model, { type: "bar", stacked: false }, "chartId"); - expect(isChartAxisStacked(model, "chartId", "x")).toBeUndefined(); - expect(isChartAxisStacked(model, "chartId", "y")).toBeUndefined(); + expect(isChartAxisStacked(model, "chartId", "x")).toBeFalsy(); + expect(isChartAxisStacked(model, "chartId", "y")).toBeFalsy(); updateChart(model, "chartId", { stacked: true }); expect(isChartAxisStacked(model, "chartId", "x")).toBe(true); diff --git a/tests/figures/chart/chart_plugin.test.ts b/tests/figures/chart/chart_plugin.test.ts index 1917013576..840d207147 100644 --- a/tests/figures/chart/chart_plugin.test.ts +++ b/tests/figures/chart/chart_plugin.test.ts @@ -2117,7 +2117,7 @@ describe("Chart design configuration", () => { }); test.each(["line", "scatter", "bar", "combo"] as const)( - "%s chart correctly use right axis if set up in definition", + "%s chart correctly use right axis if set up in definition, and the grid lines are only displayed once", (chartType) => { setCellContent(model, "A1", "1"); setCellContent(model, "A2", "2"); @@ -2139,8 +2139,14 @@ describe("Chart design configuration", () => { let config = getChartConfiguration(model, "43"); expect(config.data?.datasets![0]["yAxisID"]).toEqual("y"); expect(config.data?.datasets![1]["yAxisID"]).toEqual("y1"); - expect(config.options?.scales?.y).toMatchObject({ position: "left" }); - expect(config.options?.scales?.y1).toMatchObject({ position: "right" }); + expect(config.options?.scales?.y).toMatchObject({ + position: "left", + grid: { display: true }, + }); + expect(config.options?.scales?.y1).toMatchObject({ + position: "right", + grid: { display: false }, + }); updateChart(model, "43", { dataSets: [ { dataRange: "A1:A2", yAxisId: "y1" }, @@ -2150,8 +2156,11 @@ describe("Chart design configuration", () => { config = getChartConfiguration(model, "43"); expect(config.data?.datasets![0]["yAxisID"]).toEqual("y1"); expect(config.data?.datasets![1]["yAxisID"]).toEqual("y1"); - expect(config.options?.scales?.y).not.toBeDefined(); - expect(config.options?.scales?.y1).toMatchObject({ position: "right" }); + expect(config.options?.scales?.y).toBeUndefined(); + expect(config.options?.scales?.y1).toMatchObject({ + position: "right", + grid: { display: true }, + }); updateChart(model, "43", { dataSets: [ { dataRange: "A1:A2", yAxisId: "y" }, @@ -2161,8 +2170,11 @@ describe("Chart design configuration", () => { config = getChartConfiguration(model, "43"); expect(config.data?.datasets![0]["yAxisID"]).toEqual("y"); expect(config.data?.datasets![1]["yAxisID"]).toEqual("y"); - expect(config.options?.scales?.y1).not.toBeDefined(); - expect(config.options?.scales?.y).toMatchObject({ position: "left" }); + expect(config.options?.scales?.y1).toBeUndefined(); + expect(config.options?.scales?.y).toMatchObject({ + position: "left", + grid: { display: true }, + }); } ); diff --git a/tests/figures/chart/line_chart_plugin.test.ts b/tests/figures/chart/line_chart_plugin.test.ts index 5c72ec20f8..2bf1a7b546 100644 --- a/tests/figures/chart/line_chart_plugin.test.ts +++ b/tests/figures/chart/line_chart_plugin.test.ts @@ -60,8 +60,8 @@ describe("line chart", () => { ], }); createChart(model, { type: "line", dataSets: [{ dataRange: "Sheet1!B1:B4" }] }, "chartId"); - expect(isChartAxisStacked(model, "chartId", "x")).toBeUndefined(); - expect(isChartAxisStacked(model, "chartId", "y")).toBeUndefined(); + expect(isChartAxisStacked(model, "chartId", "x")).toBeFalsy(); + expect(isChartAxisStacked(model, "chartId", "y")).toBeFalsy(); updateChart(model, "chartId", { stacked: true }); const runtime = model.getters.getChartRuntime("chartId") as any; @@ -105,8 +105,8 @@ describe("line chart", () => { expect(runtime.chartJsConfig.data.datasets[0].backgroundColor).toBe("#4EA7F266"); expect(runtime.chartJsConfig.data.datasets[1].fill).toBe("origin"); expect(runtime.chartJsConfig.data.datasets[1].backgroundColor).toBe("#EA617566"); - expect(isChartAxisStacked(model, "chartId", "x")).toBeUndefined(); - expect(isChartAxisStacked(model, "chartId", "y")).toBeUndefined(); + expect(isChartAxisStacked(model, "chartId", "x")).toBeFalsy(); + expect(isChartAxisStacked(model, "chartId", "y")).toBeFalsy(); }); test("Stacked area chart", () => {