Files
enterprise-addons/spreadsheet_sale_management/static/tests/field_sync_plugins.test.js
T

446 lines
16 KiB
JavaScript

import { describe, before, expect, test } from "@odoo/hoot";
import { animationFrame } from "@odoo/hoot-mock";
import { Model } from "@odoo/o-spreadsheet";
import { x2ManyCommands } from "@web/core/orm_service";
import {
addColumns,
addRows,
autofill,
undo,
redo,
copy,
cut,
paste,
deleteColumns,
setCellContent,
} from "@spreadsheet/../tests/helpers/commands";
import { getCellContent } from "@spreadsheet/../tests/helpers/getters";
import { mailModels } from "@mail/../tests/mail_test_helpers";
import { defineModels, onRpc } from "@web/../tests/web_test_helpers";
import {
addFieldSync,
deleteFieldSyncs,
createSaleOrderSpreadsheetModel,
} from "./helpers/commands";
import { addSpreadsheetFieldSyncExtensionWithCleanUp } from "../src/bundle/field_sync/field_sync_extension_hook";
import { getFieldSync } from "./helpers/getters";
import { SaleOrderLine, defineSpreadsheetSaleModels } from "./helpers/data";
describe.current.tags("headless");
defineModels(mailModels);
defineSpreadsheetSaleModels();
before(() => {
addSpreadsheetFieldSyncExtensionWithCleanUp();
});
test("add a field sync", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
const fieldSync = getFieldSync(model, "A1");
expect(fieldSync).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
undo(model);
expect(getFieldSync(model, "A1")).toBe(undefined);
redo(model);
expect(getFieldSync(model, "A1")).toEqual(fieldSync);
});
test("delete a field sync", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
const fieldSync = getFieldSync(model, "A1");
deleteFieldSyncs(model, "A1");
expect(getFieldSync(model, "A1")).toBe(undefined);
undo(model);
expect(getFieldSync(model, "A1")).toBe(fieldSync);
redo(model);
expect(getFieldSync(model, "A1")).toBe(undefined);
});
test("export/import a field sync", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
const data = model.exportData();
expect(data.sheets[0].fieldSyncs["A1"]).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
const newModel = new Model(data, { custom: model.config.custom });
expect(getFieldSync(newModel, "A1")).toEqual(getFieldSync(model, "A1"));
});
test("can't add same field sync twice", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
const result = addFieldSync(model, "A1", "product_uom_qty", 0);
expect(result.isSuccessful).toBe(false);
});
test("can't delete field sync that doesn't exist", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
expect(deleteFieldSyncs(model, "A1").isSuccessful).toBe(false);
});
test("field sync is moved when column is added before", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addColumns(model, "before", "A", 1);
expect(getFieldSync(model, "A1")).toBe(undefined);
expect(getFieldSync(model, "B1")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
});
test("field sync is moved when row is added before", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addFieldSync(model, "A2", "product_uom_qty", 1);
addRows(model, "before", 0, 1);
expect(getFieldSync(model, "A1")).toBe(undefined);
expect(getFieldSync(model, "A2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "A3")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 1,
fieldName: "product_uom_qty",
});
});
test("field sync is deleted when column is removed", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
deleteColumns(model, ["A"]);
expect(getFieldSync(model, "A1")).toBe(undefined);
expect(model.getters.getAllFieldSyncs().size).toBe(0);
});
test("x2many commands when the cell is empty", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
expect(getCellContent(model, "A1")).toBe("");
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [],
errors: [],
});
});
test("x2many commands when the cell is a number", async () => {
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
setCellContent(model, "A1", "111");
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [
x2ManyCommands.update(42, {
product_uom_qty: 111,
}),
],
errors: [],
});
});
test("x2many commands with field sync position bigger than formula", async () => {
SaleOrderLine._records = [{ id: 42 }, { id: 43 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addFieldSync(model, "A2", "product_uom_qty", 1); // has a matching record but not loaded
addFieldSync(model, "A3", "product_uom_qty", 2); // doesn't have a matching record
setCellContent(model, "A1", "111");
setCellContent(model, "A2", "112");
setCellContent(model, "B1", '=ODOO.LIST(1, 1, "order_id")');
await animationFrame();
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [
x2ManyCommands.update(42, {
product_uom_qty: 111,
}),
x2ManyCommands.update(43, {
product_uom_qty: 112,
}),
],
errors: [],
});
});
test("load order lines list only once", async () => {
onRpc("web_search_read", () => {
expect.step("web_search_read");
});
SaleOrderLine._records = [{ id: 42 }, { id: 43 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addFieldSync(model, "A2", "product_uom_qty", 1);
setCellContent(model, "A1", "111");
setCellContent(model, "A2", "112");
setCellContent(model, "B1", '=ODOO.LIST(1, 1, "order_id")');
setCellContent(model, "B1", '=ODOO.LIST(1, 2, "order_id")');
await animationFrame();
expect.verifySteps(["web_search_read"]);
await model.getters.getFieldSyncX2ManyCommands();
expect.verifySteps([]);
// add a field sync beyond the loaded records
addFieldSync(model, "A3", "product_uom_qty", 2);
await model.getters.getFieldSyncX2ManyCommands();
expect.verifySteps(["web_search_read"]);
});
test("x2many commands on 2 fields", async () => {
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addFieldSync(model, "A2", "qty_delivered", 0);
setCellContent(model, "A1", "111");
setCellContent(model, "A2", "222");
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [
x2ManyCommands.update(42, {
product_uom_qty: 111,
qty_delivered: 222,
}),
],
errors: [],
});
});
test("x2many commands when the cell is an error", async () => {
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
setCellContent(model, "A1", "=1/0");
expect((await model.getters.getFieldSyncX2ManyCommands()).errors).toEqual([
'The value of A1 (#DIV/0!) can\'t be used for field "Product uom qty". It should be a number.',
]);
});
test("x2many commands text value on a numeric field", async () => {
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
setCellContent(model, "A1", "Hello");
expect((await model.getters.getFieldSyncX2ManyCommands()).errors).toEqual([
'The value of A1 (Hello) can\'t be used for field "Product uom qty". It should be a number.',
]);
});
test("x2many commands numeric value on a text field", async () => {
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "name", 0);
setCellContent(model, "A1", "30%");
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [
x2ManyCommands.update(42, {
name: "30%",
}),
],
errors: [],
});
});
test("x2many commands with not enough records in the list", async () => {
// only one record
SaleOrderLine._records = [{ id: 42 }];
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
setCellContent(model, "A1", "111");
// doesn't match any record in the list
addFieldSync(model, "A2", "product_uom_qty", 1);
setCellContent(model, "A2", "222");
expect(await model.getters.getFieldSyncX2ManyCommands()).toEqual({
commands: [
x2ManyCommands.update(42, {
product_uom_qty: 111,
}),
],
errors: [],
});
});
test("auto fill down increments position", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
autofill(model, "A1", "A3");
expect(getFieldSync(model, "A2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 1,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "A3")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 2,
fieldName: "product_uom_qty",
});
});
test("auto fill up decrements position", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A3", "product_uom_qty", 2);
autofill(model, "A3", "A1");
expect(getFieldSync(model, "A2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 1,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "A1")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
});
test("auto fill up stops at 0", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A3", "product_uom_qty", 1);
autofill(model, "A3", "A1");
expect(getFieldSync(model, "A2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "A1")).toBe(undefined);
});
test("auto fill right copies", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
autofill(model, "A1", "B1");
expect(getFieldSync(model, "B1")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
});
test("auto fill left copies", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
autofill(model, "B1", "A1");
expect(getFieldSync(model, "A1")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
});
test("copy-paste below", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
copy(model, "B1");
paste(model, "B2");
expect(getFieldSync(model, "B2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 1,
fieldName: "product_uom_qty",
});
});
test("copy-paste up", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B3", "product_uom_qty", 1);
copy(model, "B3");
paste(model, "B2");
paste(model, "B1");
expect(getFieldSync(model, "B2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 0,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "B1")).toBe(undefined);
});
test("copy-paste horizontally", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
copy(model, "B1");
paste(model, "A1");
paste(model, "C1");
const fieldSync = getFieldSync(model, "B1");
expect(getFieldSync(model, "A1")).toEqual(fieldSync);
expect(getFieldSync(model, "C1")).toEqual(fieldSync);
});
test("copy-paste horizontally and vertically", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
copy(model, "B1");
paste(model, "C2");
expect(getFieldSync(model, "C2")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 1,
fieldName: "product_uom_qty",
});
});
test("copy-paste zone", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
addFieldSync(model, "B2", "product_uom_qty", 1);
copy(model, "B1:B2");
paste(model, "B3");
expect(getFieldSync(model, "B3")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 2,
fieldName: "product_uom_qty",
});
expect(getFieldSync(model, "B4")).toEqual({
listId: model.getters.getMainSaleOrderLineList().id,
indexInList: 3,
fieldName: "product_uom_qty",
});
});
test("cut-paste", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "B1", "product_uom_qty", 0);
const originalFieldSync = getFieldSync(model, "B1");
cut(model, "B1");
paste(model, "B3");
expect(getFieldSync(model, "B3")).toBe(originalFieldSync);
expect(getFieldSync(model, "B1")).toBe(undefined);
});
test("can't delete main sale order line list", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
const result = model.dispatch("REMOVE_ODOO_LIST", {
listId: model.getters.getMainSaleOrderLineList().id,
});
expect(result.isSuccessful).toBe(false);
});
test("can't delete main sale order global filter", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
const [filter] = model.getters.getGlobalFilters();
const result = model.dispatch("REMOVE_GLOBAL_FILTER", { id: filter.id });
expect(result.isSuccessful).toBe(false);
});
test("duplicated field sync error", async () => {
const { model } = await createSaleOrderSpreadsheetModel();
addFieldSync(model, "A1", "product_uom_qty", 0);
addFieldSync(model, "A2", "product_uom_qty", 0);
expect((await model.getters.getFieldSyncX2ManyCommands()).errors).toEqual([]);
setCellContent(model, "A1", "111");
expect((await model.getters.getFieldSyncX2ManyCommands()).errors).toEqual([]);
setCellContent(model, "A2", "789");
expect((await model.getters.getFieldSyncX2ManyCommands()).errors).toEqual([
"Multiple cells are updating the same field of the same record! Unable to determine which one to choose: A1, A2",
]);
});