270 lines
13 KiB
JavaScript
270 lines
13 KiB
JavaScript
import { describe, expect, test } from "@odoo/hoot";
|
|
|
|
import { getFirstListFunction, getNumberOfListFormulas } from "@spreadsheet/list/list_helpers";
|
|
import { constants, tokenize, helpers } from "@odoo/o-spreadsheet";
|
|
import { patchTranslations } from "@web/../tests/web_test_helpers";
|
|
const {
|
|
getFirstPivotFunction,
|
|
getNumberOfPivotFunctions,
|
|
pivotTimeAdapter,
|
|
toNormalizedPivotValue,
|
|
toNumber,
|
|
} = helpers;
|
|
const { DEFAULT_LOCALE } = constants;
|
|
|
|
function stringArg(value) {
|
|
return { type: "STRING", value: `${value}` };
|
|
}
|
|
|
|
describe.current.tags("headless");
|
|
|
|
describe("pivot_helpers", () => {
|
|
test("Basic formula extractor", async function () {
|
|
const formula = `=PIVOT.VALUE("1", "test") + ODOO.LIST("2", "hello", "bla")`;
|
|
const tokens = tokenize(formula);
|
|
let functionName;
|
|
let args;
|
|
({ functionName, args } = getFirstPivotFunction(tokens));
|
|
expect(functionName).toBe("PIVOT.VALUE");
|
|
expect(args.length).toBe(2);
|
|
expect(args[0]).toEqual(stringArg("1"));
|
|
expect(args[1]).toEqual(stringArg("test"));
|
|
({ functionName, args } = getFirstListFunction(tokens));
|
|
expect(functionName).toBe("ODOO.LIST");
|
|
expect(args.length).toBe(3);
|
|
expect(args[0]).toEqual(stringArg("2"));
|
|
expect(args[1]).toEqual(stringArg("hello"));
|
|
expect(args[2]).toEqual(stringArg("bla"));
|
|
});
|
|
|
|
test("Extraction with two PIVOT formulas", async function () {
|
|
const formula = `=PIVOT.VALUE("1", "test") + PIVOT.VALUE("2", "hello", "bla")`;
|
|
const tokens = tokenize(formula);
|
|
const { functionName, args } = getFirstPivotFunction(tokens);
|
|
expect(functionName).toBe("PIVOT.VALUE");
|
|
expect(args.length).toBe(2);
|
|
expect(args[0]).toEqual(stringArg("1"));
|
|
expect(args[1]).toEqual(stringArg("test"));
|
|
expect(getFirstListFunction(tokens)).toBe(undefined);
|
|
});
|
|
|
|
test("Number of formulas", async function () {
|
|
const formula = `=PIVOT.VALUE("1", "test") + PIVOT.VALUE("2", "hello", "bla") + ODOO.LIST("1", "bla")`;
|
|
expect(getNumberOfPivotFunctions(tokenize(formula))).toBe(2);
|
|
expect(getNumberOfListFormulas(tokenize(formula))).toBe(1);
|
|
expect(getNumberOfPivotFunctions(tokenize("=1+1"))).toBe(0);
|
|
expect(getNumberOfListFormulas(tokenize("=1+1"))).toBe(0);
|
|
expect(getNumberOfPivotFunctions(tokenize("=bla"))).toBe(0);
|
|
expect(getNumberOfListFormulas(tokenize("=bla"))).toBe(0);
|
|
});
|
|
|
|
test("getFirstPivotFunction does not crash when given crap", async function () {
|
|
expect(getFirstListFunction(tokenize("=SUM(A1)"))).toBe(undefined);
|
|
expect(getFirstPivotFunction(tokenize("=SUM(A1)"))).toBe(undefined);
|
|
expect(getFirstListFunction(tokenize("=1+1"))).toBe(undefined);
|
|
expect(getFirstPivotFunction(tokenize("=1+1"))).toBe(undefined);
|
|
expect(getFirstListFunction(tokenize("=bla"))).toBe(undefined);
|
|
expect(getFirstPivotFunction(tokenize("=bla"))).toBe(undefined);
|
|
expect(getFirstListFunction(tokenize("bla"))).toBe(undefined);
|
|
expect(getFirstPivotFunction(tokenize("bla"))).toBe(undefined);
|
|
});
|
|
});
|
|
|
|
describe("toNormalizedPivotValue", () => {
|
|
test("parse values of a selection, char or text field", () => {
|
|
for (const fieldType of ["selection", "text", "char"]) {
|
|
const dimension = {
|
|
type: fieldType,
|
|
displayName: "A field",
|
|
name: "my_field_name",
|
|
};
|
|
expect(toNormalizedPivotValue(dimension, "won")).toBe("won");
|
|
expect(toNormalizedPivotValue(dimension, "1")).toBe("1");
|
|
expect(toNormalizedPivotValue(dimension, 1)).toBe("1");
|
|
expect(toNormalizedPivotValue(dimension, "11/2020")).toBe("11/2020");
|
|
expect(toNormalizedPivotValue(dimension, "2020")).toBe("2020");
|
|
expect(toNormalizedPivotValue(dimension, "01/11/2020")).toBe("01/11/2020");
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, "true")).toBe("true");
|
|
}
|
|
});
|
|
|
|
test("parse values of time fields", () => {
|
|
for (const fieldType of ["date", "datetime"]) {
|
|
const dimension = {
|
|
type: fieldType,
|
|
displayName: "A field",
|
|
name: "my_field_name",
|
|
};
|
|
|
|
dimension.granularity = "day";
|
|
expect(toNormalizedPivotValue(dimension, "1/11/2020")).toBe(43841);
|
|
expect(toNormalizedPivotValue(dimension, "01/11/2020")).toBe(43841);
|
|
expect(toNormalizedPivotValue(dimension, "11/2020")).toBe(44136);
|
|
expect(toNormalizedPivotValue(dimension, "1")).toBe(1);
|
|
expect(toNormalizedPivotValue(dimension, 1)).toBe(1);
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
|
|
dimension.granularity = "week";
|
|
expect(toNormalizedPivotValue(dimension, "11/2020")).toBe("11/2020");
|
|
expect(toNormalizedPivotValue(dimension, "1/2020")).toBe("1/2020");
|
|
expect(toNormalizedPivotValue(dimension, "01/2020")).toBe("1/2020");
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
|
|
dimension.granularity = "month";
|
|
expect(toNormalizedPivotValue(dimension, "11/2020")).toBe("11/2020");
|
|
expect(toNormalizedPivotValue(dimension, "1/2020")).toBe("01/2020");
|
|
expect(toNormalizedPivotValue(dimension, "01/2020")).toBe("01/2020");
|
|
expect(toNormalizedPivotValue(dimension, "2/11/2020")).toBe("02/2020");
|
|
expect(toNormalizedPivotValue(dimension, "2/1/2020")).toBe("02/2020");
|
|
expect(toNormalizedPivotValue(dimension, 1)).toBe("12/1899");
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
expect(() => toNormalizedPivotValue(dimension, "true")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, true)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "won")).toThrow();
|
|
|
|
dimension.granularity = "quarter";
|
|
// special quarter syntax:
|
|
expect(toNormalizedPivotValue(dimension, "1/2020")).toBe("1/2020");
|
|
expect(toNormalizedPivotValue(dimension, "2/2020")).toBe("2/2020");
|
|
expect(toNormalizedPivotValue(dimension, "3/2020")).toBe("3/2020");
|
|
expect(toNormalizedPivotValue(dimension, "4/2020")).toBe("4/2020");
|
|
|
|
// falls back on regular date parsing:
|
|
expect(toNormalizedPivotValue(dimension, "5/2020")).toBe("2/2020");
|
|
expect(toNormalizedPivotValue(dimension, "01/01/2020")).toBe("1/2020");
|
|
expect(toNormalizedPivotValue(dimension, toNumber("01/01/2020", DEFAULT_LOCALE))).toBe(
|
|
"1/2020"
|
|
);
|
|
expect(() => toNormalizedPivotValue(dimension, "hello")).toThrow();
|
|
|
|
dimension.granularity = "year";
|
|
expect(toNormalizedPivotValue(dimension, "2020")).toBe(2020);
|
|
expect(toNormalizedPivotValue(dimension, 2020)).toBe(2020);
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
}
|
|
});
|
|
|
|
test("parse values of boolean field", () => {
|
|
const dimension = {
|
|
type: "boolean",
|
|
displayName: "A field",
|
|
name: "my_field_name",
|
|
};
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, "true")).toBe(true);
|
|
expect(toNormalizedPivotValue(dimension, true)).toBe(true);
|
|
expect(() => toNormalizedPivotValue(dimension, "11/2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "01/11/2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "1")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, 1)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "won")).toThrow();
|
|
});
|
|
|
|
test("parse values of numeric fields", () => {
|
|
for (const fieldType of ["float", "integer", "monetary", "many2one", "many2many"]) {
|
|
const dimension = {
|
|
type: fieldType,
|
|
displayName: "A field",
|
|
name: "my_field_name",
|
|
};
|
|
expect(toNormalizedPivotValue(dimension, "2020")).toBe(2020);
|
|
expect(toNormalizedPivotValue(dimension, "01/11/2020")).toBe(43841); // a date is actually a number in a spreadsheet
|
|
expect(toNormalizedPivotValue(dimension, "11/2020")).toBe(44136); // 1st of november 2020
|
|
expect(toNormalizedPivotValue(dimension, "1")).toBe(1);
|
|
expect(toNormalizedPivotValue(dimension, 1)).toBe(1);
|
|
expect(toNormalizedPivotValue(dimension, "false")).toBe(false);
|
|
expect(toNormalizedPivotValue(dimension, false)).toBe(false);
|
|
expect(() => toNormalizedPivotValue(dimension, "true")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, true)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "won")).toThrow();
|
|
}
|
|
});
|
|
|
|
test("parse values of unsupported fields", () => {
|
|
for (const fieldType of ["one2many", "binary", "html"]) {
|
|
const dimension = {
|
|
type: fieldType,
|
|
displayName: "A field",
|
|
name: "my_field_name",
|
|
};
|
|
expect(() => toNormalizedPivotValue(dimension, "false")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, false)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "true")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, true)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "11/2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "01/11/2020")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "1")).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, 1)).toThrow();
|
|
expect(() => toNormalizedPivotValue(dimension, "won")).toThrow();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("pivot time adapters formatted value", () => {
|
|
test("Day adapter", () => {
|
|
const adapter = pivotTimeAdapter("day");
|
|
expect(adapter.toValueAndFormat("11/12/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 44147,
|
|
format: "dd mmm yyyy",
|
|
});
|
|
expect(adapter.toValueAndFormat("01/11/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 43841,
|
|
format: "dd mmm yyyy",
|
|
});
|
|
expect(adapter.toValueAndFormat("12/05/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 44170,
|
|
format: "dd mmm yyyy",
|
|
});
|
|
});
|
|
|
|
test("Week adapter", () => {
|
|
patchTranslations();
|
|
const adapter = pivotTimeAdapter("week");
|
|
expect(adapter.toValueAndFormat("5/2024", DEFAULT_LOCALE)).toEqual({ value: "W5 2024" });
|
|
expect(adapter.toValueAndFormat("51/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: "W51 2020",
|
|
});
|
|
});
|
|
|
|
test("Month adapter", () => {
|
|
patchTranslations();
|
|
const adapter = pivotTimeAdapter("month");
|
|
expect(adapter.toValueAndFormat("12/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 44166,
|
|
format: "mmmm yyyy",
|
|
});
|
|
expect(adapter.toValueAndFormat("02/2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 43862,
|
|
format: "mmmm yyyy",
|
|
});
|
|
});
|
|
|
|
test("Quarter adapter", () => {
|
|
patchTranslations();
|
|
const adapter = pivotTimeAdapter("quarter");
|
|
expect(adapter.toValueAndFormat("1/2022", DEFAULT_LOCALE)).toEqual({ value: "Q1 2022" });
|
|
expect(adapter.toValueAndFormat("3/1998", DEFAULT_LOCALE)).toEqual({ value: "Q3 1998" });
|
|
});
|
|
|
|
test("Year adapter", () => {
|
|
const adapter = pivotTimeAdapter("year");
|
|
expect(adapter.toValueAndFormat("2020", DEFAULT_LOCALE)).toEqual({
|
|
value: 2020,
|
|
format: "0",
|
|
});
|
|
expect(adapter.toValueAndFormat("1997", DEFAULT_LOCALE)).toEqual({
|
|
value: 1997,
|
|
format: "0",
|
|
});
|
|
});
|
|
});
|