vanilla 18.0

This commit is contained in:
Ernad Husremovic 2025-10-08 10:48:09 +02:00
parent 5454004ff9
commit d7f6d2725e
979 changed files with 428093 additions and 0 deletions

View file

@ -0,0 +1,193 @@
import { beforeEach, describe, expect, test } from "@odoo/hoot";
import { click, queryAll } from "@odoo/hoot-dom";
import { animationFrame } from "@odoo/hoot-mock";
import {
contains,
defineActions,
defineMenus,
getService,
mountWithCleanup,
patchWithCleanup,
useTestClientAction,
} from "@web/../tests/web_test_helpers";
import { config as transitionConfig } from "@web/core/transition";
import { WebClient } from "@web/webclient/webclient";
import { registry } from "@web/core/registry";
describe.current.tags("mobile");
beforeEach(() => {
const testAction = useTestClientAction();
defineActions([
{ ...testAction, id: 1001, params: { description: "Id 1" } },
{ ...testAction, id: 1002, params: { description: "Info" } },
{ ...testAction, id: 1003, params: { description: "Report" } },
]);
defineMenus([
{ id: 0 }, // prevents auto-loading the first action
{ id: 1, name: "App1", actionID: 1001, xmlid: "menu_1" },
]);
patchWithCleanup(transitionConfig, { disabled: true });
});
test("Burger menu can be opened and closed", async () => {
await mountWithCleanup(WebClient);
await contains(".o_mobile_menu_toggle", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(1);
await contains(".o_sidebar_close", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(0);
});
test("Burger Menu on an App", async () => {
defineMenus([
{
id: 1,
children: [
{
id: 99,
name: "SubMenu",
appID: 1,
actionID: 1002,
xmlid: "",
webIconData: undefined,
webIcon: false,
},
],
},
]);
await mountWithCleanup(WebClient);
await contains("a.o_menu_toggle", { root: document.body }).click();
await contains(".o_sidebar_topbar a.btn-primary", { root: document.body }).click();
await contains(".o_burger_menu_content li:nth-of-type(2)", { root: document.body }).click();
expect(queryAll(".o_burger_menu_content", { root: document.body })).toHaveCount(0);
await contains("a.o_menu_toggle", { root: document.body }).click();
expect(
queryAll(".o_app_menu_sidebar nav.o_burger_menu_content", { root: document.body })
).toHaveText("App1\nSubMenu");
await click(".modal-backdrop", { root: document.body });
await contains(".o_mobile_menu_toggle", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(1);
expect(
queryAll(".o_burger_menu nav.o_burger_menu_content", { root: document.body })
).toHaveCount(1);
expect(queryAll(".o_burger_menu_content", { root: document.body })).toHaveClass(
"o_burger_menu_app"
);
await click(".o_sidebar_topbar", { root: document.body });
expect(queryAll(".o_burger_menu_content", { root: document.body })).not.toHaveClass(
"o_burger_menu_dark"
);
await click(".o_sidebar_topbar", { root: document.body });
expect(queryAll(".o_burger_menu_content", { root: document.body })).toHaveClass(
"o_burger_menu_app"
);
});
test("Burger Menu on an App without SubMenu", async () => {
await mountWithCleanup(WebClient);
await contains("a.o_menu_toggle", { root: document.body }).click();
await contains(".o_sidebar_topbar a.btn-primary", { root: document.body }).click();
await contains(".o_burger_menu_content li:nth-of-type(2)", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(0);
await contains(".o_mobile_menu_toggle", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(1);
expect(queryAll(".o_user_menu_mobile", { root: document.body })).toHaveCount(1);
await click(".o_sidebar_close", { root: document.body });
expect(queryAll(".o_burger_menu")).toHaveCount(0);
});
test("Burger menu closes when an action is requested", async () => {
await mountWithCleanup(WebClient);
await contains(".o_mobile_menu_toggle", { root: document.body }).click();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(1);
expect(queryAll(".test_client_action", { root: document.body })).toHaveCount(0);
await getService("action").doAction(1001);
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(0);
expect(queryAll(".o_kanban_view", { root: document.body })).toHaveCount(0);
expect(queryAll(".test_client_action", { root: document.body })).toHaveCount(1);
});
test("Burger menu closes when click on menu item", async () => {
defineMenus([
{
id: 1,
children: [
{
id: 99,
name: "SubMenu",
actionID: 1002,
xmlid: "",
webIconData: undefined,
webIcon: false,
},
],
},
{ id: 2, name: "App2", actionID: 1003, xmlid: "menu_2" },
]);
await mountWithCleanup(WebClient);
getService("menu").setCurrentMenu(2);
await contains(".o_menu_toggle", { root: document.body }).click();
expect(
queryAll(".o_app_menu_sidebar nav.o_burger_menu_content", { root: document.body })
).toHaveText("App2");
await contains(".oi-apps", { root: document.body }).click();
expect(
queryAll(".o_app_menu_sidebar nav.o_burger_menu_content", { root: document.body })
).toHaveText("App0\nApp1\nApp2");
await contains(".o_burger_menu_app > ul > li:nth-of-type(2)", { root: document.body }).click();
expect(queryAll(".o_burger_menu_app")).toHaveCount(0);
await contains(".o_menu_toggle", { root: document.body }).click();
expect(queryAll(".o_burger_menu_app", { root: document.body })).toHaveCount(1);
expect(
queryAll(".o_app_menu_sidebar nav.o_burger_menu_content", { root: document.body })
).toHaveText("App1\nSubMenu");
await click(".o_burger_menu_content li:nth-of-type(1)", { root: document.body });
// click
await animationFrame();
// action
await animationFrame();
// close burger
await animationFrame();
expect(queryAll(".o_burger_menu_content", { root: document.body })).toHaveCount(0);
expect(queryAll(".test_client_action", { root: document.body })).toHaveCount(1);
});
test("Burger menu closes when click on user menu item", async () => {
registry.category("user_menuitems").add("ring_item", () => ({
type: "item",
id: "ring",
description: "Ring",
callback: () => {
expect.step("callback ring_item");
},
sequence: 5,
}));
await mountWithCleanup(WebClient);
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(0);
await click(queryAll(".o_mobile_menu_toggle", { root: document.body }));
await animationFrame();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(1);
await click(queryAll(".o_burger_menu .o_user_menu_mobile a", { root: document.body }));
await animationFrame();
expect(queryAll(".o_burger_menu", { root: document.body })).toHaveCount(0);
expect.verifySteps(["callback ring_item"]);
});

View file

@ -0,0 +1,305 @@
import { beforeEach, describe, expect, test } from "@odoo/hoot";
import { queryAllTexts } from "@odoo/hoot-dom";
import { animationFrame, runAllTimers } from "@odoo/hoot-mock";
import {
contains,
getService,
mountWithCleanup,
patchWithCleanup,
serverState,
} from "@web/../tests/web_test_helpers";
import { cookie } from "@web/core/browser/cookie";
import { MobileSwitchCompanyMenu } from "@web/webclient/burger_menu/mobile_switch_company_menu/mobile_switch_company_menu";
describe.current.tags("mobile");
const clickConfirm = () => contains(".o_switch_company_menu_buttons button:first").click();
const stepOnCookieChange = () =>
patchWithCleanup(cookie, {
set(key, value) {
if (key === "cids") {
expect.step(value);
}
return super.set(key, value);
},
});
/**
* @param {number} index
*/
const toggleCompany = async (index) =>
contains(`[data-company-id] [role=menuitemcheckbox]:eq(${index})`).click();
beforeEach(() => {
serverState.companies = [
{ id: 1, name: "Hermit", parent_id: false, child_ids: [] },
{ id: 2, name: "Herman's", parent_id: false, child_ids: [] },
{ id: 3, name: "Heroes TM", parent_id: false, child_ids: [] },
];
});
test("basic rendering", async () => {
await mountWithCleanup(MobileSwitchCompanyMenu);
expect(".o_burger_menu_companies").toHaveProperty("tagName", "DIV");
expect(".o_burger_menu_companies").toHaveClass("o_burger_menu_companies");
expect("[data-company-id]").toHaveCount(3);
expect(".log_into").toHaveCount(3);
expect(".fa-check-square").toHaveCount(1);
expect(".fa-square-o").toHaveCount(2);
expect(".o_switch_company_item:eq(0)").toHaveText("Hermit");
expect(".o_switch_company_item:eq(0)").toHaveClass("alert-secondary");
expect(".o_switch_company_item:eq(1)").toHaveText("Herman's");
expect(".o_switch_company_item:eq(2)").toHaveText("Heroes TM");
expect(".o_switch_company_item i:eq(0)").toHaveClass("fa-check-square");
expect(".o_switch_company_item i:eq(1)").toHaveClass("fa-square-o");
expect(".o_switch_company_item i:eq(2)").toHaveClass("fa-square-o");
expect(".o_burger_menu_companies").toHaveText("Companies\nHermit\nHerman's\nHeroes TM");
});
test("companies can be toggled: toggle a second company", async () => {
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["1"]);
/**
* [x] **Company 1**
* [ ] Company 2
* [ ] Company 3
*/
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(1);
expect("[data-company-id] .fa-square-o").toHaveCount(2);
/**
* [x] **Company 1**
* [x] Company 2 -> toggle
* [ ] Company 3
*/
await toggleCompany(1);
expect("[data-company-id] .fa-check-square").toHaveCount(2);
expect("[data-company-id] .fa-square-o").toHaveCount(1);
await clickConfirm();
expect.verifySteps(["1-2"]);
});
test("can toggle multiple companies at once", async () => {
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["1"]);
/**
* [x] **Company 1**
* [ ] Company 2
* [ ] Company 3
*/
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(1);
expect("[data-company-id] .fa-square-o").toHaveCount(2);
/**
* [ ] **Company 1** -> toggle all
* [x] Company 2 -> toggle all
* [x] Company 3 -> toggle all
*/
await toggleCompany(0);
await toggleCompany(1);
await toggleCompany(2);
expect("[data-company-id] .fa-check-square").toHaveCount(2);
expect("[data-company-id] .fa-square-o").toHaveCount(1);
expect.verifySteps([]);
await clickConfirm();
expect.verifySteps(["2-3"]);
});
test("single company selected: toggling it off will keep it", async () => {
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["1"]);
/**
* [x] **Company 1**
* [ ] Company 2
* [ ] Company 3
*/
await runAllTimers();
expect(cookie.get("cids")).toBe("1");
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(1);
expect("[data-company-id] .fa-square-o").toHaveCount(2);
/**
* [ ] **Company 1** -> toggle off
* [ ] Company 2
* [ ] Company 3
*/
await toggleCompany(0);
await clickConfirm();
expect.verifySteps(["1"]);
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id] .fa-check-squarqe").toHaveCount(0);
expect("[data-company-id] .fa-square-o").toHaveCount(3);
});
test("single company mode: companies can be logged in", async () => {
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["1"]);
/**
* [x] **Company 1**
* [ ] Company 2
* [ ] Company 3
*/
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(1);
expect("[data-company-id] .fa-square-o").toHaveCount(2);
/**
* [x] **Company 1**
* [ ] Company 2 -> log into
* [ ] Company 3
*/
await contains(".log_into:eq(1)").click();
expect.verifySteps(["2"]);
});
test("multi company mode: log into a non selected company", async () => {
cookie.set("cids", "3-1");
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["3-1"]);
/**
* [x] Company 1
* [ ] Company 2
* [x] **Company 3**
*/
expect(getService("company").activeCompanyIds).toEqual([3, 1]);
expect(getService("company").currentCompany.id).toBe(3);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(2);
expect("[data-company-id] .fa-square-o").toHaveCount(1);
/**
* [x] Company 1
* [ ] Company 2 -> log into
* [x] **Company 3**
*/
await contains(".log_into:eq(1)").click();
expect.verifySteps(["2-3-1"]);
});
test("multi company mode: log into an already selected company", async () => {
cookie.set("cids", "2-3");
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["2-3"]);
/**
* [ ] Company 1
* [x] **Company 2**
* [x] Company 3
*/
expect(getService("company").activeCompanyIds).toEqual([2, 3]);
expect(getService("company").currentCompany.id).toBe(2);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(2);
expect("[data-company-id] .fa-square-o").toHaveCount(1);
/**
* [ ] Company 1
* [x] **Company 2**
* [x] Company 3 -> log into
*/
await contains(".log_into:eq(2)").click();
expect.verifySteps(["3-2"]);
});
test("companies can be logged in even if some toggled within delay", async () => {
stepOnCookieChange();
await mountWithCleanup(MobileSwitchCompanyMenu);
expect.verifySteps(["1"]);
/**
* [x] **Company 1**
* [ ] Company 2
* [ ] Company 3
*/
expect(getService("company").activeCompanyIds).toEqual([1]);
expect(getService("company").currentCompany.id).toBe(1);
expect("[data-company-id]").toHaveCount(3);
expect("[data-company-id] .fa-check-square").toHaveCount(1);
expect("[data-company-id] .fa-square-o").toHaveCount(2);
/**
* [ ] **Company 1** -> toggled
* [ ] Company 2 -> logged in
* [ ] Company 3 -> toggled
*/
await contains("[data-company-id] [role=menuitemcheckbox]:eq(2)").click();
await contains("[data-company-id] [role=menuitemcheckbox]:eq(0)").click();
await contains(".log_into:eq(1)").click();
expect.verifySteps(["2"]);
});
test("show confirm and reset buttons only when selection has changed", async () => {
await mountWithCleanup(MobileSwitchCompanyMenu);
expect(".o_switch_company_menu_buttons").toHaveCount(0);
await toggleCompany(1);
expect(".o_switch_company_menu_buttons button").toHaveCount(2);
await toggleCompany(1);
expect(".o_switch_company_menu_buttons").toHaveCount(0);
});
test("No collapse and no search input when less that 10 companies", async () => {
await mountWithCleanup(MobileSwitchCompanyMenu);
expect(".o_burger_menu_companies .fa-caret-right").toHaveCount(0);
expect(".o_burger_menu_companies .visually-hidden input").toHaveCount(1);
});
test("Show search input when more that 10 companies & search filters items but ignore case and spaces", async () => {
serverState.companies = [
{ id: 3, name: "Hermit", sequence: 1, parent_id: false, child_ids: [] },
{ id: 2, name: "Herman's", sequence: 2, parent_id: false, child_ids: [] },
{ id: 1, name: "Heroes TM", sequence: 3, parent_id: false, child_ids: [4, 5] },
{ id: 4, name: "Hercules", sequence: 4, parent_id: 1, child_ids: [] },
{ id: 5, name: "Hulk", sequence: 5, parent_id: 1, child_ids: [] },
{ id: 6, name: "Random Company a", sequence: 6, parent_id: false, child_ids: [7, 8] },
{ id: 7, name: "Random Company aa", sequence: 7, parent_id: 6, child_ids: [] },
{ id: 8, name: "Random Company ab", sequence: 8, parent_id: 6, child_ids: [] },
{ id: 9, name: "Random d", sequence: 9, parent_id: false, child_ids: [] },
{ id: 10, name: "Random e", sequence: 10, parent_id: false, child_ids: [] },
];
await mountWithCleanup(MobileSwitchCompanyMenu);
await contains(".o_burger_menu_companies > div").click();
expect(".o_burger_menu_companies input").toHaveCount(1);
expect(".o_burger_menu_companies input").not.toBeFocused();
expect(".o_switch_company_item").toHaveCount(10);
contains(".o_burger_menu_companies input").edit("omcom");
await animationFrame();
expect(".o_switch_company_item").toHaveCount(3);
expect(queryAllTexts(".o_switch_company_item.o-navigable")).toEqual([
"Random Company a",
"Random Company aa",
"Random Company ab",
]);
});