[FIX] *: adapt QUnit tests and tours

[FIX] *: selectors in tours

[FIX][TMP] account: CogMenu selector in tours

[FIX][TMP] web*: Breadcrumb targetting in tours

Adds a `o_breadcrumb` class to target the whole breadcrumb, no matter
how much elements it contains (collapsed parts, visible path, single
name...).

add classname on last breadcrumb item

[FIX][TMP] project: View buttons selector in tours (moved away from CP)

[FIX][TMP] project: Kanban selectors in tours (quick create)

[FIX][TMP] *: SearchBar selectors in tours (toggle menu)

[FIX][TMP] *: ButtonBox selector in tours

[WIP][IMP] web: add toggleSearchBarMenu in search helpers

adapt and unskip 3 list tests

adapt and unskip calendar tests

unskip web_tour test that actually pass

post rebase fix

allow to lose cell focus after multi edition (given to searchbar) - bug reported, to check later

post rebase fixes

fix

Part-of: odoo/odoo#116641
This commit is contained in:
Pierre Paridans
2023-05-12 22:59:22 +02:00
parent 3aaa0bfff1
commit eef262abf4
112 changed files with 3673 additions and 2329 deletions
@@ -430,7 +430,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target, ".my_owl_action");
await doAction(webClient, 3);
assert.strictEqual(
target.querySelector(".breadcrumb").textContent,
target.querySelector(".o_breadcrumb").textContent,
"Favorite PoniesnewOwlTitlePartners"
);
});
@@ -3,14 +3,16 @@
import {
click,
getFixture,
getNodesTextContent,
legacyExtraNextTick,
makeDeferred,
nextTick,
} from "@web/../tests/helpers/utils";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { SearchBar } from "@web/search/search_bar/search_bar";
import {
isItemSelected,
toggleFilterMenu,
toggleSearchBarMenu,
toggleMenuItem,
switchView,
} from "@web/../tests/search/helpers";
@@ -26,6 +28,10 @@ import {
import { Component, xml } from "@odoo/owl";
const actionRegistry = registry.category("actions");
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData;
let target;
@@ -109,12 +115,7 @@ QUnit.module("ActionManager", (hooks) => {
doAction(webClient, 4);
def.resolve();
await nextTick();
await legacyExtraNextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
});
QUnit.test("clicking quickly on breadcrumbs...", async function (assert) {
@@ -140,11 +141,7 @@ QUnit.module("ActionManager", (hooks) => {
// resolve the form view read
def.resolve();
await nextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded and visible"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
});
QUnit.test(
@@ -335,11 +332,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4");
assert.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -370,11 +363,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4");
assert.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -398,12 +387,12 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_view");
assert.containsN(target, ".o_list_view .o_data_row", 5);
assert.containsOnce(target, ".o_control_panel .o_list_buttons");
assert.containsOnce(target, ".o_control_panel .d-none.d-xl-inline-flex .o_list_buttons");
// reload (the search_read RPC will be blocked)
def = makeDeferred();
await switchView(target, "list");
assert.containsN(target, ".o_list_view .o_data_row", 5);
assert.containsOnce(target, ".o_control_panel .o_list_buttons");
assert.containsOnce(target, ".o_control_panel .d-none.d-xl-inline-flex .o_list_buttons");
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
@@ -468,10 +457,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_list_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_form_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -505,10 +491,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -540,10 +523,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -575,10 +555,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -616,18 +593,12 @@ QUnit.module("ActionManager", (hooks) => {
await click(row1.querySelector(".o_data_cell"));
await click(row2.querySelector(".o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
});
QUnit.test("local state, global state, and race conditions", async function (assert) {
@@ -659,15 +630,15 @@ QUnit.module("ActionManager", (hooks) => {
ToyController.template = xml`
<div class="o_toy_view">
<ControlPanel />
<SearchBar />
</div>`;
ToyController.components = { ControlPanel };
ToyController.components = { ControlPanel, SearchBar };
registry.category("views").add("toy", {
type: "toy",
display_name: "Toy",
icon: "fab fa-android",
multiRecord: true,
searchMenuTypes: ["filter"],
Controller: ToyController,
});
@@ -683,7 +654,7 @@ QUnit.module("ActionManager", (hooks) => {
],
});
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Foo");
assert.ok(isItemSelected(target, "Foo"));
@@ -695,7 +666,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
assert.ok(isItemSelected(target, "Foo"));
// this test is not able to detect that getGlobalState is put on the right place:
// currentController.action.globalState contains in any case the search state
@@ -33,7 +33,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, "1");
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partners Action 1");
assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partners Action 1");
assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"]
@@ -46,7 +46,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.ok(e.cause instanceof TypeError);
}
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partners Action 1");
assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partners Action 1");
assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"]
@@ -17,8 +17,9 @@ import {
nextTick,
makeDeferred,
editInput,
getNodesTextContent,
} from "../../helpers/utils";
import { pagerNext, toggleFilterMenu, toggleMenuItem } from "@web/../tests/search/helpers";
import { pagerNext, toggleMenuItem, toggleSearchBarMenu } from "@web/../tests/search/helpers";
import { session } from "@web/session";
import {
createWebClient,
@@ -31,6 +32,10 @@ import { errorService } from "@web/core/errors/error_service";
import { Component, xml } from "@odoo/owl";
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData;
let target;
@@ -233,13 +238,8 @@ QUnit.module("ActionManager", (hooks) => {
model: "partner",
});
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
});
@@ -261,11 +261,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.nextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.containsNone(target, ".o_menu_brand");
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
});
@@ -318,7 +314,7 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test(
"lazy load multi record view if mono record one is requested",
async function (assert) {
assert.expect(12);
assert.expect(11);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -332,15 +328,9 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsNone(target, ".o_list_view");
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".o_control_panel .breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Second record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
// go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view");
assert.containsNone(target, ".o_form_view");
assert.verifySteps([
@@ -354,48 +344,21 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("lazy load multi record view with previous action", async function (assert) {
assert.expect(6);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 4);
assert.containsOnce(
target,
".o_control_panel .breadcrumb li",
"there should be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
await doAction(webClient, 3, {
props: { resId: 2 },
viewType: "form",
});
assert.containsN(
target,
".o_control_panel .breadcrumb li",
3,
"there should be three controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4PartnersSecond record",
"the breadcrumb elements should be correctly ordered"
);
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners Action 4",
"Partners",
"Second record",
]);
// go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:last"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb li",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4Partners",
"the breadcrumb elements should be correctly ordered"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4", "Partners"]);
});
QUnit.test(
@@ -421,7 +384,7 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("change the viewType of the current action", async function (assert) {
assert.expect(14);
assert.expect(13);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -447,17 +410,7 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsNone(target, ".o_kanban_view");
assert.containsOnce(target, ".o_form_view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Fourth record",
"should have opened the requested record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
// verify steps to ensure that the whole action hasn't been re-executed
// (if it would have been, /web/action/load and get_views would appear
// several times)
@@ -472,7 +425,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("change the id of the current action", async function (assert) {
assert.expect(12);
assert.expect(11);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -480,13 +433,8 @@ QUnit.module("ActionManager", (hooks) => {
// execute action 3 and open the first record in a form view
await doAction(webClient, 3);
await testUtils.dom.click($(target).find(".o_list_view .o_data_cell:first"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"should have opened the first record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// switch to record 4
webClient.env.bus.trigger("test:hashchange", {
action: 3,
@@ -494,19 +442,8 @@ QUnit.module("ActionManager", (hooks) => {
view_type: "form",
});
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Fourth record",
"should have switched to the requested record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
// verify steps to ensure that the whole action hasn't been re-executed
// (if it would have been, /web/action/load and get_views would appear
// twice)
@@ -699,20 +636,12 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 4);
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
await loadState(webClient, {
model: "partner",
view_type: "list",
});
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"should still be in the same action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.containsNone(target, ".o_kanban_view", "should no longer display a kanban view");
assert.containsOnce(target, ".o_list_view", "should display a list view");
assert.verifySteps([
@@ -742,11 +671,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await loadState(webClient, { menu_id: 666 });
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -762,21 +687,14 @@ QUnit.module("ActionManager", (hooks) => {
1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1 },
};
const webClient = await createWebClient({ serverData });
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
await loadState(webClient, { action: 3 });
assert.containsOnce(target, ".o_list_view"); // action 3
assert.strictEqual($(target).find(".o_control_panel .breadcrumb-item").text(), "Partners");
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
await loadState(webClient, { home: 1 });
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
});
QUnit.test("load state supports #home as initial state", async function (assert) {
@@ -793,10 +711,7 @@ QUnit.module("ActionManager", (hooks) => {
await createWebClient({ serverData, mockRPC });
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -806,7 +721,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("load state: in a form view, remove the id from the state", async function (assert) {
assert.expect(13);
assert.expect(11);
serverData.actions[999] = {
id: 999,
name: "Partner",
@@ -823,11 +738,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999, { viewType: "form", props: { resId: 2 } });
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "Second record"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -841,11 +752,7 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.verifySteps(["/web/dataset/call_kw/partner/onchange"]);
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"New"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "New"]);
});
QUnit.test("hashchange does not trigger canberemoved right away", async function (assert) {
@@ -957,11 +864,10 @@ QUnit.module("ActionManager", (hooks) => {
});
await click(target.querySelector(".o_control_panel .breadcrumb-item"));
await legacyExtraNextTick();
assert.containsN(target, ".o_list_view .o_data_row", 5);
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter");
assert.containsN(target, ".o_list_view .o_data_row", 1);
@@ -982,18 +888,18 @@ QUnit.module("ActionManager", (hooks) => {
},
{ props: { resIds: [1, 2] } }
);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "First record");
assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
await pagerNext(target);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Second record");
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
await editInput(target, "[name=display_name] input", "new name");
// without saving we now make a loadState which should commit changes
await loadState(webClient, { action: 1337, id: 1, model: "partner", view_type: "form" });
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "First record");
assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
// loadState again just to check if changes were commited
await loadState(webClient, { action: 1337, id: 2, model: "partner", view_type: "form" });
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "new name");
assert.deepEqual(getBreadCrumbTexts(target), ["new name"]);
});
QUnit.test("initial action crashes", async (assert) => {
@@ -5,7 +5,6 @@ import { registry } from "@web/core/registry";
import { session } from "@web/session";
import AbstractAction from "web.AbstractAction";
import core from "web.core";
import testUtils from "web.test_utils";
import { makeTestEnv } from "../../helpers/mock_env";
import {
click,
@@ -207,10 +206,10 @@ QUnit.module("ActionManager", (hooks) => {
serverData.actions[4].context = { no_breadcrumbs: true };
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
assert.containsOnce(target, ".o_control_panel .breadcrumb-item");
assert.containsOnce(target, ".o_control_panel .o_breadcrumb");
// push another action flagged with 'no_breadcrumbs=true'
await doAction(webClient, 4);
assert.containsNone(target, ".o_control_panel .breadcrumb-item");
assert.containsNone(target, ".o_control_panel .o_breadcrumb");
});
QUnit.test("document's title is updated when an action is executed", async function (assert) {
@@ -272,10 +271,10 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, "ClientAction");
assert.containsOnce(target, ".my_button");
await testUtils.dom.click(target.querySelector(".my_button"));
await click(target.querySelector(".my_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view");
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:first"));
await click(target, ".o_control_panel .breadcrumb a");
await legacyExtraNextTick();
assert.containsOnce(target, ".my_button");
assert.verifySteps(["on_reverse_breadcrumb"]);
@@ -284,7 +283,7 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test('handles "history_back" event', async function (assert) {
assert.expect(3);
assert.expect(4);
let list;
patchWithCleanup(listView.Controller.prototype, {
setup() {
@@ -295,13 +294,13 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, 4);
await doAction(webClient, 3);
assert.containsN(target, ".o_control_panel .breadcrumb-item", 2);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
list.env.config.historyBack();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_control_panel .breadcrumb-item");
await nextTick();
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partners Action 4",
"breadcrumbs should display the display_name of the action"
);
@@ -166,7 +166,12 @@ QUnit.module("ActionManager", (hooks) => {
".o_content iframe",
"should have opened the report client action"
);
assert.containsOnce(target, "button[title='Print']", "should have a print button");
// the control panel has the content twice and a d-none class is toggled depending the screen size
assert.containsOnce(
target,
":not(.d-none) > button[title='Print']",
"should have a print button"
);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -359,7 +364,11 @@ QUnit.module("ActionManager", (hooks) => {
assert.verifySteps([
"/report/html/ennio.morricone/99?context=%7B%22lang%22%3A%22en%22%2C%22uid%22%3A7%2C%22tz%22%3A%22taht%22%7D",
]);
await click(target.querySelector("button[title='Print']"));
await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex button[title='Print']"
)
);
assert.verifySteps(["/report/check_wkhtmltopdf", "/report/download"]);
});
@@ -407,7 +407,7 @@ QUnit.module("ActionManager", (hooks) => {
// execute an action in target="current"
await doAction(webClient, 1);
assert.deepEqual(
[...target.querySelectorAll(".breadcrumb-item")].map((i) => i.innerText),
[...target.querySelectorAll(".o_breadcrumb span")].map((i) => i.innerText),
["Partners Action 1"]
);
@@ -420,7 +420,7 @@ QUnit.module("ActionManager", (hooks) => {
type: "ir.actions.act_window",
views: [[false, "list"]],
});
assert.containsNone(target, ".modal .breadcrumb");
assert.containsNone(target, ".modal .o_breadcrumb");
});
QUnit.test('call switchView in an action in target="new"', async function (assert) {
@@ -554,9 +554,9 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 1);
assert.containsOnce(target, ".o_kanban_view");
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partners Action 1"
);
@@ -569,9 +569,9 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.containsOnce(target, ".o_list_view");
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Another Partner Action"
);
});
@@ -590,9 +590,9 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.containsOnce(target, ".o_list_view");
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partner Action"
);
@@ -600,9 +600,10 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_data_row .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partner ActionFirst record"
);
});
@@ -621,31 +622,34 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.containsOnce(target, ".o_list_view");
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partner Action"
);
// open first record
await click(target.querySelector(".o_data_row .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partner ActionFirst record"
);
await doAction(webClient, 1);
assert.containsOnce(target, ".o_kanban_view");
assert.containsN(target, ".breadcrumb-item", 3);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
// go back to form view
await click(target.querySelectorAll(".breadcrumb-item")[1]);
await click(target.querySelector("ol.breadcrumb .o_back_button"));
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partner ActionFirst record"
);
});
@@ -32,6 +32,18 @@ let serverData;
let target;
const serviceRegistry = registry.category("services");
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
async function clickKanbanNew(target) {
await click(target.querySelectorAll(".o_control_panel .o-kanban-button-new")[1]);
}
async function clickListNew(target) {
await click(target.querySelectorAll(".o_control_panel .o_list_button_add")[1]);
}
QUnit.module("ActionManager", (hooks) => {
hooks.beforeEach(() => {
serverData = getActionManagerServerData();
@@ -78,7 +90,8 @@ QUnit.module("ActionManager", (hooks) => {
};
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 3);
assert.containsNone(target, ".o_cp_action_menus");
assert.containsNone(target, ".o_cp_action_menus .o_dropdown_title"); // no action menu
await click(target.querySelector("input.form-check-input"));
assert.isVisible(
$(target).find('.o_cp_action_menus button.dropdown-toggle:contains("Print")')[0]
@@ -160,7 +173,7 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 1);
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view");
// quick create record
await testUtils.dom.click(target.querySelector(".o-kanban-button-new"));
await clickKanbanNew(target);
await editInput(target, ".o_field_widget[name=display_name] input", "New name");
// edit quick-created record
@@ -236,98 +249,41 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("breadcrumbs are updated when switching between views", async function (assert) {
assert.expect(15);
assert.expect(10);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.containsNone(target, ".o_control_panel .breadcrumb-item");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners",
"breadcrumbs should display the display_name of the action"
target.querySelector(".o_control_panel .o_breadcrumb .active").innerText,
"Partners"
);
// switch to kanban view
await cpHelpers.switchView(target, "kanban");
await legacyExtraNextTick();
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should still be one controller in the breadcrumbs"
);
assert.containsNone(target, ".o_control_panel .breadcrumb-item");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners",
"breadcrumbs should still display the display_name of the action"
target.querySelector(".o_control_panel .o_breadcrumb .active").innerText,
"Partners"
);
// open a record in form view
await testUtils.dom.click(target.querySelector(".o_kanban_view .o_kanban_record"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// go back to kanban view using the breadcrumbs
await testUtils.dom.click(target.querySelector(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
// switch back to list view
await cpHelpers.switchView(target, "list");
await legacyExtraNextTick();
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should still be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners",
"breadcrumbs should still display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
// open a record in form view
await testUtils.dom.click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// go back to list view using the breadcrumbs
await testUtils.dom.click(target.querySelector(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view", "should be back on list view");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
});
QUnit.test("switch buttons are updated when switching between views", async function (assert) {
@@ -562,7 +518,7 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
assert.containsN(target, ".o_data_row", 5);
// activate a domain
await cpHelpers.toggleFilterMenu(target);
await cpHelpers.toggleSearchBarMenu(target);
await cpHelpers.toggleMenuItem(target, "Bar");
await legacyExtraNextTick();
assert.containsN(target, ".o_data_row", 2);
@@ -596,7 +552,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.containsOnce(target, ".o_form_view", "The form view should be displayed");
// Delete the current record
await testUtils.controlPanel.toggleActionMenu(target);
await click(target, ".o_cp_action_menus .fa-cog");
await testUtils.dom.click(
Array.from(document.querySelectorAll(".o_menu_item")).find(
(e) => e.textContent === "Delete"
@@ -649,103 +605,56 @@ QUnit.module("ActionManager", (hooks) => {
// switch to kanban view
def = testUtils.makeTestPromise();
await cpHelpers.switchView(target, "kanban");
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view", "should still display the list view");
assert.containsNone(target, ".o_kanban_view", "shouldn't display the kanban view yet");
def.resolve();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsNone(target, ".o_list_view", "shouldn't display the list view anymore");
assert.containsOnce(target, ".o_kanban_view", "should now display the kanban view");
// switch back to list view
def = testUtils.makeTestPromise();
await cpHelpers.switchView(target, "list");
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view", "should still display the kanban view");
assert.containsNone(target, ".o_list_view", "shouldn't display the list view yet");
def.resolve();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsNone(target, ".o_kanban_view", "shouldn't display the kanban view anymore");
assert.containsOnce(target, ".o_list_view", "should now display the list view");
// open a record in form view
def = testUtils.makeTestPromise();
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view", "should still display the list view");
assert.containsNone(target, ".o_form_view", "shouldn't display the form view yet");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should still be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
def.resolve();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsNone(target, ".o_list_view", "should no longer display the list view");
assert.containsOnce(target, ".o_form_view", "should display the form view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// go back to list view using the breadcrumbs
def = testUtils.makeTestPromise();
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view", "should still display the form view");
assert.containsNone(target, ".o_list_view", "shouldn't display the list view yet");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should still be two controllers in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
def.resolve();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsNone(target, ".o_form_view", "should no longer display the form view");
assert.containsOnce(target, ".o_list_view", "should display the list view");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
});
QUnit.test("breadcrumbs are updated when display_name changes", async function (assert) {
assert.expect(4);
assert.expect(2);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// switch to edit mode and change the display_name
await editInput(target, ".o_field_widget[name=display_name] input", "New name");
await clickSave(target);
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should still be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"New name",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "New name"]);
});
QUnit.test('reverse breadcrumb works on accesskey "b"', async function (assert) {
@@ -754,20 +663,23 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
await testUtils.dom.click($(target).find(".o_form_view button:contains(Execute action)"));
assert.containsN(target, ".o_control_panel .breadcrumb li", 3);
let $previousBreadcrumb = $(target).find(".o_control_panel .breadcrumb li.active").prev();
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners",
"First record",
"Partners Action 4",
]);
let previousBreadcrumb = target.querySelector(".breadcrumb-item.o_back_button");
assert.strictEqual(
$previousBreadcrumb.attr("data-hotkey"),
previousBreadcrumb.getAttribute("data-hotkey"),
"b",
"previous breadcrumb should have accessKey 'b'"
);
await testUtils.dom.click($previousBreadcrumb);
assert.containsN(target, ".o_control_panel .breadcrumb li", 2);
$previousBreadcrumb = $(target).find(".o_control_panel .breadcrumb li.active").prev();
await testUtils.dom.click(previousBreadcrumb);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
previousBreadcrumb = target.querySelector(".breadcrumb-item.o_back_button");
assert.strictEqual(
$previousBreadcrumb.attr("data-hotkey"),
previousBreadcrumb.getAttribute("data-hotkey"),
"b",
"previous breadcrumb should have accessKey 'b'"
);
@@ -781,8 +693,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 3);
// create a new record
await testUtils.dom.click($(target).find(".o_control_panel .o_list_button_add"));
await legacyExtraNextTick();
await clickListNew(target);
assert.containsOnce(
target,
".o_form_view .o_form_editable",
@@ -790,7 +701,6 @@ QUnit.module("ActionManager", (hooks) => {
);
// discard
await testUtils.dom.click($(target).find(".o_control_panel .o_form_button_cancel"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view", "should have switched back to the list view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -978,22 +888,14 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
// click on 'Execute action' button (should execute an action)
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two parts in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
await testUtils.dom.click($(target).find(".o_form_view button:contains(Execute action)"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
3,
"the returned action should have been stacked over the previous one"
);
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners",
"First record",
"Partners Action 4",
]);
assert.containsOnce(
target,
".o_kanban_view",
@@ -1025,14 +927,14 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 24);
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.containsOnce(target, ".o_form_button_create:not([disabled]):visible");
await testUtils.dom.click(target.querySelector(".oe_stat_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view");
await testUtils.dom.click(target.querySelector(".breadcrumb-item"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.containsOnce(target, ".o_form_button_create:not([disabled]):visible");
assert.verifySteps(["read", "web_search_read", "read"]);
});
@@ -1047,11 +949,11 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 24);
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.containsOnce(target, ".o_form_button_create:not([disabled]):visible");
await testUtils.dom.click(target.querySelector(".oe_stat_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.containsOnce(target, ".o_form_button_create:not([disabled]):visible");
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -1138,9 +1040,8 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
// open the first record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
target.querySelector(".o_breadcrumb .active").innerText,
"First record",
"breadcrumbs should contain the display_name of the opened record"
);
@@ -1151,14 +1052,12 @@ QUnit.module("ActionManager", (hooks) => {
);
// go back to list view using the breadcrumbs
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
// open the second record in form view
await testUtils.dom.click(
$(target).find(".o_list_view .o_data_row:nth(1) .o_data_cell:first")
);
await legacyExtraNextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
target.querySelector(".o_breadcrumb .active").innerText,
"Second record",
"breadcrumbs should contain the display_name of the opened record"
);
@@ -1179,45 +1078,24 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("restore previous view state when switching back", async function (assert) {
assert.expect(5);
registry.category("services").add("cookie", fakeCookieService);
serverData.actions[3].views.unshift([false, "graph"]);
serverData.views["partner,false,graph"] = "<graph/>";
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
assert.hasClass(
$(target).find(".o_control_panel [data-mode='bar']")[0],
"active",
"bar chart button is active"
);
assert.hasClass(target.querySelector(".o_graph_renderer [data-mode='bar']"), "active");
assert.doesNotHaveClass(
$(target).find(".o_control_panel [data-mode='line']")[0],
"active",
"line chart button is not active"
target.querySelector(".o_graph_renderer [data-mode='line']"),
"active"
);
// display line chart
await testUtils.dom.click($(target).find(".o_control_panel [data-mode='line']"));
await legacyExtraNextTick();
assert.hasClass(
$(target).find(".o_control_panel [data-mode='line']")[0],
"active",
"line chart button is now active"
);
await testUtils.dom.click(target.querySelector(".o_graph_renderer [data-mode='line']"));
assert.hasClass(target.querySelector(".o_graph_renderer [data-mode='line']"), "active");
// switch to kanban and back to graph view
await cpHelpers.switchView(target, "kanban");
await legacyExtraNextTick();
assert.containsNone(
target,
".o_control_panel [data-mode='line']",
"graph buttons are no longer in control panel"
);
assert.containsNone(target, ".o_graph_renderer [data-mode='line']");
await cpHelpers.switchView(target, "graph");
await legacyExtraNextTick();
assert.hasClass(
$(target).find(".o_control_panel [data-mode='line']")[0],
"active",
"line chart button is still active"
);
assert.hasClass(target.querySelector(".o_graph_renderer [data-mode='line']"), "active");
});
QUnit.test("can't restore previous action if form is invalid", async function (assert) {
@@ -1227,7 +1105,7 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_view");
await click(target.querySelector(".o_list_button_add"));
await clickListNew(target);
assert.containsOnce(target, ".o_form_view");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
@@ -1287,7 +1165,7 @@ QUnit.module("ActionManager", (hooks) => {
"list view is not grouped"
);
// open group by dropdown
await cpHelpers.toggleGroupByMenu(target);
await cpHelpers.toggleSearchBarMenu(target);
// click on foo link
await cpHelpers.toggleMenuItem(target, "foo");
await legacyExtraNextTick();
@@ -1367,77 +1245,32 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("go back to a previous action using the breadcrumbs", async function (assert) {
assert.expect(10);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// push another action on top of the first one, and come back to the form view
await doAction(webClient, 4);
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
3,
"there should be three controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners",
"First record",
"Partners Action 4",
"breadcrumbs should contain the name of the current action"
);
]);
// go back using the breadcrumbs
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:nth(1)"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// push again the other action on top of the first one, and come back to the list view
await doAction(webClient, 4);
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
3,
"there should be three controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners",
"First record",
"Partners Action 4",
"breadcrumbs should contain the name of the current action"
);
]);
// go back using the breadcrumbs
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:first"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
1,
"there should be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Partners",
"breadcrumbs should contain the name of the current action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
});
QUnit.test(
@@ -1481,14 +1314,14 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("honor group_by specified in actions context", async function (assert) {
assert.expect(5);
serverData.actions[3].context = "{'group_by': 'bar'}";
serverData.views["partner,false,search"] = `
<search>
<group>
<filter name="foo" string="foo" context="{'group_by': 'foo'}"/>
</group>
</search>`;
<search>
<group>
<filter name="foo" string="Foo" context="{'group_by': 'foo'}"/>
</group>
</search>
`;
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_table_grouped", "should be grouped");
@@ -1498,9 +1331,9 @@ QUnit.module("ActionManager", (hooks) => {
2,
"should be grouped by 'bar' (two groups) at first load"
);
// groupby 'bar' using the searchview
await click(target.querySelectorAll(".o_control_panel .o_cp_bottom_right button")[1]);
await click(target.querySelector(".o_control_panel .o_group_by_menu .o_menu_item"));
// groupby 'foo' using the searchview
await cpHelpers.toggleSearchBarMenu(target);
await cpHelpers.toggleMenuItem(target, "Foo");
assert.containsN(target, ".o_group_header", 5, "should be grouped by 'foo' (five groups)");
// remove the groupby in the searchview
await click(target.querySelector(".o_control_panel .o_searchview .o_facet_remove"));
@@ -1561,7 +1394,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, 33);
assert.containsOnce(target, ".o_list_view");
assert.containsN(target, ".o_cp_switch_buttons button", 2);
assert.containsN(target, "nav.o_cp_switch_buttons button", 2);
});
QUnit.test("flags field of ir.actions.act_window is used", async function (assert) {
@@ -1631,7 +1464,7 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 33);
assert.containsN(target, ".o_data_row", 5, "should contain 5 records");
// filter on bar
await cpHelpers.toggleFilterMenu(target);
await cpHelpers.toggleSearchBarMenu(target);
await cpHelpers.toggleMenuItem(target, "Bar");
assert.containsN(target, ".o_data_row", 2);
// save filter
@@ -1674,7 +1507,7 @@ QUnit.module("ActionManager", (hooks) => {
"record should be in descending order as default_order applies"
);
await cpHelpers.toggleFavoriteMenu(target);
await cpHelpers.toggleSearchBarMenu(target);
await cpHelpers.toggleMenuItem(target, "favorite filter");
assert.strictEqual(
target.querySelector(".o_control_panel .o_facet_values").innerText.trim(),
@@ -1736,25 +1569,19 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test(
"search menus are still available when switching between actions",
async function (assert) {
assert.expect(3);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 1);
assert.isVisible(
target.querySelector(".o_search_options .dropdown.o_filter_menu"),
"the search options should be available"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.containsOnce(target, ".o_searchview_dropdown_toggler");
await doAction(webClient, 3);
assert.isVisible(
target.querySelector(".o_search_options .dropdown.o_filter_menu"),
"the search options should be available"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1", "Partners"]);
assert.containsOnce(target, ".o_searchview_dropdown_toggler");
// go back using the breadcrumbs
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:first"));
await legacyExtraNextTick();
assert.isVisible(
target.querySelector(".o_search_options .dropdown.o_filter_menu"),
"the search options should be available"
);
await click(target, ".o_control_panel .breadcrumb-item a");
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.containsOnce(target, ".o_searchview_dropdown_toggler");
}
);
@@ -1791,7 +1618,6 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("destroy action with lazy loaded controller", async function (assert) {
assert.expect(6);
const webClient = await createWebClient({ serverData });
await loadState(webClient, {
action: 3,
@@ -1800,17 +1626,7 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.containsNone(target, ".o_list_view");
assert.containsOnce(target, ".o_form_view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Second record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
await doAction(webClient, 1, { clearBreadcrumbs: true });
assert.containsNone(target, ".o_form_view");
assert.containsOnce(target, ".o_kanban_view");
@@ -1839,32 +1655,23 @@ QUnit.module("ActionManager", (hooks) => {
// execute an action and create a new record
await doAction(webClient, 3);
await click(target.querySelector(".o_list_button_add"));
await clickListNew(target);
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.containsOnce(target, ".o_form_uri:contains(First record)");
assert.deepEqual(
getNodesTextContent(target.querySelectorAll(".o_control_panel .breadcrumb-item")),
["Partners", "New"]
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "New"]);
// set form view dirty and open m2o record
await editInput(target, '.o_field_widget[name="display_name"] input', "test");
await editInput(target, ".o_field_widget[name=foo] input", "val");
await click(target.querySelector(".o_form_uri"));
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.deepEqual(
getNodesTextContent(target.querySelectorAll(".o_control_panel .breadcrumb-item")),
["Partners", "test", "First record"]
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "test", "First record"]);
// go back to test using the breadcrumbs
await testUtils.dom.click(
target.querySelectorAll(".o_control_panel .breadcrumb-item a")[1]
);
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.deepEqual(
getNodesTextContent(target.querySelectorAll(".o_control_panel .breadcrumb-item")),
["Partners", "test"]
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "test"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -1903,7 +1710,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_data_row .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
// execute the custom action from the action menu
await cpHelpers.toggleActionMenu(target);
await click(target, ".o_cp_action_menus .fa-cog");
await cpHelpers.toggleMenuItem(target, "Favorite Ponies");
assert.containsOnce(target, ".o_list_view");
});
@@ -1933,23 +1740,14 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999);
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
// push another action in the breadcrumb
await click(target, ".o_field_many2one .o_external_button");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second recordThird record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record", "Third record"]);
// go back to the form view
await click(target.querySelector(".o_control_panel .breadcrumb a"));
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
}
);
@@ -1973,10 +1771,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999, { props: { resIds: [1, 2] } });
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"First record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
assert.strictEqual(
target.querySelector(".o_control_panel .o_pager_counter").textContent,
"1 / 2"
@@ -1984,10 +1779,7 @@ QUnit.module("ActionManager", (hooks) => {
// load another id on current action (through pager)
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.strictEqual(
target.querySelector(".o_control_panel .o_pager_counter").textContent,
"2 / 2"
@@ -1995,17 +1787,11 @@ QUnit.module("ActionManager", (hooks) => {
// push another action in the breadcrumb
await click(target, ".o_field_many2one .o_external_button");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second recordThird record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record", "Third record"]);
// restore previous action through breadcrumb
await click(target.querySelector(".o_control_panel .breadcrumb a"));
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.strictEqual(
target.querySelector(".o_control_panel .o_pager_counter").textContent,
"2 / 2"
@@ -2027,7 +1813,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_control_panel .breadcrumb-item a"));
assert.containsOnce(target, ".o_list_view");
// create a new record
await click(target.querySelector(".o_list_button_add"));
await clickListNew(target);
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_view .o_form_editable");
});
@@ -2074,7 +1860,7 @@ QUnit.module("ActionManager", (hooks) => {
// execute an action and create a new record
await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_view");
await click(target.querySelector(".o_list_button_add"));
await clickListNew(target);
assert.containsOnce(target, ".o_form_view");
assert.containsOnce(target, ".o_form_view .o_form_editable");
await editInput(target, ".o_field_widget[name=display_name] input", "another record");
@@ -2191,7 +1977,7 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
await click(target.querySelector(".o_list_button_add"));
await clickListNew(target);
assert.containsOnce(
document.body,
".modal.o_technical_modal",
@@ -2633,36 +2419,42 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_data_row .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb-item")), [
"Partners",
"",
"First record",
"Partners",
"First record",
]);
assert.strictEqual(target.querySelector(".o_breadcrumb .active").innerText, "First record");
// open action menu and delete
await cpHelpers.toggleActionMenu(target);
await click(target, ".o_cp_action_menus .fa-cog");
await cpHelpers.toggleMenuItem(target, "Delete");
assert.containsOnce(target, ".o_dialog");
// confirm
await click(target.querySelector(".o_dialog .modal-footer .btn-primary"));
assert.containsOnce(target, ".o_form_view");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb-item")), [
"Partners",
"",
"First record",
"Partners",
"Second record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb .active").innerText,
"Second record"
);
// click on "First record" in breadcrumbs, which doesn't exist anymore
await click(target.querySelectorAll(".breadcrumb-item a")[1]);
await click(target.querySelectorAll(".breadcrumb-item a")[0]);
await nextTick();
assert.containsOnce(target, ".o_form_view");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb-item")), [
"",
"Partners",
"Partners",
"Partners",
"Second record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb .active").innerText,
"Second record"
);
});
});
@@ -407,10 +407,7 @@ QUnit.module("SettingsFormView", (hooks) => {
await doAction(webClient, 1);
assert.notOk(target.querySelector(".o_field_boolean input").disabled);
await click(target.querySelector("button[name='4']"));
assert.strictEqual(
target.querySelector(".breadcrumb").textContent,
"SettingsOther action"
);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Settings");
await click(target.querySelector(".o_control_panel .breadcrumb-item a"));
assert.notOk(target.querySelector(".o_field_boolean input").disabled);
assert.verifySteps([
@@ -500,7 +497,7 @@ QUnit.module("SettingsFormView", (hooks) => {
await click(target.querySelector(".o_field_char .btn.o_field_translate")); // Transalte
await click(target.querySelector(".modal-footer .btn-primary")); // Warning dialog (OK)
await click(target.querySelectorAll(".modal-footer .btn")[1]); // Discard
await click(target.querySelector(".o_form_button_save")); // Save Settings
await click(target.querySelector(".o_control_panel .o_form_button_save")); // Save Settings
});
QUnit.test("settings views does not read existing id when reload", async function (assert) {
@@ -733,7 +730,7 @@ QUnit.module("SettingsFormView", (hooks) => {
assert.notOk(target.querySelector(".o_field_boolean input").disabled);
await click(target.querySelector(".o_field_boolean input"));
assert.containsOnce(target, ".o_field_boolean input:checked", "checkbox should be checked");
await click(target.querySelector(".o_form_button_save"));
await click(target.querySelector(".o_control_panel .o_form_button_save"));
await nextTick();
assert.notOk(webClient.env.services.router.current.hash.id);
@@ -928,12 +925,12 @@ QUnit.module("SettingsFormView", (hooks) => {
await click(target.querySelectorAll(".modal-footer .btn")[1]); // Stay Here
assert.containsOnce(target, ".o_form_view", "should be remain on form view");
await click(target.querySelector(".o_form_button_save")); // Form Save button
await click(target.querySelector(".o_control_panel .o_form_button_save")); // Form Save button
assert.containsNone(document.body, ".modal", "should not open a warning dialog");
assert.notOk(target.querySelector(".o_field_boolean input").disabled); // Everything must stay in edit
await click(target.querySelector(".o_field_boolean input"));
await click(target.querySelector(".o_form_button_cancel")); // Form Discard button
await click(target.querySelector(".o_control_panel .o_form_button_cancel")); // Form Discard button
assert.containsNone(document.body, ".modal", "should not open a warning dialog");
}
);
@@ -1138,10 +1135,18 @@ QUnit.module("SettingsFormView", (hooks) => {
".o_field_boolean input:checked",
"checkbox should not be checked"
);
assert.containsNone(target, ".o_dirty_warning", "warning message should not be shown");
assert.containsNone(
target,
".o_control_panel .o_dirty_warning",
"warning message should not be shown"
);
await click(target.querySelector(".o_field_boolean input[id=bar_0]"));
assert.containsOnce(target, ".o_field_boolean input:checked", "checkbox should be checked");
assert.containsOnce(target, ".o_dirty_warning", "warning message should be shown");
assert.containsOnce(
target,
".o_control_panel .o_dirty_warning",
"warning message should be shown"
);
});
QUnit.test(
@@ -1171,9 +1176,17 @@ QUnit.module("SettingsFormView", (hooks) => {
});
await click(target.querySelector("input[id=bar_0]"));
assert.containsOnce(target, ".o_dirty_warning", "warning message should be shown");
await click(target.querySelector(".o_form_button_save"));
assert.containsOnce(target, ".o_dirty_warning", "warning message should be shown");
assert.containsOnce(
target,
".o_control_panel .o_dirty_warning",
"warning message should be shown"
);
await click(target.querySelector(".o_control_panel .o_form_button_save"));
assert.containsOnce(
target,
".o_control_panel .o_dirty_warning",
"warning message should be shown"
);
}
);
@@ -1233,19 +1246,19 @@ QUnit.module("SettingsFormView", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 1);
assert.strictEqual($(target).find(".breadcrumb").text(), "First action");
assert.strictEqual($(target).find(".o_breadcrumb").text(), "First action");
await doAction(webClient, 2);
assert.strictEqual($(target).find(".breadcrumb").text(), "First actionSettings");
assert.strictEqual($(target).find(".o_breadcrumb").text(), "First actionSettings");
def = makeDeferred();
await click(target.querySelector('button[name="3"]'));
assert.strictEqual($(target).find(".breadcrumb").text(), "First actionSettings");
assert.strictEqual($(target).find(".o_breadcrumb").text(), "First actionSettings");
def.resolve();
await nextTick();
assert.strictEqual(
$(target).find(".breadcrumb").text(),
$(target).find(".o_breadcrumb").text(),
"First actionSettingsOther action"
);
}
@@ -1407,7 +1420,7 @@ QUnit.module("SettingsFormView", (hooks) => {
await click(target.querySelector(".o_field_boolean input"));
assert.containsOnce(target, ".o_field_boolean input:checked", "checkbox should be checked");
await click(target.querySelector(".o_form_button_cancel"));
await click(target.querySelector(".o_control_panel .o_form_button_cancel"));
assert.containsNone(
target,
@@ -1596,7 +1609,7 @@ QUnit.module("SettingsFormView", (hooks) => {
assert.containsOnce(target, "[name='textField'] input");
assert.verifySteps([
`focusin: <input type="text" class="o_searchview_input" accesskey="Q" placeholder="Search..." role="searchbox">`,
`focusin: <input type="text" class="o_searchview_input flex-grow-1 w-auto border-0" accesskey="Q" placeholder="Search..." role="searchbox">`,
]);
});