Files
enterprise-addons/web_enterprise/static/tests/webclient/home_menu.test.js
T

395 lines
11 KiB
JavaScript

import {
advanceTime,
animationFrame,
click,
describe,
drag,
expect,
mockDate,
mockTouch,
pointerDown,
press,
queryFirst,
test,
} from "@odoo/hoot";
import {
defineMenus,
getService,
mockService,
mountWebClient,
mountWithCleanup,
onRpc,
patchWithCleanup,
} from "@web/../tests/web_test_helpers";
import { session } from "@web/session";
import { reorderApps } from "@web/webclient/menus/menu_helpers";
import { HomeMenu } from "@web_enterprise/webclient/home_menu/home_menu";
import { WebClientEnterprise } from "@web_enterprise/webclient/webclient";
/**
* @param {Iterable<{
* index?: number;
* key: import("@odoo/hoot").KeyStrokes;
* shiftKey?: boolean;
* }>} steps
*/
async function walkOn(steps) {
for (const step of steps) {
await press(step.key);
await animationFrame();
expect(`.o_menuitem:eq(${step.index || 0})`).toHaveClass("o_focused", {
message: `step ${JSON.stringify(step)}`,
});
}
}
const getDefaultHomeMenuProps = () => {
const apps = [
{
actionID: 121,
href: "/odoo/action-121",
appID: 1,
id: 1,
label: "Discuss",
parents: "",
webIcon: false,
xmlid: "app.1",
},
{
actionID: 122,
href: "/odoo/action-122",
appID: 2,
id: 2,
label: "Calendar",
parents: "",
webIcon: false,
xmlid: "app.2",
},
{
actionID: 123,
href: "/odoo/contacts",
appID: 3,
id: 3,
label: "Contacts",
parents: "",
webIcon: false,
xmlid: "app.3",
},
];
return { apps, reorderApps: (order) => reorderApps(apps, order) };
};
describe.current.tags("desktop");
test("ESC Support", async () => {
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
mockService("home_menu", {
async toggle(show) {
expect.step(`toggle ${show}`);
},
});
await press("escape");
expect.verifySteps(["toggle false"]);
});
test("Click on an app", async () => {
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
mockService("menu", {
async selectMenu(menu) {
expect.step(`selectMenu ${menu.id}`);
},
});
await click(".o_menuitem:eq(0)");
await animationFrame();
expect.verifySteps(["selectMenu 1"]);
});
test("Display Expiration Panel (no module installed)", async () => {
mockDate("2019-10-09T00:00:00");
patchWithCleanup(session, {
expiration_date: "2019-11-01 12:00:00",
expiration_reason: "",
isMailInstalled: false,
warning: "admin",
});
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
expect(".database_expiration_panel").toHaveCount(1);
expect(".database_expiration_panel .oe_instance_register").toHaveText(
"You will be able to register your database once you have installed your first app.",
{ message: "There should be an expiration panel displayed" }
);
// Close the expiration panel
await click(".database_expiration_panel .oe_instance_hide_panel");
await animationFrame();
expect(".database_expiration_panel").toHaveCount(0);
});
test("Navigation (only apps, only one line)", async () => {
expect.assertions(8);
const homeMenuProps = {
apps: new Array(3).fill().map((x, i) => ({
actionID: 120 + i,
href: "/odoo/act" + (120 + i),
appID: i + 1,
id: i + 1,
label: `0${i}`,
parents: "",
webIcon: false,
xmlid: `app.${i}`,
})),
reorderApps: (order) => reorderApps(homeMenuProps.apps, order),
};
await mountWithCleanup(HomeMenu, {
props: homeMenuProps,
});
await walkOn([
{ key: "ArrowDown", index: 0 },
{ key: "ArrowRight", index: 1 },
{ key: "Tab", index: 2 },
{ key: "ArrowRight", index: 0 },
{ key: ["Shift", "Tab"], index: 2 },
{ key: "ArrowLeft", index: 1 },
{ key: "ArrowDown", index: 1 },
{ key: "ArrowUp", index: 1 },
]);
});
test("Navigation (only apps, two lines, one incomplete)", async () => {
expect.assertions(19);
const homeMenuProps = {
apps: new Array(8).fill().map((x, i) => ({
actionID: 121,
href: "/odoo/action-121",
appID: i + 1,
id: i + 1,
label: `0${i}`,
parents: "",
webIcon: false,
xmlid: `app.${i}`,
})),
reorderApps: (order) => reorderApps(homeMenuProps.apps, order),
};
await mountWithCleanup(HomeMenu, {
props: homeMenuProps,
});
await walkOn([
{ key: "ArrowRight", index: 0 },
{ key: "ArrowUp", index: 6 },
{ key: "ArrowUp", index: 0 },
{ key: "ArrowDown", index: 6 },
{ key: "ArrowDown", index: 0 },
{ key: "ArrowRight", index: 1 },
{ key: "ArrowRight", index: 2 },
{ key: "ArrowUp", index: 7 },
{ key: "ArrowUp", index: 1 },
{ key: "ArrowRight", index: 2 },
{ key: "ArrowDown", index: 7 },
{ key: "ArrowDown", index: 1 },
{ key: "ArrowUp", index: 7 },
{ key: "ArrowRight", index: 6 },
{ key: "ArrowLeft", index: 7 },
{ key: "ArrowUp", index: 1 },
{ key: "ArrowLeft", index: 0 },
{ key: "ArrowLeft", index: 5 },
{ key: "ArrowRight", index: 0 },
]);
});
test("Navigation and open an app in the home menu", async () => {
expect.assertions(6);
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
mockService("menu", {
async selectMenu(menu) {
expect.step(`selectMenu ${menu.id}`);
},
});
// No app selected so nothing to open
await press("enter");
expect.verifySteps([]);
await walkOn([
{ key: "ArrowDown", index: 0 },
{ key: "ArrowRight", index: 1 },
{ key: "Tab", index: 2 },
{ key: "shift+Tab", index: 1 },
]);
// open first app (Calendar)
await press("enter");
expect.verifySteps(["selectMenu 2"]);
});
test("Reorder apps in home menu using drag and drop", async () => {
const apps = [];
for (let i = 0; i < 8; i++) {
apps.push({
actionID: 121,
href: "/odoo/action-121",
appID: i + 1,
id: i + 1,
label: `0${i}`,
parents: "",
webIcon: false,
xmlid: `app.${i}`,
});
}
defineMenus(apps);
onRpc("set_res_users_settings", () => {
expect.step(`set_res_users_settings`);
return {
id: 1,
homemenu_config: '["app.1","app.2","app.3","app.0","app.4","app.5","app.6","app.7"]',
};
});
await mountWebClient({ WebClient: WebClientEnterprise });
const { moveTo, drop } = await drag(".o_draggable:first-child");
await advanceTime(250);
expect(".o_draggable:first-child a").not.toHaveClass("o_dragged_app");
await advanceTime(250);
expect(".o_draggable:first-child a").toHaveClass("o_dragged_app");
await moveTo(".o_draggable:first-child", {
position: {
x: 70,
y: 35,
},
relative: true,
});
await drop(".o_draggable:not(.o_dragged):eq(3)");
await animationFrame();
expect.verifySteps(["set_res_users_settings"]);
expect(".o_app:eq(0)").toHaveAttribute("data-menu-xmlid", "app.1", {
message: "first displayed app has app.1 xmlid",
});
expect(".o_app:eq(3)").toHaveAttribute("data-menu-xmlid", "app.0", {
message: "app 0 is now at 4th position",
});
});
test("The HomeMenu input takes the focus when you press a key only if no other element is the activeElement", async () => {
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
expect(".o_search_hidden").toBeFocused();
const activeElement = document.createElement("div");
getService("ui").activateElement(activeElement);
// remove the focus from the input
const otherInput = document.createElement("input");
queryFirst(".o_home_menu").appendChild(otherInput);
await pointerDown(otherInput);
await pointerDown(document.body);
expect(document.body).toBeFocused();
expect(".o_command_palette_search input").not.toHaveCount();
await press("a");
await animationFrame();
expect(document.body).toBeFocused();
expect(".o_command_palette_search input").not.toHaveCount();
getService("ui").deactivateElement(activeElement);
await press("a");
await animationFrame();
expect(".o_command_palette_search input").toBeFocused();
});
test("The HomeMenu input does not take the focus if it is already on another input", async () => {
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
expect(".o_search_hidden").toBeFocused();
const otherInput = document.createElement("input");
queryFirst(".o_home_menu").appendChild(otherInput);
await pointerDown(otherInput);
await press("a");
await animationFrame();
expect(otherInput).toBeFocused();
expect(".o_command_palette_search input").not.toHaveCount();
otherInput.remove();
await press("a");
await animationFrame();
expect(".o_command_palette_search input").toBeFocused();
});
test("The HomeMenu input does not take the focus if it is already on a textarea", async () => {
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
expect(".o_search_hidden").toBeFocused();
const textarea = document.createElement("textarea");
queryFirst(".o_home_menu").appendChild(textarea);
await pointerDown(textarea);
await press("a");
await animationFrame();
expect(textarea).toBeFocused();
expect(".o_command_palette_search input").not.toHaveCount();
textarea.remove();
await press("a");
await animationFrame();
expect(".o_command_palette_search input").toBeFocused();
});
test("home search input shouldn't be focused on touch devices", async () => {
mockTouch(true);
await mountWithCleanup(HomeMenu, {
props: getDefaultHomeMenuProps(),
});
expect(".o_search_hidden").not.toBeFocused({
message: "home menu search input shouldn't have the focus",
});
});
test("home keynav not triggering when navigating a dropdown", async () => {
const apps = [];
for (let i = 0; i < 8; i++) {
apps.push({
actionID: 121,
href: "/odoo/action-121",
appID: i + 1,
id: i + 1,
label: `0${i}`,
parents: "",
webIcon: false,
xmlid: `app.${i}`,
});
}
defineMenus(apps);
await mountWebClient({ WebClient: WebClientEnterprise });
await click(".o_user_menu .o-dropdown");
await animationFrame();
await press("arrowdown");
await animationFrame();
expect(".o-dropdown-item.focus").toHaveCount(1);
await press("arrowleft");
await animationFrame();
expect(".o-dropdown-item.focus").toHaveCount(1);
expect(".o_app.o_focused").toHaveCount(0);
});