Files
enterprise-addons/documents_spreadsheet/static/tests/chart/chart_side_panel.test.js
T

756 lines
32 KiB
JavaScript

import {
createSpreadsheetFromGraphView,
openChartSidePanel,
} from "@documents_spreadsheet/../tests/helpers/chart_helpers";
import { defineDocumentSpreadsheetModels } from "@documents_spreadsheet/../tests/helpers/data";
import { createSpreadsheet } from "@documents_spreadsheet/../tests/helpers/spreadsheet_test_utils";
import { describe, expect, getFixture, test } from "@odoo/hoot";
import { animationFrame } from "@odoo/hoot-mock";
import { registries } from "@odoo/o-spreadsheet";
import { addGlobalFilter, createBasicChart } from "@spreadsheet/../tests/helpers/commands";
import * as dsHelpers from "@web/../tests/core/tree_editor/condition_tree_editor_test_helpers";
import { contains, makeServerError, onRpc, fields } from "@web/../tests/web_test_helpers";
import { Partner } from "@spreadsheet/../tests/helpers/data";
defineDocumentSpreadsheetModels();
describe.current.tags("desktop");
const { chartSubtypeRegistry } = registries;
async function changeChartType(type) {
await contains(".o-type-selector").click();
await contains(`.o-chart-type-item[data-id="${type}"]`).click();
}
test("Open a chart panel", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
await openChartSidePanel(model, env);
expect(".o-sidePanel .o-sidePanelBody .o-chart").toHaveCount(1);
});
test("From an Odoo chart, can only change to an Odoo chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
await openChartSidePanel(model, env);
const target = getFixture();
await contains(".o-type-selector").click();
const odooChartTypes = chartSubtypeRegistry
.getKeys()
.filter((key) => key.startsWith("odoo_") && key !== "odoo_geo")
.sort();
/** @type {NodeListOf<HTMLDivElement>} */
const options = target.querySelectorAll(".o-chart-type-item");
const optionValues = Array.from(options)
.map((option) => option.dataset.id)
.sort();
expect(optionValues).toEqual(odooChartTypes);
});
test("From a spreadsheet chart, can only change to a spreadsheet chart", async () => {
const { model, env } = await createSpreadsheet();
createBasicChart(model, "1");
await openChartSidePanel(model, env);
const target = getFixture();
await contains(".o-type-selector").click();
/** @type {NodeListOf<HTMLDivElement>} */
const options = target.querySelectorAll(".o-chart-type-item");
const optionValues = Array.from(options)
.map((option) => option.dataset.id)
.sort();
const nonOdooChartTypes = chartSubtypeRegistry
.getKeys()
.filter((key) => !key.startsWith("odoo_"))
.sort();
expect(optionValues).toEqual(nonOdooChartTypes);
});
test("Possible chart types are correct when switching from a spreadsheet to an odoo chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
createBasicChart(model, "nonOdooChartId", {}, undefined, "figureId");
await openChartSidePanel(model, env);
const target = getFixture();
await contains(".o-type-selector").click();
/** @type {NodeListOf<HTMLDivElement>} */
let options = target.querySelectorAll(".o-chart-type-item");
let optionValues = Array.from(options).map((option) => option.dataset.id);
expect(optionValues.every((value) => value.startsWith("odoo_"))).toBe(true);
model.dispatch("SELECT_FIGURE", { figureId: "figureId" });
await animationFrame();
await contains(".o-type-selector").click();
options = target.querySelectorAll(".o-chart-type-item");
optionValues = Array.from(options).map((option) => option.dataset.id);
expect(optionValues.every((value) => !value.startsWith("odoo_"))).toBe(true);
});
test("Change odoo chart type", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
expect(model.getters.getChart(chartId).type).toBe("odoo_bar");
await openChartSidePanel(model, env);
/** @type {HTMLSelectElement} */
await changeChartType("odoo_pie");
expect(model.getters.getChart(chartId).type).toBe("odoo_pie");
await changeChartType("odoo_line");
expect(model.getters.getChart(chartId).verticalAxisPosition).toBe("left");
expect(model.getters.getChart(chartId).stacked).toBe(false);
await changeChartType("odoo_bar");
expect(model.getters.getChart(chartId).type).toBe("odoo_bar");
expect(model.getters.getChart(chartId).stacked).toBe(false);
await changeChartType("odoo_stacked_bar");
expect(model.getters.getChart(chartId).type).toBe("odoo_bar");
expect(model.getters.getChart(chartId).stacked).toBe(true);
await changeChartType("odoo_stacked_line");
expect(model.getters.getChart(chartId).type).toBe("odoo_line");
expect(model.getters.getChart(chartId).stacked).toBe(true);
});
test("data markers are displayed by default for line, combo and radar charts", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
expect(model.getters.getChart(chartId).type).toBe("odoo_bar");
await openChartSidePanel(model, env);
await changeChartType("odoo_line");
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(undefined);
await changeChartType("odoo_combo");
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(undefined);
await changeChartType("odoo_radar");
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(undefined);
});
for (const type of ["odoo_line", "odoo_combo", "odoo_radar"]) {
test(`can toggle data markers for ${type}`, async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType(type);
await contains(".o-panel-design").click();
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(undefined);
await contains(".o-checkbox input[name='showDataMarkers']:checked").click();
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(true);
await contains(".o-checkbox input[name='showDataMarkers']").click();
expect(model.getters.getChartDefinition(chartId).hideDataMarkers).toBe(false);
});
}
test("stacked line chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_stacked_line");
// checked by default
expect(model.getters.getChart(chartId).stacked).toBe(true);
expect(".o-checkbox input[name='stackedBar']:checked").toHaveCount(1, {
message: "checkbox should be checked",
});
// uncheck
await contains(".o-checkbox input:checked").click();
expect(model.getters.getChart(chartId).stacked).toBe(false);
expect(".o-checkbox input[name='stackedBar']:checked").toHaveCount(0, {
message: "checkbox should no longer be checked",
});
// check
await contains(".o-checkbox input[name='stackedBar']").click();
expect(model.getters.getChart(chartId).stacked).toBe(true);
expect(".o-checkbox input[name='stackedBar']:checked").toHaveCount(1, {
message: "checkbox should be checked",
});
});
test("Odoo line chart with cumulated start", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_line");
expect(model.getters.getChartDefinition(chartId).cumulative).toBe(undefined);
expect(model.getters.getChartDefinition(chartId).cumulatedStart).toBe(undefined);
expect(".o-checkbox input[name='cumulatedStart']").toHaveCount(0, {
message: "cumulated Start is not visible",
});
// uncheck
await contains(".o-checkbox input[name='cumulative']").click();
expect(model.getters.getChart(chartId).cumulative).toBe(true);
expect(model.getters.getChart(chartId).cumulatedStart).toBe(undefined);
expect(".o-checkbox input[name='cumulatedStart']").toHaveCount(1, {
message: "cumulated Start is visible",
});
expect(".o-checkbox input[name='cumulatedStart']:checked").toHaveCount(0, {
message: "cumulated Start not checked",
});
// check
await contains(".o-checkbox input[name='cumulatedStart']").click();
expect(model.getters.getChart(chartId).cumulative).toBe(true);
expect(model.getters.getChart(chartId).cumulatedStart).toBe(true);
expect(".o-checkbox input[name='cumulatedStart']:checked").toHaveCount(1, {
message: "cumulated Start is visible and checked",
});
});
test("Odoo area chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_area");
let chartDefinition = model.getters.getChartDefinition(chartId);
expect(chartDefinition.type).toBe("odoo_line");
expect(chartDefinition.fillArea).toBe(true);
expect(chartDefinition.stacked).toBe(false);
await changeChartType("odoo_stacked_area");
chartDefinition = model.getters.getChartDefinition(chartId);
expect(chartDefinition.type).toBe("odoo_line");
expect(chartDefinition.fillArea).toBe(true);
expect(chartDefinition.stacked).toBe(true);
});
test("Change the title of a chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
expect(model.getters.getChart(chartId).type).toBe("odoo_bar");
await openChartSidePanel(model, env);
const target = getFixture();
await contains(".o-panel-design").click();
/** @type {HTMLInputElement} */
const input = target.querySelector(".o-chart-title input");
expect(model.getters.getChart(chartId).title.text).toBe("PartnerGraph");
await contains(input).edit("bla");
expect(model.getters.getChart(chartId).title.text).toBe("bla");
});
test("Open chart odoo's data properties", async function () {
const target = getFixture();
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const figureId = model.getters.getFigures(sheetId)[0].id;
// opening from a chart
model.dispatch("SELECT_FIGURE", { figureId });
env.openSidePanel("ChartPanel");
await animationFrame();
const sections = target.querySelectorAll(".o-panel-content > div:not(.d-none) .o-section");
expect(sections.length).toBe(6, { message: "it should have 6 sections" });
const [, , pivotModel, domain, , measures] = sections;
expect(pivotModel.children[0]).toHaveText("Model");
expect(pivotModel.children[1]).toHaveText("Partner (partner)");
expect(domain.children[0]).toHaveText("Domain");
expect(domain.children[1]).toHaveText("Match all records\nInclude archived");
expect(measures.children[0].innerText.startsWith("Last updated at")).toBe(true);
});
test("Update the chart domain from the side panel", async function () {
onRpc("/web/domain/validate", () => true);
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
const figureId = model.getters.getFigures(sheetId)[0].id;
model.dispatch("SELECT_FIGURE", { figureId });
env.openSidePanel("ChartPanel");
await animationFrame();
const fixture = getFixture();
await contains(".o_edit_domain").click();
await dsHelpers.addNewRule();
await contains(".modal-footer .btn-primary").click();
expect(model.getters.getChartDefinition(chartId).searchParams.domain).toEqual([["id", "=", 1]]);
expect(dsHelpers.getConditionText(fixture)).toBe("Id = 1");
});
test("Cumulative line chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_line");
await contains(".o-checkbox input[name='cumulative']").click();
// check
expect(model.getters.getChart(chartId).cumulative).toBe(true);
expect(".o-checkbox input[name='cumulative']:checked").toHaveCount(1, {
message: "checkbox should be checked",
});
// uncheck
await contains(".o-checkbox input[name='cumulative']").click();
expect(model.getters.getChart(chartId).cumulative).toBe(false);
expect(".o-checkbox input[name='cumulative']:checked").toHaveCount(0, {
message: "checkbox should no longer be checked",
});
});
test("radar chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_radar");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_radar");
expect(model.getters.getChartRuntime(chartId).chartJsConfig.type).toBe("radar");
});
test("filled radar chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_filled_radar");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_radar");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("radar");
expect(runtime.chartJsConfig.data.datasets[0].fill).toBe("start");
});
test("waterfall chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_waterfall");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_waterfall");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("bar");
expect(runtime.chartJsConfig.options.plugins.waterfallLinesPlugin).toEqual({
showConnectorLines: true,
});
});
test("population pyramid chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView({
additionalContext: {
graph_groupbys: ["bar", "product_id"],
graph_measure: ["probability"],
},
});
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_pyramid");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_pyramid");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("bar");
expect(runtime.chartJsConfig.data.datasets[0].data).toEqual([15, 106]);
// negative values for the other side of the pyramid
expect(runtime.chartJsConfig.data.datasets[1].data).toEqual([0, -10]);
});
test("scatter chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_scatter");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_scatter");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("line");
expect(runtime.chartJsConfig.data.datasets[0].showLine).toBe(false);
});
test("geo chart", async () => {
const country_id = fields.Many2one({ string: "Country", relation: "res.country" });
Partner._fields = { ...Partner._fields, country_id };
const mockGeoJson = {
type: "FeatureCollection",
features: [{ type: "Feature", id: "BE", properties: { name: "Belgium" }, geometry: {} }],
};
onRpc("/spreadsheet/static/topojson/world.topo.json", () => mockGeoJson);
onRpc("/spreadsheet/static/topojson/europe.topo.json", () => mockGeoJson);
const { model, env } = await createSpreadsheetFromGraphView({
additionalContext: {
graph_groupbys: ["country_id"],
graph_measure: ["probability"],
},
});
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_geo");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_geo");
expect(model.getters.getChartRuntime(chartId).chartJsConfig.type).toBe("choropleth");
await contains(".o-geo-region select").select("europe");
expect(model.getters.getChartDefinition(chartId).region).toBe("europe");
});
test("sunburst chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView({
additionalContext: {
graph_groupbys: ["product_id", "date:month"],
graph_measure: ["probability"],
},
});
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_sunburst");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_sunburst");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("doughnut");
expect(runtime.chartJsConfig.options.plugins.sunburstHoverPlugin).toEqual({ enabled: true });
expect(runtime.chartJsConfig.data.datasets[0].data).toMatchObject([
{ groups: ["xpad", "December 2016"], label: "December 2016", value: 110 },
{ groups: ["xpad", "October 2016"], label: "October 2016", value: 11 },
{ groups: ["xphone", "April 2016"], label: "April 2016", value: 10 },
]);
expect(runtime.chartJsConfig.data.datasets[1].data).toMatchObject([
{ groups: ["xpad"], label: "xpad", value: 121 },
{ groups: ["xphone"], label: "xphone", value: 10 },
]);
});
test("treemap chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView({
additionalContext: {
graph_groupbys: ["product_id", "date:month"],
graph_measure: ["probability"],
},
});
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_treemap");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_treemap");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("treemap");
expect(runtime.chartJsConfig.data.datasets[0].tree).toEqual([
{ 0: "xphone", 1: "April 2016", value: 10 },
{ 0: "xpad", 1: "October 2016", value: 11 },
{ 0: "xpad", 1: "December 2016", value: 110 },
]);
});
test("cannot change chart type to geo chart for a chart not grouped by country", async () => {
const { model, env } = await createSpreadsheetFromGraphView({});
await openChartSidePanel(model, env);
await contains(".o-type-selector").click();
expect(".o-chart-type-item[data-id='odoo_geo']").toHaveCount(0);
});
test("combo chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView({
additionalContext: {
graph_groupbys: ["bar", "product_id"],
graph_measure: ["probability"],
},
});
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_combo");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_combo");
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("bar");
expect(runtime.chartJsConfig.data.datasets[0].type).toBe("bar");
expect(runtime.chartJsConfig.data.datasets[1].type).toBe("line");
});
test("horizontal & stacked horizontal bar charts", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_horizontal_bar");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_bar");
let runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("bar");
expect(runtime.chartJsConfig.options.indexAxis).toBe("y");
expect(runtime.chartJsConfig.options.scales.x.stacked).toBe(false);
await changeChartType("odoo_horizontal_stacked_bar");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_bar");
runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("bar");
expect(runtime.chartJsConfig.options.indexAxis).toBe("y");
expect(runtime.chartJsConfig.options.scales.x.stacked).toBe(true);
});
test("doughnut charts", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_doughnut");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_pie");
expect(model.getters.getChartDefinition(chartId).isDoughnut).toBe(true);
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.type).toBe("doughnut");
});
test("funnel chart", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_funnel");
expect(model.getters.getChartDefinition(chartId).type).toBe("odoo_funnel");
expect(model.getters.getChartDefinition(chartId).cumulative).toBe(true);
expect(model.getters.getChartRuntime(chartId).chartJsConfig.type).toBe("funnel");
});
describe("trend line", () => {
test("activate trend line with the checkbox", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains("input[name='showTrendLine']").click();
const definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend).toEqual({
type: "polynomial",
order: 1,
display: true,
});
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.data.datasets.length).toBe(2);
});
test("Axistype for odoo line chart trendlines must be defined", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await changeChartType("odoo_line");
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains("input[name='showTrendLine']").click();
const runtime = model.getters.getChartRuntime(chartId);
expect(runtime.chartJsConfig.options.scales.x1.type).toBe("category");
});
test("Can change trend type", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains("input[name='showTrendLine']").click();
let definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend).toEqual({
type: "polynomial",
order: 1,
display: true,
});
await contains(".trend-type-selector").select("logarithmic");
definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend?.type).toBe("logarithmic");
});
test("Can change polynomial degree", async function () {
onRpc("formatted_read_group", () =>
// return at least 3 groups to have a valid trend line
[
{
bar: true,
__count: 1,
__domain: [],
},
{
bar: false,
__count: 2,
__domain: [],
},
{
bar: null,
__count: 3,
__domain: [],
},
]
);
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains("input[name='showTrendLine']").click();
let definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend).toEqual({
type: "polynomial",
order: 1,
display: true,
});
await contains(".trend-type-selector").select("polynomial");
definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend).toEqual({
type: "polynomial",
order: 2,
display: true,
});
await contains(".trend-order-input").select("1");
definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets[0].trend?.order).toBe(1);
});
});
test("Show values", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
expect(model.getters.getChartDefinition(chartId).showValues).toBe(undefined);
let options = model.getters.getChartRuntime(chartId).chartJsConfig.options;
expect(options.plugins.chartShowValuesPlugin.showValues).toBe(false);
await contains("input[name='showValues']").click();
expect(model.getters.getChartDefinition(chartId).showValues).toBe(true);
options = model.getters.getChartRuntime(chartId).chartJsConfig.options;
expect(options.plugins.chartShowValuesPlugin.showValues).toBe(true);
});
test("Use compact format (humanize numbers)", async () => {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
expect(model.getters.getChartDefinition(chartId).humanize).toBe(true);
let options = model.getters.getChartRuntime(chartId).chartJsConfig.options;
expect(options.scales.y.ticks.callback(100000)).toBe("100k");
await contains("input[name='humanizeNumbers']").click();
expect(model.getters.getChartDefinition(chartId).humanize).toBe(false);
options = model.getters.getChartRuntime(chartId).chartJsConfig.options;
expect(options.scales.y.ticks.callback(100000)).toBe("100,000");
});
describe("Can edit chart data series", () => {
test("Can edit bar chart data series ", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains(".o-radio input[value='right']").click();
await contains(".o-serie-label-editor").edit("Random name");
const definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets).toEqual([
{
label: "Random name",
yAxisId: "y1",
},
]);
});
test("Can edit line chart data series ", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
await changeChartType("odoo_line");
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await openChartSidePanel(model, env);
await contains(".o-panel-design").click();
const collapsible = document.querySelectorAll(".collapsor");
await collapsible[1].click();
await contains(".o-radio input[value='right']").click();
await contains(".o-serie-label-editor").edit("Random name");
const definition = model.getters.getChartDefinition(chartId);
expect(definition.dataSets).toEqual([
{
label: "Random name",
yAxisId: "y1",
},
]);
});
});
test("An error is displayed in the side panel if the chart has invalid model", async function () {
const { model, env } = await createSpreadsheetFromGraphView({
mockRPC: async function (route, { model, method, kwargs }) {
if (method === "fields_get") {
throw makeServerError({ code: 404 });
}
},
});
await openChartSidePanel(model, env);
expect(".o-validation-error").toHaveCount(1);
});
test("display chart related filters", async function () {
const { model, env } = await createSpreadsheetFromGraphView();
const sheetId = model.getters.getActiveSheetId();
const chartId = model.getters.getChartIds(sheetId)[0];
await addGlobalFilter(
model,
{ id: "42", type: "relation", label: "Filter" },
{
chart: {
[chartId]: {
chain: "product_id",
type: "many2one",
},
},
}
);
await addGlobalFilter(model, { id: "43", type: "relation", label: "Filter 2" });
await openChartSidePanel(model, env);
expect(".o_side_panel_collapsible_title:contains(Matching 1 / 2 filters)").toHaveCount(1);
});