395 lines
11 KiB
JavaScript
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);
|
|
});
|