mirror of
https://github.com/bringout/oca-ocb-report.git
synced 2026-04-21 07:22:07 +02:00
Initial commit: Report packages
This commit is contained in:
commit
bc5e1e9efa
604 changed files with 474102 additions and 0 deletions
|
|
@ -0,0 +1,217 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
import { getBasicData } from "@spreadsheet/../tests/utils/data";
|
||||
import { createBasicChart } from "@spreadsheet/../tests/utils/commands";
|
||||
import { createSpreadsheetWithChart } from "@spreadsheet/../tests/utils/chart";
|
||||
import { makeTestEnv } from "@web/../tests/helpers/mock_env";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { menuService } from "@web/webclient/menus/menu_service";
|
||||
import { actionService } from "@web/webclient/actions/action_service";
|
||||
import { ormService } from "@web/core/orm_service";
|
||||
import { viewService } from "@web/views/view_service";
|
||||
|
||||
const { Model } = spreadsheet;
|
||||
|
||||
const chartId = "uuid1";
|
||||
|
||||
QUnit.module(
|
||||
"spreadsheet > ir.ui.menu chart plugin",
|
||||
{
|
||||
beforeEach: function () {
|
||||
this.serverData = {};
|
||||
this.serverData.menus = {
|
||||
root: {
|
||||
id: "root",
|
||||
children: [1, 2],
|
||||
name: "root",
|
||||
appID: "root",
|
||||
},
|
||||
1: {
|
||||
id: 1,
|
||||
children: [],
|
||||
name: "test menu 1",
|
||||
xmlid: "documents_spreadsheet.test.menu",
|
||||
appID: 1,
|
||||
actionID: "menuAction",
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
children: [],
|
||||
name: "test menu 2",
|
||||
xmlid: "documents_spreadsheet.test.menu2",
|
||||
appID: 1,
|
||||
actionID: "menuAction2",
|
||||
},
|
||||
};
|
||||
this.serverData.actions = {
|
||||
menuAction: {
|
||||
id: 99,
|
||||
xml_id: "ir.ui.menu",
|
||||
name: "menuAction",
|
||||
res_model: "ir.ui.menu",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "list"]],
|
||||
},
|
||||
menuAction2: {
|
||||
id: 100,
|
||||
xml_id: "ir.ui.menu",
|
||||
name: "menuAction2",
|
||||
res_model: "ir.ui.menu",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "list"]],
|
||||
},
|
||||
};
|
||||
this.serverData.views = {};
|
||||
this.serverData.views["ir.ui.menu,false,list"] = `<tree></tree>`;
|
||||
this.serverData.views["ir.ui.menu,false,search"] = `<search></search>`;
|
||||
this.serverData.models = {
|
||||
...getBasicData(),
|
||||
"ir.ui.menu": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
action: { string: "Action", type: "char" },
|
||||
groups_id: {
|
||||
string: "Groups",
|
||||
type: "many2many",
|
||||
relation: "res.group",
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: "test menu 1",
|
||||
action: "action1",
|
||||
groups_id: [10],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "test menu 2",
|
||||
action: "action2",
|
||||
groups_id: [10],
|
||||
},
|
||||
],
|
||||
},
|
||||
"res.users": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
groups_id: {
|
||||
string: "Groups",
|
||||
type: "many2many",
|
||||
relation: "res.group",
|
||||
},
|
||||
},
|
||||
records: [{ id: 1, name: "Raoul", groups_id: [10] }],
|
||||
},
|
||||
"ir.actions": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [{ id: 1 }],
|
||||
},
|
||||
"res.group": {
|
||||
fields: { name: { string: "Name", type: "char" } },
|
||||
records: [{ id: 10, name: "test group" }],
|
||||
},
|
||||
};
|
||||
registry.category("services").add("menu", menuService).add("action", actionService);
|
||||
registry.category("services").add("view", viewService, { force: true }); // #action-serv-leg-compat-js-class
|
||||
registry.category("services").add("orm", ormService, { force: true }); // #action-serv-leg-compat-js-class
|
||||
},
|
||||
},
|
||||
|
||||
() => {
|
||||
QUnit.test(
|
||||
"Links between charts and ir.menus are correctly imported/exported",
|
||||
async function (assert) {
|
||||
const env = await makeTestEnv({ serverData: this.serverData });
|
||||
const model = new Model({}, { evalContext: { env } });
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
const exportedData = model.exportData();
|
||||
assert.equal(
|
||||
exportedData.chartOdooMenusReferences[chartId],
|
||||
1,
|
||||
"Link to odoo menu is exported"
|
||||
);
|
||||
const importedModel = new Model(exportedData, { evalContext: { env } });
|
||||
const chartMenu = importedModel.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu.id, 1, "Link to odoo menu is imported");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Can undo-redo a LINK_ODOO_MENU_TO_CHART", async function (assert) {
|
||||
const env = await makeTestEnv({ serverData: this.serverData });
|
||||
const model = new Model({}, { evalContext: { env } });
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
assert.equal(model.getters.getChartOdooMenu(chartId).id, 1);
|
||||
model.dispatch("REQUEST_UNDO");
|
||||
assert.equal(model.getters.getChartOdooMenu(chartId), undefined);
|
||||
model.dispatch("REQUEST_REDO");
|
||||
assert.equal(model.getters.getChartOdooMenu(chartId).id, 1);
|
||||
});
|
||||
|
||||
QUnit.test("link is removed when figure is deleted", async function (assert) {
|
||||
const env = await makeTestEnv({ serverData: this.serverData });
|
||||
const model = new Model({}, { evalContext: { env } });
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
assert.equal(model.getters.getChartOdooMenu(chartId).id, 1);
|
||||
model.dispatch("DELETE_FIGURE", {
|
||||
sheetId: model.getters.getActiveSheetId(),
|
||||
id: chartId,
|
||||
});
|
||||
assert.equal(model.getters.getChartOdooMenu(chartId), undefined);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Links of Odoo charts are duplicated when duplicating a sheet",
|
||||
async function (assert) {
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_pie",
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const secondSheetId = "mySecondSheetId";
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
model.dispatch("DUPLICATE_SHEET", { sheetId, sheetIdTo: secondSheetId });
|
||||
const newChartId = model.getters.getChartIds(secondSheetId)[0];
|
||||
assert.deepEqual(
|
||||
model.getters.getChartOdooMenu(newChartId),
|
||||
model.getters.getChartOdooMenu(chartId)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Links of standard charts are duplicated when duplicating a sheet",
|
||||
async function (assert) {
|
||||
const env = await makeTestEnv({ serverData: this.serverData });
|
||||
const model = new Model({}, { evalContext: { env } });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const secondSheetId = "mySecondSheetId";
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
model.dispatch("DUPLICATE_SHEET", { sheetId, sheetIdTo: secondSheetId });
|
||||
const newChartId = model.getters.getChartIds(secondSheetId)[0];
|
||||
assert.deepEqual(
|
||||
model.getters.getChartOdooMenu(newChartId),
|
||||
model.getters.getChartOdooMenu(chartId)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { OdooBarChart } from "@spreadsheet/chart/odoo_chart/odoo_bar_chart";
|
||||
import { OdooChart } from "@spreadsheet/chart/odoo_chart/odoo_chart";
|
||||
import { OdooLineChart } from "@spreadsheet/chart/odoo_chart/odoo_line_chart";
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
import { createSpreadsheetWithChart, insertChartInSpreadsheet } from "../../utils/chart";
|
||||
import { createModelWithDataSource, waitForDataSourcesLoaded } from "../../utils/model";
|
||||
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
|
||||
import { RPCError } from "@web/core/network/rpc_service";
|
||||
|
||||
const { toZone } = spreadsheet.helpers;
|
||||
|
||||
QUnit.module("spreadsheet > odoo chart plugin", {}, () => {
|
||||
QUnit.test("Can add an Odoo Bar chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_bar" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
assert.strictEqual(model.getters.getChartIds(sheetId).length, 1);
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const chart = model.getters.getChart(chartId);
|
||||
assert.ok(chart instanceof OdooBarChart);
|
||||
assert.strictEqual(chart.getDefinitionForExcel(), undefined);
|
||||
assert.strictEqual(model.getters.getChartRuntime(chartId).chartJsConfig.type, "bar");
|
||||
});
|
||||
|
||||
QUnit.test("Can add an Odoo Line chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_line" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
assert.strictEqual(model.getters.getChartIds(sheetId).length, 1);
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const chart = model.getters.getChart(chartId);
|
||||
assert.ok(chart instanceof OdooLineChart);
|
||||
assert.strictEqual(chart.getDefinitionForExcel(), undefined);
|
||||
assert.strictEqual(model.getters.getChartRuntime(chartId).chartJsConfig.type, "line");
|
||||
});
|
||||
|
||||
QUnit.test("Can add an Odoo Pie chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_pie" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
assert.strictEqual(model.getters.getChartIds(sheetId).length, 1);
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const chart = model.getters.getChart(chartId);
|
||||
assert.ok(chart instanceof OdooChart);
|
||||
assert.strictEqual(chart.getDefinitionForExcel(), undefined);
|
||||
assert.strictEqual(model.getters.getChartRuntime(chartId).chartJsConfig.type, "pie");
|
||||
});
|
||||
|
||||
QUnit.test("A data source is added after a chart creation", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart();
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
assert.ok(model.getters.getChartDataSource(chartId));
|
||||
});
|
||||
|
||||
QUnit.test("Odoo bar chart runtime loads the data", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_bar",
|
||||
mockRPC: async function (route, args) {
|
||||
if (args.method === "web_read_group") {
|
||||
assert.step("web_read_group");
|
||||
}
|
||||
},
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
assert.verifySteps([], "it should not be loaded eagerly");
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [],
|
||||
labels: [],
|
||||
});
|
||||
await nextTick();
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: "rgb(31,119,180)",
|
||||
borderColor: "rgb(31,119,180)",
|
||||
data: [1, 3],
|
||||
label: "Count",
|
||||
},
|
||||
],
|
||||
labels: ["false", "true"],
|
||||
});
|
||||
assert.verifySteps(["web_read_group"], "it should have loaded the data");
|
||||
});
|
||||
|
||||
QUnit.test("Odoo pie chart runtime loads the data", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_pie",
|
||||
mockRPC: async function (route, args) {
|
||||
if (args.method === "web_read_group") {
|
||||
assert.step("web_read_group");
|
||||
}
|
||||
},
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
assert.verifySteps([], "it should not be loaded eagerly");
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [],
|
||||
labels: [],
|
||||
});
|
||||
await nextTick();
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: ["rgb(31,119,180)", "rgb(255,127,14)", "rgb(174,199,232)"],
|
||||
borderColor: "#FFFFFF",
|
||||
data: [1, 3],
|
||||
label: "",
|
||||
},
|
||||
],
|
||||
labels: ["false", "true"],
|
||||
});
|
||||
assert.verifySteps(["web_read_group"], "it should have loaded the data");
|
||||
});
|
||||
|
||||
QUnit.test("Odoo line chart runtime loads the data", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_line",
|
||||
mockRPC: async function (route, args) {
|
||||
if (args.method === "web_read_group") {
|
||||
assert.step("web_read_group");
|
||||
}
|
||||
},
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
assert.verifySteps([], "it should not be loaded eagerly");
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [],
|
||||
labels: [],
|
||||
});
|
||||
await nextTick();
|
||||
assert.deepEqual(model.getters.getChartRuntime(chartId).chartJsConfig.data, {
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: "#1F77B466",
|
||||
borderColor: "rgb(31,119,180)",
|
||||
data: [1, 3],
|
||||
label: "Count",
|
||||
lineTension: 0,
|
||||
fill: "origin",
|
||||
pointBackgroundColor: "rgb(31,119,180)",
|
||||
},
|
||||
],
|
||||
labels: ["false", "true"],
|
||||
});
|
||||
assert.verifySteps(["web_read_group"], "it should have loaded the data");
|
||||
});
|
||||
|
||||
QUnit.test("Changing the chart type does not reload the data", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_line",
|
||||
mockRPC: async function (route, args) {
|
||||
if (args.method === "web_read_group") {
|
||||
assert.step("web_read_group");
|
||||
}
|
||||
},
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const definition = model.getters.getChartDefinition(chartId);
|
||||
|
||||
// force runtime computation
|
||||
model.getters.getChartRuntime(chartId);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["web_read_group"], "it should have loaded the data");
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
type: "odoo_bar",
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
await nextTick();
|
||||
// force runtime computation
|
||||
model.getters.getChartRuntime(chartId);
|
||||
assert.verifySteps([], "it should have not have loaded the data a second time");
|
||||
});
|
||||
|
||||
QUnit.test("Can import/export an Odoo chart", async (assert) => {
|
||||
const model = await createModelWithDataSource();
|
||||
insertChartInSpreadsheet(model, "odoo_line");
|
||||
const data = model.exportData();
|
||||
const figures = data.sheets[0].figures;
|
||||
assert.strictEqual(figures.length, 1);
|
||||
const figure = figures[0];
|
||||
assert.strictEqual(figure.tag, "chart");
|
||||
assert.strictEqual(figure.data.type, "odoo_line");
|
||||
const m1 = await createModelWithDataSource({ spreadsheetData: data });
|
||||
const sheetId = m1.getters.getActiveSheetId();
|
||||
assert.strictEqual(m1.getters.getChartIds(sheetId).length, 1);
|
||||
const chartId = m1.getters.getChartIds(sheetId)[0];
|
||||
assert.ok(m1.getters.getChartDataSource(chartId));
|
||||
assert.strictEqual(m1.getters.getChartRuntime(chartId).chartJsConfig.type, "line");
|
||||
});
|
||||
|
||||
QUnit.test("Can undo/redo an Odoo chart creation", async (assert) => {
|
||||
const model = await createModelWithDataSource();
|
||||
insertChartInSpreadsheet(model, "odoo_line");
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
assert.ok(model.getters.getChartDataSource(chartId));
|
||||
model.dispatch("REQUEST_UNDO");
|
||||
assert.strictEqual(model.getters.getChartIds(sheetId).length, 0);
|
||||
model.dispatch("REQUEST_REDO");
|
||||
assert.ok(model.getters.getChartDataSource(chartId));
|
||||
assert.strictEqual(model.getters.getChartIds(sheetId).length, 1);
|
||||
});
|
||||
|
||||
QUnit.test("charts with no legend", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_pie" });
|
||||
insertChartInSpreadsheet(model, "odoo_bar");
|
||||
insertChartInSpreadsheet(model, "odoo_line");
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const [pieChartId, barChartId, lineChartId] = model.getters.getChartIds(sheetId);
|
||||
const pie = model.getters.getChartDefinition(pieChartId);
|
||||
const bar = model.getters.getChartDefinition(barChartId);
|
||||
const line = model.getters.getChartDefinition(lineChartId);
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(pieChartId).chartJsConfig.options.legend.display,
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(barChartId).chartJsConfig.options.legend.display,
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(lineChartId).chartJsConfig.options.legend.display,
|
||||
true
|
||||
);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...pie,
|
||||
legendPosition: "none",
|
||||
},
|
||||
id: pieChartId,
|
||||
sheetId,
|
||||
});
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...bar,
|
||||
legendPosition: "none",
|
||||
},
|
||||
id: barChartId,
|
||||
sheetId,
|
||||
});
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...line,
|
||||
legendPosition: "none",
|
||||
},
|
||||
id: lineChartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(pieChartId).chartJsConfig.options.legend.display,
|
||||
false
|
||||
);
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(barChartId).chartJsConfig.options.legend.display,
|
||||
false
|
||||
);
|
||||
assert.strictEqual(
|
||||
model.getters.getChartRuntime(lineChartId).chartJsConfig.options.legend.display,
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Bar chart with stacked attribute is supported", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_bar" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const definition = model.getters.getChartDefinition(chartId);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
stacked: true,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.ok(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.xAxes[0].stacked
|
||||
);
|
||||
assert.ok(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.yAxes[0].stacked
|
||||
);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
stacked: false,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.notOk(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.xAxes[0].stacked
|
||||
);
|
||||
assert.notOk(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.yAxes[0].stacked
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Can copy/paste Odoo chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_pie" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
model.dispatch("SELECT_FIGURE", { id: chartId });
|
||||
model.dispatch("COPY");
|
||||
model.dispatch("PASTE", { target: [toZone("A1")] });
|
||||
const chartIds = model.getters.getChartIds(sheetId);
|
||||
assert.strictEqual(chartIds.length, 2);
|
||||
assert.ok(model.getters.getChart(chartIds[1]) instanceof OdooChart);
|
||||
assert.strictEqual(
|
||||
JSON.stringify(model.getters.getChartRuntime(chartIds[1])),
|
||||
JSON.stringify(model.getters.getChartRuntime(chartId))
|
||||
);
|
||||
|
||||
assert.notEqual(
|
||||
model.getters.getChart(chartId).dataSource,
|
||||
model.getters.getChart(chartIds[1]).dataSource,
|
||||
"The datasource is also duplicated"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Can cut/paste Odoo chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_pie" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const chartRuntime = model.getters.getChartRuntime(chartId);
|
||||
model.dispatch("SELECT_FIGURE", { id: chartId });
|
||||
model.dispatch("CUT");
|
||||
model.dispatch("PASTE", { target: [toZone("A1")] });
|
||||
const chartIds = model.getters.getChartIds(sheetId);
|
||||
assert.strictEqual(chartIds.length, 1);
|
||||
assert.notEqual(chartIds[0], chartId);
|
||||
assert.ok(model.getters.getChart(chartIds[0]) instanceof OdooChart);
|
||||
assert.strictEqual(
|
||||
JSON.stringify(model.getters.getChartRuntime(chartIds[0])),
|
||||
JSON.stringify(chartRuntime)
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Duplicating a sheet correctly duplicates Odoo chart", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_bar" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const secondSheetId = "secondSheetId";
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
model.dispatch("DUPLICATE_SHEET", { sheetId, sheetIdTo: secondSheetId });
|
||||
const chartIds = model.getters.getChartIds(secondSheetId);
|
||||
assert.strictEqual(chartIds.length, 1);
|
||||
assert.ok(model.getters.getChart(chartIds[0]) instanceof OdooChart);
|
||||
assert.strictEqual(
|
||||
JSON.stringify(model.getters.getChartRuntime(chartIds[0])),
|
||||
JSON.stringify(model.getters.getChartRuntime(chartId))
|
||||
);
|
||||
|
||||
assert.notEqual(
|
||||
model.getters.getChart(chartId).dataSource,
|
||||
model.getters.getChart(chartIds[0]).dataSource,
|
||||
"The datasource is also duplicated"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Line chart with stacked attribute is supported", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_line" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const definition = model.getters.getChartDefinition(chartId);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
stacked: true,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.notOk(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.xAxes[0].stacked
|
||||
);
|
||||
assert.ok(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.yAxes[0].stacked
|
||||
);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
stacked: false,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.notOk(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.xAxes[0].stacked
|
||||
);
|
||||
assert.notOk(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.options.scales.yAxes[0].stacked
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Load odoo chart spreadsheet with models that cannot be accessed",
|
||||
async function (assert) {
|
||||
let hasAccessRights = true;
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
mockRPC: async function (route, args) {
|
||||
if (
|
||||
args.model === "partner" &&
|
||||
args.method === "web_read_group" &&
|
||||
!hasAccessRights
|
||||
) {
|
||||
const error = new RPCError();
|
||||
error.data = { message: "ya done!" };
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
});
|
||||
const chartId = model.getters.getFigures(model.getters.getActiveSheetId())[0].id;
|
||||
const chartDataSource = model.getters.getChartDataSource(chartId);
|
||||
await waitForDataSourcesLoaded(model);
|
||||
const data = chartDataSource.getData();
|
||||
assert.equal(data.datasets.length, 1);
|
||||
assert.equal(data.labels.length, 2);
|
||||
|
||||
hasAccessRights = false;
|
||||
chartDataSource.load({ reload: true });
|
||||
await waitForDataSourcesLoaded(model);
|
||||
assert.deepEqual(chartDataSource.getData(), { datasets: [], labels: [] });
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Line chart to support cumulative data", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_line" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
const definition = model.getters.getChartDefinition(chartId);
|
||||
await waitForDataSourcesLoaded(model);
|
||||
assert.deepEqual(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.data.datasets[0].data,
|
||||
[1, 3]
|
||||
);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
cumulative: true,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.deepEqual(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.data.datasets[0].data,
|
||||
[1, 4]
|
||||
);
|
||||
model.dispatch("UPDATE_CHART", {
|
||||
definition: {
|
||||
...definition,
|
||||
cumulative: false,
|
||||
},
|
||||
id: chartId,
|
||||
sheetId,
|
||||
});
|
||||
assert.deepEqual(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.data.datasets[0].data,
|
||||
[1, 3]
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Remove odoo chart when sheet is deleted", async (assert) => {
|
||||
const { model } = await createSpreadsheetWithChart({ type: "odoo_line" });
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
model.dispatch("CREATE_SHEET", {
|
||||
sheetId: model.uuidGenerator.uuidv4(),
|
||||
position: model.getters.getSheetIds().length,
|
||||
});
|
||||
assert.strictEqual(model.getters.getOdooChartIds().length, 1);
|
||||
model.dispatch("DELETE_SHEET", { sheetId });
|
||||
assert.strictEqual(model.getters.getOdooChartIds().length, 0);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { click, nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { session } from "@web/session";
|
||||
import { getBasicData } from "@spreadsheet/../tests/utils/data";
|
||||
import { createBasicChart } from "@spreadsheet/../tests/utils/commands";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { menuService } from "@web/webclient/menus/menu_service";
|
||||
import { actionService } from "@web/webclient/actions/action_service";
|
||||
import { ormService } from "@web/core/orm_service";
|
||||
import { viewService } from "@web/views/view_service";
|
||||
import { mountSpreadsheet } from "@spreadsheet/../tests/utils/ui";
|
||||
import { createModelWithDataSource } from "@spreadsheet/../tests/utils/model";
|
||||
|
||||
const chartId = "uuid1";
|
||||
|
||||
/**
|
||||
* The chart menu is hidden by default, and visible on :hover, but this property
|
||||
* can't be triggered programmatically, so we artificially make it visible to be
|
||||
* able to interact with it.
|
||||
*/
|
||||
async function showChartMenu(fixture) {
|
||||
const chartMenu = fixture.querySelector(".o-chart-menu");
|
||||
chartMenu.style.display = "flex";
|
||||
await nextTick();
|
||||
}
|
||||
|
||||
/** Click on external link of the first chart found in the page*/
|
||||
async function clickChartExternalLink(fixture) {
|
||||
await showChartMenu(fixture);
|
||||
const chartMenuItem = fixture.querySelector(".o-chart-menu-item.o-chart-external-link");
|
||||
await click(chartMenuItem);
|
||||
}
|
||||
|
||||
function mockActionService(assert, doActionStep) {
|
||||
const serviceRegistry = registry.category("services");
|
||||
serviceRegistry.add("actionMain", actionService);
|
||||
const fakeActionService = {
|
||||
dependencies: ["actionMain"],
|
||||
start(env, { actionMain }) {
|
||||
return {
|
||||
...actionMain,
|
||||
doAction: (actionRequest, options = {}) => {
|
||||
if (actionRequest === "menuAction2") {
|
||||
assert.step(doActionStep);
|
||||
}
|
||||
return actionMain.doAction(actionRequest, options);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
serviceRegistry.add("action", fakeActionService, {
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
|
||||
QUnit.module(
|
||||
"spreadsheet > ir.ui.menu chart figure",
|
||||
{
|
||||
beforeEach: function () {
|
||||
this.serverData = {};
|
||||
this.serverData.menus = {
|
||||
root: {
|
||||
id: "root",
|
||||
children: [1, 2],
|
||||
name: "root",
|
||||
appID: "root",
|
||||
},
|
||||
1: {
|
||||
id: 1,
|
||||
children: [],
|
||||
name: "test menu 1",
|
||||
xmlid: "documents_spreadsheet.test.menu",
|
||||
appID: 1,
|
||||
actionID: "menuAction",
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
children: [],
|
||||
name: "test menu 2",
|
||||
xmlid: "documents_spreadsheet.test.menu2",
|
||||
appID: 1,
|
||||
actionID: "menuAction2",
|
||||
},
|
||||
};
|
||||
this.serverData.actions = {
|
||||
menuAction: {
|
||||
id: 99,
|
||||
xml_id: "ir.ui.menu",
|
||||
name: "menuAction",
|
||||
res_model: "ir.ui.menu",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "list"]],
|
||||
},
|
||||
menuAction2: {
|
||||
id: 100,
|
||||
xml_id: "ir.ui.menu",
|
||||
name: "menuAction2",
|
||||
res_model: "ir.ui.menu",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "list"]],
|
||||
},
|
||||
};
|
||||
this.serverData.views = {};
|
||||
this.serverData.views["ir.ui.menu,false,list"] = `<tree></tree>`;
|
||||
this.serverData.views["ir.ui.menu,false,search"] = `<search></search>`;
|
||||
this.serverData.models = {
|
||||
...getBasicData(),
|
||||
"ir.ui.menu": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
action: { string: "Action", type: "char" },
|
||||
groups_id: {
|
||||
string: "Groups",
|
||||
type: "many2many",
|
||||
relation: "res.group",
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: "test menu 1",
|
||||
action: "action1",
|
||||
groups_id: [10],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "test menu 2",
|
||||
action: "action2",
|
||||
groups_id: [10],
|
||||
},
|
||||
],
|
||||
},
|
||||
"res.users": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
groups_id: {
|
||||
string: "Groups",
|
||||
type: "many2many",
|
||||
relation: "res.group",
|
||||
},
|
||||
},
|
||||
records: [{ id: 1, name: "Raoul", groups_id: [10] }],
|
||||
},
|
||||
"ir.actions": {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [{ id: 1 }],
|
||||
},
|
||||
"res.group": {
|
||||
fields: { name: { string: "Name", type: "char" } },
|
||||
records: [{ id: 10, name: "test group" }],
|
||||
},
|
||||
};
|
||||
patchWithCleanup(session, { uid: 1 });
|
||||
registry.category("services").add("menu", menuService).add("action", actionService);
|
||||
registry.category("services").add("view", viewService, { force: true }); // #action-serv-leg-compat-js-class
|
||||
registry.category("services").add("orm", ormService, { force: true }); // #action-serv-leg-compat-js-class
|
||||
},
|
||||
},
|
||||
|
||||
() => {
|
||||
QUnit.test(
|
||||
"icon external link isn't on the chart when its not linked to an odoo menu",
|
||||
async function (assert) {
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
createBasicChart(model, chartId);
|
||||
await nextTick();
|
||||
const odooMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(odooMenu, undefined, "No menu linked with the chart");
|
||||
|
||||
const externalRefIcon = fixture.querySelector(".o-chart-external-link");
|
||||
assert.equal(externalRefIcon, null);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"icon external link is on the chart when its linked to an odoo menu",
|
||||
async function (assert) {
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
const chartMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu.id, 1, "Odoo menu is linked to chart");
|
||||
await nextTick();
|
||||
const externalRefIcon = fixture.querySelector(".o-chart-external-link");
|
||||
assert.ok(externalRefIcon);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"icon external link is not on the chart when its linked to a wrong odoo menu",
|
||||
async function (assert) {
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: "menu which does not exist",
|
||||
});
|
||||
const chartMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu, undefined, "cannot get a wrong menu");
|
||||
await nextTick();
|
||||
assert.containsNone(fixture, ".o-chart-external-link");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"icon external link isn't on the chart in dashboard mode",
|
||||
async function (assert) {
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 1,
|
||||
});
|
||||
const chartMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu.id, 1, "Odoo menu is linked to chart");
|
||||
model.updateMode("dashboard");
|
||||
await nextTick();
|
||||
assert.containsNone(fixture, ".o-chart-external-link", "No link icon in dashboard");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"click on icon external link on chart redirect to the odoo menu",
|
||||
async function (assert) {
|
||||
const doActionStep = "doAction";
|
||||
mockActionService(assert, doActionStep);
|
||||
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 2,
|
||||
});
|
||||
const chartMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu.id, 2, "Odoo menu is linked to chart");
|
||||
await nextTick();
|
||||
|
||||
await clickChartExternalLink(fixture);
|
||||
|
||||
assert.verifySteps([doActionStep]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Click on chart in dashboard mode redirect to the odoo menu",
|
||||
async function (assert) {
|
||||
const doActionStep = "doAction";
|
||||
mockActionService(assert, doActionStep);
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: 2,
|
||||
});
|
||||
const chartMenu = model.getters.getChartOdooMenu(chartId);
|
||||
assert.equal(chartMenu.id, 2, "Odoo menu is linked to chart");
|
||||
await nextTick();
|
||||
|
||||
await click(fixture, ".o-chart-container");
|
||||
assert.verifySteps([], "Clicking on a chart while not dashboard mode do nothing");
|
||||
|
||||
model.updateMode("dashboard");
|
||||
await nextTick();
|
||||
await click(fixture, ".o-chart-container");
|
||||
assert.verifySteps(
|
||||
[doActionStep],
|
||||
"Clicking on a chart while on dashboard mode redirect to the odoo menu"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("can use menus xmlIds instead of menu ids", async function (assert) {
|
||||
const serviceRegistry = registry.category("services");
|
||||
serviceRegistry.add("actionMain", actionService);
|
||||
const fakeActionService = {
|
||||
dependencies: ["actionMain"],
|
||||
start(env, { actionMain }) {
|
||||
return {
|
||||
...actionMain,
|
||||
doAction: (actionRequest, options = {}) => {
|
||||
if (actionRequest === "menuAction2") {
|
||||
assert.step("doAction");
|
||||
}
|
||||
return actionMain.doAction(actionRequest, options);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
serviceRegistry.add("action", fakeActionService, {
|
||||
force: true,
|
||||
});
|
||||
|
||||
const model = await createModelWithDataSource({
|
||||
serverData: this.serverData,
|
||||
});
|
||||
const fixture = await mountSpreadsheet(model);
|
||||
|
||||
createBasicChart(model, chartId);
|
||||
model.dispatch("LINK_ODOO_MENU_TO_CHART", {
|
||||
chartId,
|
||||
odooMenuId: "documents_spreadsheet.test.menu2",
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
await clickChartExternalLink(fixture);
|
||||
|
||||
assert.verifySteps(["doAction"]);
|
||||
});
|
||||
}
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue