mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[MIG] web_timeline: Migration to 17.0
- Convert Moment.js to Luxon. - Replace Underscore.js with native JavaScript code. - Migrate legacy views to the new system and add an architecture parser to separate logic. - added basic test
This commit is contained in:
8
web_timeline/static/tests/helpers.esm.js
Normal file
8
web_timeline/static/tests/helpers.esm.js
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
export const FAKE_ORDER_FIELDS = {
|
||||
display_name: {string: "Display Name", type: "char"},
|
||||
date_start: {string: "Date start", type: "date"},
|
||||
date_end: {string: "Date end", type: "date"},
|
||||
partner_id: {string: "Partner", type: "many2one", relation: "partner"},
|
||||
};
|
||||
141
web_timeline/static/tests/web_timeline_arch_parser_tests.esm.js
Normal file
141
web_timeline/static/tests/web_timeline_arch_parser_tests.esm.js
Normal file
@@ -0,0 +1,141 @@
|
||||
/** @odoo-module **/
|
||||
import {
|
||||
TimelineArchParser,
|
||||
TimelineParseArchError,
|
||||
} from "@web_timeline/views/timeline/timeline_arch_parser.esm";
|
||||
import {FAKE_ORDER_FIELDS} from "./helpers.esm";
|
||||
import {parseXML} from "@web/core/utils/xml";
|
||||
|
||||
function parseArch(arch) {
|
||||
const parser = new TimelineArchParser();
|
||||
const xmlDoc = parseXML(arch);
|
||||
return parser.parse(xmlDoc, FAKE_ORDER_FIELDS);
|
||||
}
|
||||
|
||||
function check(assert, paramName, paramValue, expectedName, expectedValue) {
|
||||
const arch = `<timeline date_start="start_date" default_group_by="partner_id" ${paramName}="${paramValue}" />`;
|
||||
const data = parseArch(arch);
|
||||
assert.strictEqual(data[expectedName], expectedValue);
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.module("TimelineView - ArchParser");
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("throw if date_start is not set", (assert) => {
|
||||
assert.throws(
|
||||
() => parseArch(`<timeline default_group_by="partner_id"/>`),
|
||||
TimelineParseArchError
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("throw if default_group_by is not set", (assert) => {
|
||||
assert.throws(
|
||||
() => parseArch(`<timeline date_start="date_start"/>`),
|
||||
TimelineParseArchError
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("hasEditDialog", (assert) => {
|
||||
check(assert, "event_open_popup", "", "open_popup_action", false);
|
||||
check(assert, "event_open_popup", "true", "open_popup_action", true);
|
||||
check(assert, "event_open_popup", "True", "open_popup_action", true);
|
||||
check(assert, "event_open_popup", "1", "open_popup_action", true);
|
||||
check(assert, "event_open_popup", "false", "open_popup_action", false);
|
||||
check(assert, "event_open_popup", "False", "open_popup_action", false);
|
||||
check(assert, "event_open_popup", "0", "open_popup_action", false);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("create", (assert) => {
|
||||
check(assert, "create", "", "canCreate", true);
|
||||
check(assert, "create", "true", "canCreate", true);
|
||||
check(assert, "create", "True", "canCreate", true);
|
||||
check(assert, "create", "1", "canCreate", true);
|
||||
check(assert, "create", "false", "canCreate", false);
|
||||
check(assert, "create", "False", "canCreate", false);
|
||||
check(assert, "create", "0", "canCreate", false);
|
||||
check(assert, "create", "12", "canCreate", true);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("edit", (assert) => {
|
||||
check(assert, "edit", "", "canUpdate", true);
|
||||
check(assert, "edit", "true", "canUpdate", true);
|
||||
check(assert, "edit", "True", "canUpdate", true);
|
||||
check(assert, "edit", "1", "canUpdate", true);
|
||||
check(assert, "edit", "false", "canUpdate", false);
|
||||
check(assert, "edit", "False", "canUpdate", false);
|
||||
check(assert, "edit", "0", "canUpdate", false);
|
||||
check(assert, "edit", "12", "canUpdate", true);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("delete", (assert) => {
|
||||
check(assert, "delete", "", "canDelete", true);
|
||||
check(assert, "delete", "true", "canDelete", true);
|
||||
check(assert, "delete", "True", "canDelete", true);
|
||||
check(assert, "delete", "1", "canDelete", true);
|
||||
check(assert, "delete", "false", "canDelete", false);
|
||||
check(assert, "delete", "False", "canDelete", false);
|
||||
check(assert, "delete", "0", "canDelete", false);
|
||||
check(assert, "delete", "12", "canDelete", true);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("mode", (assert) => {
|
||||
check(assert, "mode", "day", "mode", "day");
|
||||
check(assert, "mode", "week", "mode", "week");
|
||||
check(assert, "mode", "month", "mode", "month");
|
||||
assert.throws(() => {
|
||||
parseArch(
|
||||
`<timeline date_start="start_date" default_group_by="partner_id" mode="other" />`
|
||||
);
|
||||
}, TimelineParseArchError);
|
||||
|
||||
assert.throws(() => {
|
||||
parseArch(
|
||||
`<timeline date_start="start_date" default_group_by="partner_id" mode="" />`
|
||||
);
|
||||
}, TimelineParseArchError);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("colors", (assert) => {
|
||||
const archInfo = parseArch(`
|
||||
<timeline date_start="start_date" default_group_by="partner_id" colors="gray: state == 'cancel'; #ec7063: state == 'done'"/>
|
||||
`);
|
||||
assert.strictEqual(archInfo.colors.length, 2, "colors should be 2");
|
||||
assert.strictEqual(archInfo.colors[0].field, "state", "field should be state");
|
||||
assert.strictEqual(archInfo.colors[0].color, "gray", "color should be gray");
|
||||
assert.strictEqual(
|
||||
archInfo.colors[0].ast.left.value,
|
||||
"state",
|
||||
"ast left value should be state"
|
||||
);
|
||||
assert.strictEqual(archInfo.colors[0].ast.op, "==", "ast op value should be '=='");
|
||||
assert.strictEqual(
|
||||
archInfo.colors[0].ast.right.value,
|
||||
"cancel",
|
||||
"ast right value should be cancel"
|
||||
);
|
||||
assert.ok(
|
||||
archInfo.fieldNames.includes("state"),
|
||||
"fieldNames should include field state"
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("templates", (assert) => {
|
||||
const archInfo = parseArch(`
|
||||
<timeline date_start="start_date" default_group_by="partner_id">
|
||||
<field name="other_field" />
|
||||
<templates>
|
||||
<t t-name="timeline-item">
|
||||
<span t-out="record.other_field" />
|
||||
</t>
|
||||
</templates>
|
||||
</timeline>
|
||||
`);
|
||||
assert.ok(
|
||||
archInfo.templateDocs.hasOwnProperty("timeline-item"),
|
||||
"template name should be timeline-item"
|
||||
);
|
||||
assert.ok(
|
||||
archInfo.fieldNames.includes("other_field"),
|
||||
"fieldNames should include field other_field"
|
||||
);
|
||||
});
|
||||
194
web_timeline/static/tests/web_timeline_view_tests.esm.js
Normal file
194
web_timeline/static/tests/web_timeline_view_tests.esm.js
Normal file
@@ -0,0 +1,194 @@
|
||||
/** @odoo-module **/
|
||||
import {click, getFixture} from "@web/../tests/helpers/utils";
|
||||
import {makeView, setupViewRegistries} from "@web/../tests/views/helpers";
|
||||
import {FAKE_ORDER_FIELDS} from "./helpers.esm";
|
||||
import {loadBundle} from "@web/core/assets";
|
||||
|
||||
let serverData = {};
|
||||
let target = null;
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.module("Views", (hooks) => {
|
||||
loadBundle("web_timeline.vis-timeline_lib");
|
||||
hooks.beforeEach(async () => {
|
||||
serverData = {
|
||||
models: {
|
||||
partner: {
|
||||
fields: {
|
||||
name: {string: "Name", type: "char"},
|
||||
},
|
||||
records: [
|
||||
{id: 1, name: "Partner 1"},
|
||||
{id: 2, name: "Partner 2"},
|
||||
{id: 3, name: "Partner 3"},
|
||||
],
|
||||
},
|
||||
order: {
|
||||
fields: FAKE_ORDER_FIELDS,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
display_name: "Record 1",
|
||||
date_start: "2024-01-01",
|
||||
date_end: "2024-01-02",
|
||||
partner_id: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
display_name: "Record 2",
|
||||
date_start: "2024-01-03",
|
||||
date_end: "2024-02-05",
|
||||
partner_id: 1,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
display_name: "Record 3",
|
||||
date_start: "2024-01-10",
|
||||
date_end: "2024-01-15",
|
||||
partner_id: 2,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
display_name: "Record 4",
|
||||
date_start: "2024-01-15",
|
||||
date_end: "2024-02-01",
|
||||
partner_id: 3,
|
||||
},
|
||||
],
|
||||
methods: {
|
||||
check_access_rights() {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
setupViewRegistries();
|
||||
target = getFixture();
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.module("TimelineView - View");
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("Test basic timeline view", async (assert) => {
|
||||
await makeView({
|
||||
type: "timeline",
|
||||
resModel: "order",
|
||||
serverData,
|
||||
arch: '<timeline date_start="date_start" date_stop="date_stop" default_group_by="partner_id"/>',
|
||||
});
|
||||
assert.containsOnce(target, ".oe_timeline_view");
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("click today slot", async (assert) => {
|
||||
await makeView({
|
||||
type: "timeline",
|
||||
resModel: "order",
|
||||
serverData,
|
||||
arch: '<timeline date_start="date_start" date_stop="date_stop" default_group_by="partner_id"/>',
|
||||
});
|
||||
const $today = target.querySelector(".oe_timeline_button_today");
|
||||
const $day = target.querySelector(".oe_timeline_button_scale_day");
|
||||
const $week = target.querySelector(".oe_timeline_button_scale_week");
|
||||
const $month = target.querySelector(".oe_timeline_button_scale_month");
|
||||
const $year = target.querySelector(".oe_timeline_button_scale_year");
|
||||
await click($today);
|
||||
assert.hasClass(
|
||||
$today,
|
||||
"btn-primary",
|
||||
"today should have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$day,
|
||||
"btn-primary",
|
||||
"day should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$week,
|
||||
"btn-primary",
|
||||
"week should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$month,
|
||||
"btn-primary",
|
||||
"month should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$year,
|
||||
"btn-primary",
|
||||
"year should no have classnames btn-primary"
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("click month slot", async (assert) => {
|
||||
await makeView({
|
||||
type: "timeline",
|
||||
resModel: "order",
|
||||
serverData,
|
||||
arch: '<timeline date_start="date_start" date_stop="date_stop" default_group_by="partner_id"/>',
|
||||
});
|
||||
const $today = target.querySelector(".oe_timeline_button_today");
|
||||
const $day = target.querySelector(".oe_timeline_button_scale_day");
|
||||
const $week = target.querySelector(".oe_timeline_button_scale_week");
|
||||
const $month = target.querySelector(".oe_timeline_button_scale_month");
|
||||
const $year = target.querySelector(".oe_timeline_button_scale_year");
|
||||
await click($month);
|
||||
assert.hasClass(
|
||||
$month,
|
||||
"btn-primary",
|
||||
"month should have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$today,
|
||||
"btn-primary",
|
||||
"today should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$day,
|
||||
"btn-primary",
|
||||
"day should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$week,
|
||||
"btn-primary",
|
||||
"week should no have classnames btn-primary"
|
||||
);
|
||||
assert.doesNotHaveClass(
|
||||
$year,
|
||||
"btn-primary",
|
||||
"year should no have classnames btn-primary"
|
||||
);
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("Check button delete", async (assert) => {
|
||||
await makeView({
|
||||
type: "timeline",
|
||||
resModel: "order",
|
||||
serverData,
|
||||
arch: '<timeline date_start="date_start" date_stop="date_stop" default_group_by="partner_id"/>',
|
||||
});
|
||||
const $elements = [...target.querySelectorAll(".vis-item-content")];
|
||||
const $item_contents = $elements.filter((el) =>
|
||||
el.textContent.includes("Record 2")
|
||||
);
|
||||
assert.strictEqual($item_contents.length, 1, "items should be 1");
|
||||
const $item_content = $item_contents[0];
|
||||
await click($item_content);
|
||||
assert.containsOnce($item_content.parentElement, ".vis-delete");
|
||||
});
|
||||
// eslint-disable-next-line no-undef
|
||||
QUnit.test("Check button delete disabled", async (assert) => {
|
||||
await makeView({
|
||||
type: "timeline",
|
||||
resModel: "order",
|
||||
serverData,
|
||||
arch: '<timeline date_start="date_start" date_stop="date_stop" default_group_by="partner_id" delete="0"/>',
|
||||
});
|
||||
const $elements = [...target.querySelectorAll(".vis-item-content")];
|
||||
const $item_contents = $elements.filter((el) =>
|
||||
el.textContent.includes("Record 2")
|
||||
);
|
||||
assert.strictEqual($item_contents.length, 1, "items should be 1");
|
||||
const $item_content = $item_contents[0];
|
||||
await click($item_content);
|
||||
assert.containsNone($item_content.parentElement, ".vis-delete");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user