Skip to content

Commit

Permalink
[FIX] ChartJs: Properly destroy chartJs object on component wrapper d…
Browse files Browse the repository at this point in the history
…eletion

How to reproduce:

-Make a chartjs chart (line/bar/pie)
-Mousedown on a datapoint/bar/part of the pie
-move your mouse
- mouseup (lift your finger) while still moving your mouse
-> crash

We were not properly destroying the chart js item and their linker
eventListeners persisted. Specifically, the eventHandler of the tooltip
plugin would still try to handle the mousemove event while its internal
state was partially invalidated.

Task: 3777754
  • Loading branch information
rrahir committed Apr 25, 2024
1 parent 47bb1a9 commit 5a6a703
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/components/figures/chart/chartJs/chartjs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, onMounted, useEffect, useRef } from "@odoo/owl";
import { Component, onMounted, onWillUnmount, useEffect, useRef } from "@odoo/owl";
import type { Chart, ChartConfiguration } from "chart.js";
import { Figure, SpreadsheetChildEnv } from "../../../../types";
import { ChartJSRuntime } from "../../../../types/chart/chart";
Expand Down Expand Up @@ -38,6 +38,7 @@ export class ChartJsComponent extends Component<Props, SpreadsheetChildEnv> {
const runtime = this.chartRuntime;
this.createChart(runtime.chartJsConfig);
});
onWillUnmount(() => this.chart?.destroy());
useEffect(
() => this.updateChartJs(this.chartRuntime),
() => [this.chartRuntime]
Expand Down
12 changes: 12 additions & 0 deletions tests/figures/chart/charts_component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1215,3 +1215,15 @@ describe("Default background on runtime tests", () => {
expect(model.getters.getChartRuntime("1").background).toBe("#FA0000");
});
});

test("ChartJS charts are correctly destroyed on chart deletion", async () => {
({ parent, fixture, model } = await mountSpreadsheet({ model: new Model() }));
createChart(model, { dataSets: ["A1"], type: "bar" }, "1");
await nextTick();
//@ts-ignore
const spyDelete = jest.spyOn((window as any).Chart.prototype, "destroy");
model.dispatch("DELETE_FIGURE", { id: "1", sheetId: model.getters.getActiveSheetId() });
await nextTick();
await nextTick();
expect(spyDelete).toHaveBeenCalled();
});
2 changes: 1 addition & 1 deletion tests/test_helpers/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ export const mockChart = () => {
return mockChartData.data;
}
toBase64Image = () => "";
destroy = () => {};
destroy() {}
update = () => {};
options = mockChartData.options;
config = mockChartData;
Expand Down

0 comments on commit 5a6a703

Please sign in to comment.