Files
test/web_enterprise/static/tests/webclient/webclient_enterprise_tests.js
2023-04-14 17:42:23 +08:00

529 lines
24 KiB
JavaScript

/** @odoo-module **/
import {
click,
editInput,
getFixture,
nextTick,
patchWithCleanup,
} from "@web/../tests/helpers/utils";
import { doAction, getActionManagerServerData, loadState } from "@web/../tests/webclient/helpers";
import { registry } from "@web/core/registry";
import { editView } from "@web/views/debug_items";
import { createEnterpriseWebClient } from "@web_enterprise/../tests/helpers";
import { homeMenuService } from "@web_enterprise/webclient/home_menu/home_menu_service";
import { ormService } from "@web/core/orm_service";
import { enterpriseSubscriptionService } from "@web_enterprise/webclient/home_menu/enterprise_subscription_service";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { errorService } from "@web/core/errors/error_service";
import { browser } from "@web/core/browser/browser";
const { Component, xml } = owl;
let serverData;
let fixture;
const serviceRegistry = registry.category("services");
// Should test ONLY the webClient and features present in Enterprise
// Those tests rely on hidden view to be in CSS: display: none
QUnit.module("WebClient Enterprise", (hooks) => {
hooks.beforeEach(() => {
serverData = getActionManagerServerData();
fixture = getFixture();
serviceRegistry.add("home_menu", homeMenuService);
serviceRegistry.add("orm", ormService);
serviceRegistry.add("enterprise_subscription", enterpriseSubscriptionService);
});
QUnit.module("basic flow with home menu", (hooks) => {
let mockRPC;
hooks.beforeEach((assert) => {
serverData.menus[1].actionID = 4;
serverData.menus.root.children = [1];
serverData.views["partner,false,form"] = `
<form>
<field name="display_name"/>
<field name="m2o" open_target="current"/>
</form>`;
mockRPC = async (route) => {
assert.step(route);
if (route === "/web/dataset/call_kw/partner/get_formview_action") {
return {
type: "ir.actions.act_window",
res_model: "partner",
view_type: "form",
view_mode: "form",
views: [[false, "form"]],
target: "current",
res_id: 2,
};
}
};
});
QUnit.test("1 -- start up", async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
assert.ok(document.body.classList.contains("o_home_menu_background"));
assert.containsOnce(fixture, ".o_home_menu");
assert.isNotVisible(fixture.querySelector(".o_menu_toggle"));
assert.containsOnce(fixture, ".o_app.o_menuitem");
});
QUnit.test("2 -- navbar updates on displaying an action", async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
await click(fixture.querySelector(".o_app.o_menuitem"));
assert.verifySteps([
"/web/action/load",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/web_search_read",
]);
assert.notOk(document.body.classList.contains("o_home_menu_background"));
assert.containsNone(fixture, ".o_home_menu");
assert.containsOnce(fixture, ".o_kanban_view");
const menuToggle = fixture.querySelector(".o_menu_toggle");
assert.isVisible(menuToggle);
assert.notOk(menuToggle.classList.contains("o_menu_toggle_back"));
});
QUnit.test("3 -- push another action in the breadcrumb", async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
await click(fixture.querySelector(".o_app.o_menuitem"));
assert.verifySteps([
"/web/action/load",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/web_search_read",
]);
await click(fixture.querySelector(".o_kanban_record"));
await nextTick(); // there is another tick to update navbar and destroy HomeMenu
assert.verifySteps(["/web/dataset/call_kw/partner/read"]);
assert.isVisible(fixture.querySelector(".o_menu_toggle"));
assert.containsOnce(fixture, ".o_form_view");
assert.strictEqual(
fixture.querySelector(".breadcrumb-item.active").textContent,
"First record"
);
});
QUnit.test("4 -- push a third action in the breadcrumb", async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
await click(fixture.querySelector(".o_app.o_menuitem"));
assert.verifySteps([
"/web/action/load",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/web_search_read",
]);
await click(fixture.querySelector(".o_kanban_record"));
assert.verifySteps(["/web/dataset/call_kw/partner/read"]);
await click(fixture, '.o_field_widget[name="m2o"] .o_external_button', true);
assert.verifySteps([
"/web/dataset/call_kw/partner/get_formview_action",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/read",
]);
assert.containsOnce(fixture, ".o_form_view");
assert.strictEqual(
fixture.querySelector(".breadcrumb-item.active").textContent,
"Second record"
);
assert.containsN(fixture, ".breadcrumb-item", 3);
});
QUnit.test(
"5 -- switch to HomeMenu from an action with 2 breadcrumbs",
async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
await click(fixture.querySelector(".o_app.o_menuitem"));
assert.verifySteps([
"/web/action/load",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/web_search_read",
]);
await click(fixture.querySelector(".o_kanban_record"));
assert.verifySteps(["/web/dataset/call_kw/partner/read"]);
await click(fixture, '.o_field_widget[name="m2o"] .o_external_button', true);
assert.verifySteps([
"/web/dataset/call_kw/partner/get_formview_action",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/read",
]);
const menuToggle = fixture.querySelector(".o_menu_toggle");
await click(menuToggle);
assert.verifySteps([]);
assert.ok(menuToggle.classList.contains("o_menu_toggle_back"));
assert.containsOnce(fixture, ".o_home_menu");
assert.isNotVisible(fixture.querySelector(".o_form_view"));
}
);
QUnit.test("6 -- back to underlying action with many breadcrumbs", async function (assert) {
await createEnterpriseWebClient({ fixture, serverData, mockRPC });
assert.verifySteps(["/web/webclient/load_menus"]);
await click(fixture.querySelector(".o_app.o_menuitem"));
assert.verifySteps([
"/web/action/load",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/web_search_read",
]);
await click(fixture.querySelector(".o_kanban_record"));
assert.verifySteps(["/web/dataset/call_kw/partner/read"]);
await click(fixture, '.o_field_widget[name="m2o"] .o_external_button', true);
assert.verifySteps([
"/web/dataset/call_kw/partner/get_formview_action",
"/web/dataset/call_kw/partner/get_views",
"/web/dataset/call_kw/partner/read",
]);
const menuToggle = fixture.querySelector(".o_menu_toggle");
await click(menuToggle);
await click(menuToggle);
// if we don't reload on going back to underlying action
// assert.verifySteps(
// [],
// "the underlying view should not reload when toggling the HomeMenu to off"
// );
// endif
// if we reload on going back to underlying action
assert.verifySteps(
["/web/dataset/call_kw/partner/read"],
"the underlying view should reload when toggling the HomeMenu to off"
);
// endif
assert.containsNone(fixture, ".o_home_menu");
assert.containsOnce(fixture, ".o_form_view");
assert.notOk(menuToggle.classList.contains("o_menu_toggle_back"));
assert.strictEqual(
fixture.querySelector(".breadcrumb-item.active").textContent,
"Second record"
);
assert.containsN(fixture, ".breadcrumb-item", 3);
});
QUnit.test("restore the newly created record in form view (legacy)", async (assert) => {
const action = serverData.actions[6];
delete action.res_id;
action.target = "current";
const webClient = await createEnterpriseWebClient({ fixture, serverData });
await doAction(webClient, 6);
assert.containsOnce(fixture, ".o_form_view");
assert.containsOnce(fixture, ".o_form_view .o_form_editable");
await editInput(fixture, ".o_field_widget[name=display_name] input", "red right hand");
await click(fixture.querySelector(".o_form_button_save"));
assert.strictEqual(
fixture.querySelector(".breadcrumb-item.active").textContent,
"red right hand"
);
await click(fixture.querySelector(".o_menu_toggle"));
assert.isNotVisible(fixture.querySelector(".o_form_view"));
await click(fixture.querySelector(".o_menu_toggle"));
assert.containsOnce(fixture, ".o_form_view");
assert.containsOnce(fixture, ".o_form_view .o_form_saved");
assert.strictEqual(
fixture.querySelector(".breadcrumb-item.active").textContent,
"red right hand"
);
});
QUnit.skip("fast clicking on restore (implementation detail)", async (assert) => {
assert.expect(6);
let doVeryFastClick = false;
class DelayedClientAction extends Component {
setup() {
owl.onMounted(() => {
if (doVeryFastClick) {
doVeryFastClick = false;
click(fixture.querySelector(".o_menu_toggle"));
}
});
}
}
DelayedClientAction.template = xml`<div class='delayed_client_action'>
<button t-on-click="resolve">RESOLVE</button>
</div>`;
registry.category("actions").add("DelayedClientAction", DelayedClientAction);
const webClient = await createEnterpriseWebClient({ fixture, serverData });
await doAction(webClient, "DelayedClientAction");
await nextTick();
await click(fixture.querySelector(".o_menu_toggle"));
assert.isVisible(fixture.querySelector(".o_home_menu"));
assert.isNotVisible(fixture.querySelector(".delayed_client_action"));
doVeryFastClick = true;
await click(fixture.querySelector(".o_menu_toggle"));
await nextTick();
// off homemenu
assert.isVisible(fixture.querySelector(".o_home_menu"));
assert.isNotVisible(fixture.querySelector(".delayed_client_action"));
await click(fixture.querySelector(".o_menu_toggle"));
await nextTick();
assert.containsNone(fixture, ".o_home_menu");
assert.containsOnce(fixture, ".delayed_client_action");
});
});
QUnit.test("clear unCommittedChanges when toggling home menu", async function (assert) {
assert.expect(6);
// Edit a form view, don't save, toggle home menu
// the autosave feature of the Form view is activated
// and relied upon by this test
const mockRPC = (route, args) => {
if (args.method === "create") {
assert.strictEqual(args.model, "partner");
assert.deepEqual(args.args, [
{
display_name: "red right hand",
foo: false,
},
]);
}
};
const webClient = await createEnterpriseWebClient({ fixture, serverData, mockRPC });
await doAction(webClient, 3, { viewType: "form" });
assert.containsOnce(fixture, ".o_form_view .o_form_editable");
await editInput(fixture, ".o_field_widget[name=display_name] input", "red right hand");
await click(fixture.querySelector(".o_menu_toggle"));
assert.containsNone(fixture, ".o_form_view");
assert.containsNone(fixture, ".modal");
assert.containsOnce(fixture, ".o_home_menu");
});
QUnit.test("can have HomeMenu and dialog action", async function (assert) {
const webClient = await createEnterpriseWebClient({ fixture, serverData });
assert.containsOnce(fixture, ".o_home_menu");
assert.containsNone(fixture, ".modal .o_form_view");
await doAction(webClient, 5);
assert.containsOnce(fixture, ".modal .o_form_view");
assert.isVisible(fixture.querySelector(".modal .o_form_view"));
assert.containsOnce(fixture, ".o_home_menu");
});
QUnit.test("supports attachments of apps deleted", async function (assert) {
// When doing a pg_restore without the filestore
// LPE fixme: may not be necessary anymore since menus are not HomeMenu props anymore
serverData.menus = {
root: { id: "root", children: [1], name: "root", appID: "root" },
1: {
id: 1,
appID: 1,
actionID: 1,
xmlid: "",
name: "Partners",
children: [],
webIconData: "",
webIcon: "bloop,bloop",
},
};
patchWithCleanup(odoo, { debug: "1" });
await createEnterpriseWebClient({ fixture, serverData });
assert.containsOnce(fixture, ".o_home_menu");
});
QUnit.test(
"debug manager resets to global items when home menu is displayed",
async function (assert) {
const debugRegistry = registry.category("debug");
debugRegistry.category("view").add("editView", editView);
debugRegistry.category("default").add("item_1", () => {
return {
type: "item",
description: "globalItem",
callback: () => {},
sequence: 10,
};
});
const mockRPC = async (route) => {
if (route.includes("check_access_rights")) {
return true;
}
};
patchWithCleanup(odoo, { debug: "1" });
const webClient = await createEnterpriseWebClient({ fixture, serverData, mockRPC });
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
assert.containsOnce(fixture, ".o_debug_manager .dropdown-item:contains('globalItem')");
assert.containsNone(
fixture,
".o_debug_manager .dropdown-item:contains('Edit View: Kanban')"
);
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
await doAction(webClient, 1);
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
assert.containsOnce(fixture, ".o_debug_manager .dropdown-item:contains('globalItem')");
assert.containsOnce(
fixture,
".o_debug_manager .dropdown-item:contains('Edit View: Kanban')"
);
await click(fixture.querySelector(".o_menu_toggle"));
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
assert.containsOnce(fixture, ".o_debug_manager .dropdown-item:contains('globalItem')");
assert.containsNone(
fixture,
".o_debug_manager .dropdown-item:contains('Edit View: Kanban')"
);
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
await doAction(webClient, 3);
await click(fixture.querySelector(".o_debug_manager .dropdown-toggle"));
assert.containsOnce(fixture, ".o_debug_manager .dropdown-item:contains('globalItem')");
assert.containsOnce(
fixture,
".o_debug_manager .dropdown-item:contains('Edit View: List')"
);
assert.containsNone(
fixture,
".o_debug_manager .dropdown-item:contains('Edit View: Kanban')"
);
}
);
QUnit.test(
"url state is well handled when going in and out of the HomeMenu",
async function (assert) {
const webClient = await createEnterpriseWebClient({ fixture, serverData });
await nextTick();
assert.deepEqual(webClient.env.services.router.current.hash, { action: "menu" });
await click(fixture.querySelector(".o_app.o_menuitem:nth-child(2)"));
await nextTick();
assert.deepEqual(webClient.env.services.router.current.hash, {
action: 1002,
menu_id: 2,
});
await click(fixture.querySelector(".o_menu_toggle"));
await nextTick();
assert.deepEqual(webClient.env.services.router.current.hash, { action: "menu" });
await click(fixture.querySelector(".o_menu_toggle"));
await nextTick();
// if we reload on going back to underlying action
// end if
assert.deepEqual(webClient.env.services.router.current.hash, {
action: 1002,
menu_id: 2,
});
}
);
QUnit.test(
"underlying action's menu items are invisible when HomeMenu is displayed",
async function (assert) {
serverData.menus[1].children = [99];
serverData.menus[99] = {
id: 99,
children: [],
name: "SubMenu",
appID: 1,
actionID: 1002,
xmlid: "",
webIconData: undefined,
webIcon: false,
};
await createEnterpriseWebClient({ fixture, serverData });
assert.containsNone(fixture, "nav .o_menu_sections");
assert.containsNone(fixture, "nav .o_menu_brand");
await click(fixture.querySelector(".o_app.o_menuitem:nth-child(1)"));
await nextTick();
assert.containsOnce(fixture, "nav .o_menu_sections");
assert.containsOnce(fixture, "nav .o_menu_brand");
assert.isVisible(fixture.querySelector(".o_menu_sections"));
assert.isVisible(fixture.querySelector(".o_menu_brand"));
await click(fixture.querySelector(".o_menu_toggle"));
assert.containsOnce(fixture, "nav .o_menu_sections");
assert.containsOnce(fixture, "nav .o_menu_brand");
assert.isNotVisible(fixture.querySelector(".o_menu_sections"));
assert.isNotVisible(fixture.querySelector(".o_menu_brand"));
}
);
QUnit.test("loadState back and forth keeps relevant keys in state", async function (assert) {
const webClient = await createEnterpriseWebClient({ fixture, serverData });
await click(fixture.querySelector(".o_app.o_menuitem:nth-child(2)"));
await nextTick();
assert.containsOnce(fixture, ".test_client_action");
assert.containsNone(fixture, ".o_home_menu");
const state = webClient.env.services.router.current.hash;
assert.deepEqual(state, {
action: 1002,
menu_id: 2,
});
await loadState(webClient, {});
assert.containsNone(fixture, ".test_client_action");
assert.containsOnce(fixture, ".o_home_menu");
assert.deepEqual(webClient.env.services.router.current.hash, {
action: "menu",
});
await loadState(webClient, state);
assert.containsOnce(fixture, ".test_client_action");
assert.containsNone(fixture, ".o_home_menu");
assert.deepEqual(webClient.env.services.router.current.hash, state);
});
QUnit.test(
"go back to home menu using browser back button (i.e. loadState)",
async function (assert) {
const webClient = await createEnterpriseWebClient({ fixture, serverData });
assert.containsOnce(fixture, ".o_home_menu");
assert.isNotVisible(fixture.querySelector(".o_main_navbar .o_menu_toggle"));
await click(fixture.querySelector(".o_app.o_menuitem:nth-child(2)"));
assert.containsOnce(fixture, ".test_client_action");
assert.containsNone(fixture, ".o_home_menu");
await loadState(webClient, { action: "menu" }); // FIXME: this might need to be changed
assert.containsNone(fixture, ".test_client_action");
assert.containsOnce(fixture, ".o_home_menu");
assert.isNotVisible(fixture.querySelector(".o_main_navbar .o_menu_toggle"));
}
);
QUnit.test("initial action crashes", async (assert) => {
const handler = (ev) => {
// need to preventDefault to remove error from console (so python test pass)
ev.preventDefault();
};
window.addEventListener("unhandledrejection", handler);
registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
patchWithCleanup(QUnit, {
onUnhandledRejection: () => {},
});
browser.location.hash = "#action=__test__client__action__&menu_id=1";
const ClientAction = registry.category("actions").get("__test__client__action__");
class Override extends ClientAction {
setup() {
super.setup();
assert.step("clientAction setup");
throw new Error("my error");
}
}
registry.category("actions").add("__test__client__action__", Override, { force: true });
registry.category("services").add("error", errorService);
const webClient = await createEnterpriseWebClient({ fixture, serverData });
assert.verifySteps(["clientAction setup"]);
assert.containsOnce(fixture, "nav .o_menu_toggle");
assert.isVisible(fixture.querySelector("nav .o_menu_toggle"));
assert.strictEqual(fixture.querySelector(".o_action_manager").innerHTML, "");
assert.deepEqual(webClient.env.services.router.current.hash, {
action: "__test__client__action__",
menu_id: 1,
});
});
});