427 lines
18 KiB
JavaScript
427 lines
18 KiB
JavaScript
/** @odoo-module */
|
|
|
|
import * as spreadsheet from "@odoo/o-spreadsheet";
|
|
import { nextTick, getFixture } from "@web/../tests/helpers/utils";
|
|
import { createSpreadsheet } from "../spreadsheet_test_utils";
|
|
import {
|
|
getBasicData,
|
|
getBasicPivotArch,
|
|
getBasicServerData,
|
|
} from "@spreadsheet/../tests/utils/data";
|
|
import {
|
|
getCell,
|
|
getCellFormula,
|
|
getCellValue,
|
|
getEvaluatedCell,
|
|
} from "@spreadsheet/../tests/utils/getters";
|
|
import {
|
|
addGlobalFilter,
|
|
selectCell,
|
|
setCellContent,
|
|
setGlobalFilterValue,
|
|
} from "@spreadsheet/../tests/utils/commands";
|
|
import { createSpreadsheetFromPivotView } from "../utils/pivot_helpers";
|
|
import {
|
|
createSpreadsheetWithPivot,
|
|
insertPivotInSpreadsheet,
|
|
} from "@spreadsheet/../tests/utils/pivot";
|
|
import { session } from "@web/session";
|
|
|
|
const { toCartesian, toZone } = spreadsheet.helpers;
|
|
const { cellMenuRegistry, topbarMenuRegistry } = spreadsheet.registries;
|
|
import { doMenuAction } from "@spreadsheet/../tests/utils/ui";
|
|
|
|
let target;
|
|
|
|
const reinsertPivotPath = ["data", "insert_pivot", "reinsert_pivot", "reinsert_pivot_1"];
|
|
|
|
QUnit.module(
|
|
"documents_spreadsheet > Pivot Menu Items",
|
|
{
|
|
beforeEach: function () {
|
|
target = getFixture();
|
|
},
|
|
},
|
|
function () {
|
|
QUnit.test("Reinsert a pivot", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "D8");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(
|
|
getCellFormula(model, "E10"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",1)`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
});
|
|
|
|
QUnit.test("Reinsert a pivot with a contextual search domain", async function (assert) {
|
|
const serverData = getBasicServerData();
|
|
const uid = session.user_context.uid;
|
|
serverData.models.partner.records = [{ id: 1, probability: 0.5, foo: uid }];
|
|
serverData.views["partner,false,search"] = /* xml */ `
|
|
<search>
|
|
<filter string="Filter" name="filter" domain="[('foo', '=', uid)]"/>
|
|
</search>
|
|
`;
|
|
const { model, env } = await createSpreadsheetFromPivotView({
|
|
serverData,
|
|
additionalContext: { search_default_filter: 1 },
|
|
});
|
|
|
|
selectCell(model, "D8");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(
|
|
getCellFormula(model, "E10"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",${uid})`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
});
|
|
|
|
QUnit.test("Reinsert a pivot in a too small sheet", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
const sheetId = model.getters.getActiveSheetId();
|
|
model.dispatch("CREATE_SHEET", { cols: 1, rows: 1, sheetId: "111" });
|
|
model.dispatch("ACTIVATE_SHEET", {
|
|
sheetIdFrom: sheetId,
|
|
sheetIdTo: "111",
|
|
});
|
|
selectCell(model, "A1");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(model.getters.getNumberCols("111"), 6);
|
|
assert.equal(model.getters.getNumberRows("111"), 5);
|
|
assert.equal(
|
|
getCellFormula(model, "B3"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",1)`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
});
|
|
|
|
QUnit.test("Reinsert a pivot with new data", async function (assert) {
|
|
const data = getBasicData();
|
|
|
|
const { model, env } = await createSpreadsheetWithPivot({
|
|
serverData: {
|
|
models: data,
|
|
views: getBasicServerData().views,
|
|
},
|
|
});
|
|
data.partner.records.push({
|
|
active: true,
|
|
id: 5,
|
|
foo: 25, // <- New value inserted
|
|
bar: false,
|
|
date: "2016-12-11",
|
|
product_id: 41,
|
|
probability: 15,
|
|
field_with_array_agg: 4,
|
|
create_date: "2016-12-11",
|
|
tag_ids: [],
|
|
});
|
|
selectCell(model, "D8");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(getCellFormula(model, "I8"), `=ODOO.PIVOT.HEADER(1,"foo",25)`);
|
|
assert.equal(
|
|
getCellFormula(model, "I10"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",25)`
|
|
);
|
|
});
|
|
|
|
QUnit.test("Reinsert a pivot with an updated record", async function (assert) {
|
|
const data = getBasicData();
|
|
|
|
const { model, env } = await createSpreadsheetWithPivot({
|
|
serverData: {
|
|
models: data,
|
|
views: getBasicServerData().views,
|
|
},
|
|
});
|
|
assert.equal(getCellValue(model, "B1"), 1);
|
|
assert.equal(getCellValue(model, "C1"), 2);
|
|
assert.equal(getCellValue(model, "D1"), 12);
|
|
data.partner.records[0].foo = 99;
|
|
data.partner.records[1].foo = 99;
|
|
// updated measures
|
|
data.partner.records[0].probability = 88;
|
|
data.partner.records[1].probability = 77;
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
await nextTick();
|
|
assert.equal(getCellValue(model, "D1"), 99, "The header should have been updated");
|
|
assert.equal(getCellValue(model, "D4"), 77 + 88, "The value should have been updated");
|
|
});
|
|
|
|
QUnit.test(
|
|
"Reinsert a pivot which has no formula on the sheet (meaning the data is not loaded)",
|
|
async function (assert) {
|
|
const spreadsheetData = {
|
|
sheets: [
|
|
{
|
|
id: "sheet1",
|
|
},
|
|
],
|
|
pivots: {
|
|
1: {
|
|
id: 1,
|
|
colGroupBys: ["foo"],
|
|
domain: [],
|
|
measures: [{ field: "probability", operator: "avg" }],
|
|
model: "partner",
|
|
rowGroupBys: ["bar"],
|
|
context: {},
|
|
},
|
|
},
|
|
};
|
|
const serverData = getBasicServerData();
|
|
serverData.models["documents.document"].records.push({
|
|
id: 45,
|
|
spreadsheet_data: JSON.stringify(spreadsheetData),
|
|
name: "Spreadsheet",
|
|
handler: "spreadsheet",
|
|
});
|
|
const { model, env } = await createSpreadsheet({
|
|
serverData,
|
|
spreadsheetId: 45,
|
|
});
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(getCellFormula(model, "C1"), `=ODOO.PIVOT.HEADER(1,"foo",2)`);
|
|
assert.equal(
|
|
getCellFormula(model, "C2"),
|
|
`=ODOO.PIVOT.HEADER(1,"foo",2,"measure","probability")`
|
|
);
|
|
assert.equal(
|
|
getCellFormula(model, "C3"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",2)`
|
|
);
|
|
await nextTick();
|
|
assert.equal(getCellValue(model, "C1"), 2);
|
|
assert.equal(getCellValue(model, "C2"), "Probability");
|
|
assert.equal(getCellValue(model, "C3"), 15);
|
|
}
|
|
);
|
|
|
|
QUnit.test("Keep applying filter when pivot is re-inserted", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot({
|
|
arch: /*xml*/ `
|
|
<pivot>
|
|
<field name="bar" type="col"/>
|
|
<field name="product_id" type="row"/>
|
|
<field name="probability" type="measure"/>
|
|
</pivot>`,
|
|
});
|
|
await addGlobalFilter(
|
|
model,
|
|
{
|
|
id: "42",
|
|
type: "relation",
|
|
label: "Filter",
|
|
},
|
|
{
|
|
pivot: {
|
|
1: {
|
|
chain: "product_id",
|
|
type: "many2one",
|
|
},
|
|
},
|
|
}
|
|
);
|
|
await nextTick();
|
|
await setGlobalFilterValue(model, {
|
|
id: "42",
|
|
value: [41],
|
|
});
|
|
await nextTick();
|
|
assert.equal(getCellValue(model, "B3"), "", "The value should have been filtered");
|
|
assert.equal(getCellValue(model, "C3"), "", "The value should have been filtered");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
await nextTick();
|
|
assert.equal(getCellValue(model, "B3"), "", "The value should still be filtered");
|
|
assert.equal(getCellValue(model, "C3"), "", "The value should still be filtered");
|
|
});
|
|
|
|
QUnit.test("undo pivot reinsert", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "D8");
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(
|
|
getCellFormula(model, "E10"),
|
|
`=ODOO.PIVOT(1,"probability","bar","false","foo",1)`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
model.dispatch("REQUEST_UNDO");
|
|
assert.notOk(getCell(model, "E10"), "It should have removed the re-inserted pivot");
|
|
});
|
|
|
|
QUnit.test("reinsert pivot with anchor on merge but not top left", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
const sheetId = model.getters.getActiveSheetId();
|
|
assert.equal(
|
|
getCellFormula(model, "B2"),
|
|
`=ODOO.PIVOT.HEADER(1,"foo",1,"measure","probability")`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
model.dispatch("ADD_MERGE", {
|
|
sheetId,
|
|
target: [{ top: 0, bottom: 1, left: 0, right: 0 }],
|
|
force: true,
|
|
});
|
|
selectCell(model, "A2"); // A1 and A2 are merged; select A2
|
|
const { col, row } = toCartesian("A2");
|
|
assert.ok(model.getters.isInMerge({ sheetId, col, row }));
|
|
await doMenuAction(topbarMenuRegistry, reinsertPivotPath, env);
|
|
assert.equal(
|
|
getCellFormula(model, "B2"),
|
|
`=ODOO.PIVOT.HEADER(1,"foo",1,"measure","probability")`,
|
|
"It should contain a pivot formula"
|
|
);
|
|
});
|
|
|
|
QUnit.test("Verify presence of pivot properties on pivot cell", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "B2");
|
|
const root = cellMenuRegistry.getAll().find((item) => item.id === "pivot_properties");
|
|
assert.ok(root.isVisible(env));
|
|
});
|
|
|
|
QUnit.test("Verify absence of pivot properties on non-pivot cell", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "Z26");
|
|
const root = cellMenuRegistry.getAll().find((item) => item.id === "pivot_properties");
|
|
assert.notOk(root.isVisible(env));
|
|
});
|
|
|
|
QUnit.test("Verify absence of pivot properties on formula with invalid pivot Id", async function (assert) {
|
|
const { model, env } = await createSpreadsheetWithPivot();
|
|
setCellContent(model, "A1", `=ODOO.PIVOT.HEADER("fakeId")`);
|
|
const root = cellMenuRegistry.getAll().find((item) => item.id === "pivot_properties");
|
|
assert.notOk(root.isVisible(env));
|
|
setCellContent(model, "A1", `=ODOO.PIVOT("fakeId", "probability", "foo", 2)`);
|
|
assert.notOk(root.isVisible(env));
|
|
});
|
|
|
|
QUnit.test(
|
|
"verify absence of pivots in top menu bar in a spreadsheet without a pivot",
|
|
async function (assert) {
|
|
await createSpreadsheet();
|
|
assert.containsNone(target, "div[data-id='pivots']");
|
|
}
|
|
);
|
|
|
|
QUnit.test(
|
|
"Verify presence of pivots in top menu bar in a spreadsheet with a pivot",
|
|
async function (assert) {
|
|
const { model, env } = await createSpreadsheetFromPivotView();
|
|
await insertPivotInSpreadsheet(model, { arch: getBasicPivotArch() });
|
|
assert.ok(
|
|
target.querySelector("div[data-id='data']"),
|
|
"The 'Pivots' menu should be in the dom"
|
|
);
|
|
|
|
const root = topbarMenuRegistry.getMenuItems().find((item) => item.id === "data");
|
|
const children = root.children(env);
|
|
assert.ok(children.find((c) => c.name(env) === "(#1) Partners by Foo"));
|
|
assert.ok(children.find((c) => c.name(env) === "(#2) Partner Pivot"));
|
|
// bottom children
|
|
assert.ok(children.find((c) => c.name(env) === "Refresh all data"));
|
|
assert.ok(children.find((c) => c.name(env) === "Insert pivot"));
|
|
assert.ok(children.find((c) => c.name(env) === "Re-insert list"));
|
|
|
|
const insertPivotChildren = children
|
|
.find((c) => c.name(env) === "Insert pivot")
|
|
.children(env);
|
|
assert.ok(insertPivotChildren.find((c) => c.name(env) === "Re-insert pivot"));
|
|
assert.ok(insertPivotChildren.find((c) => c.name(env) === "Insert pivot cell"));
|
|
}
|
|
);
|
|
|
|
QUnit.test("Pivot focus changes on top bar menu click", async function (assert) {
|
|
const { model, env } = await createSpreadsheetFromPivotView();
|
|
await insertPivotInSpreadsheet(model, { arch: getBasicPivotArch() });
|
|
|
|
env.openSidePanel("PIVOT_PROPERTIES_PANEL", {});
|
|
assert.notOk(model.getters.getSelectedPivotId(), "No pivot should be selected");
|
|
await doMenuAction(topbarMenuRegistry, ["data", "item_pivot_1"], env);
|
|
assert.equal(
|
|
model.getters.getSelectedPivotId(),
|
|
"1",
|
|
"The selected pivot should have id 1"
|
|
);
|
|
await doMenuAction(topbarMenuRegistry, ["data", "item_pivot_2"], env);
|
|
assert.equal(
|
|
model.getters.getSelectedPivotId(),
|
|
"2",
|
|
"The selected pivot should have id 2"
|
|
);
|
|
});
|
|
|
|
QUnit.test(
|
|
"Can rebuild the Odoo domain of records based on the according merged pivot cell",
|
|
async function (assert) {
|
|
const { webClient, model } = await createSpreadsheetFromPivotView();
|
|
const env = {
|
|
...webClient.env,
|
|
model,
|
|
services: {
|
|
...model.config.custom.env.services,
|
|
action: {
|
|
doAction: (params) => {
|
|
assert.step(params.res_model);
|
|
assert.step(JSON.stringify(params.domain));
|
|
},
|
|
},
|
|
},
|
|
};
|
|
model.dispatch("ADD_MERGE", {
|
|
sheetId: model.getters.getActiveSheetId(),
|
|
target: [toZone("C3:D3")],
|
|
force: true, // there are data in D3
|
|
});
|
|
selectCell(model, "D3");
|
|
await nextTick();
|
|
const root = cellMenuRegistry
|
|
.getAll()
|
|
.find((item) => item.id === "pivot_see_records");
|
|
await root.execute(env);
|
|
assert.verifySteps(["partner", `[["foo","=",2],["bar","=",false]]`]);
|
|
}
|
|
);
|
|
|
|
QUnit.test(
|
|
"See records is visible even if the formula is lowercase",
|
|
async function (assert) {
|
|
const { env, model } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "B4");
|
|
await nextTick();
|
|
const root = cellMenuRegistry
|
|
.getAll()
|
|
.find((item) => item.id === "pivot_see_records");
|
|
assert.ok(root.isVisible(env));
|
|
setCellContent(
|
|
model,
|
|
"B4",
|
|
getCellFormula(model, "B4").replace("ODOO.PIVOT", "odoo.pivot")
|
|
);
|
|
assert.ok(root.isVisible(env));
|
|
}
|
|
);
|
|
|
|
QUnit.test(
|
|
"See records is not visible if the formula is in error",
|
|
async function (assert) {
|
|
const { env, model } = await createSpreadsheetWithPivot();
|
|
selectCell(model, "B4");
|
|
await nextTick();
|
|
const root = cellMenuRegistry
|
|
.getAll()
|
|
.find((item) => item.id === "pivot_see_records");
|
|
assert.ok(root.isVisible(env));
|
|
setCellContent(
|
|
model,
|
|
"B4",
|
|
getCellFormula(model, "B4").replace(`ODOO.PIVOT(1`, `ODOO.PIVOT("5)`)
|
|
); //Invalid id
|
|
assert.ok(getEvaluatedCell(model, "B4").error.message);
|
|
assert.notOk(root.isVisible(env));
|
|
}
|
|
);
|
|
}
|
|
);
|