[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
@@ -16,11 +16,12 @@
position: 'bottom', position: 'bottom',
}, { }, {
trigger: '.o_data_row:first .o_data_cell', trigger: '.o_data_row:first .o_data_cell',
extra_trigger: '.breadcrumb', extra_trigger: '.o_breadcrumb',
}, { }, {
trigger: '.o_control_panel button:contains("' + _t('Print') + '")', trigger: '.o_control_panel .o_cp_action_menus .dropdown-toggle',
extra_trigger: '.o_breadcrumb .active:contains("INV/")',
}, { }, {
trigger: '.o_control_panel .o-dropdown--menu span:contains("' + _t('Invoices without Payment') + '")', trigger: '.o_control_panel .o_cp_action_menus .o_menu_item:contains("' + _t('Invoices without Payment') + '")',
}, { }, {
trigger: 'iframe .o_report_layout_standard h2', trigger: 'iframe .o_report_layout_standard h2',
content: 'Primary color is correct', content: 'Primary color is correct',
@@ -341,10 +341,11 @@ QUnit.module("Base Import Tests", (hooks) => {
"button has the right download url" "button has the right download url"
); );
assert.verifySteps(["partner/get_import_templates", "base_import.import/create"]); assert.verifySteps(["partner/get_import_templates", "base_import.import/create"]);
// Contains invisible mobile buttons
assert.containsN( assert.containsN(
target, target,
".o_control_panel button", ".o_control_panel button",
2, 5,
"only two buttons are visible by default" "only two buttons are visible by default"
); );
}); });
@@ -380,7 +381,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
assert.verifySteps([ assert.verifySteps([
"partner/get_import_templates", "partner/get_import_templates",
"base_import.import/create", "base_import.import/create",
@@ -515,8 +516,10 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await click(target.querySelector(".o_control_panel button:first-child")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
assert.verifySteps(["execute_import"]); assert.verifySteps(["execute_import"]);
}); });
@@ -533,7 +536,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
assert.containsOnce( assert.containsOnce(
target, target,
".o_import_data_sidepanel .o_import_formatting", ".o_import_data_sidepanel .o_import_formatting",
@@ -563,7 +566,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await nextTick(); await nextTick();
assert.containsOnce( assert.containsOnce(
@@ -604,7 +607,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(
target,
".o_control_panel_main_buttons .d-none input[type='file']",
file
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_sidepanel input[type=checkbox]").checked, target.querySelector(".o_import_data_sidepanel input[type=checkbox]").checked,
true, true,
@@ -637,7 +644,9 @@ QUnit.module("Base Import Tests", (hooks) => {
"as the column couldn't match with the database, user must make a choice" "as the column couldn't match with the database, user must make a choice"
); );
await click(target.querySelector(".o_control_panel button:first-child")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
assert.containsNone( assert.containsNone(
target, target,
".o_notification_body", ".o_notification_body",
@@ -660,7 +669,9 @@ QUnit.module("Base Import Tests", (hooks) => {
); );
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Display name"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Display name");
await click(target.querySelector(".o_control_panel button:first-child")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
assert.verifySteps([ assert.verifySteps([
"base_import.import/execute_import", "base_import.import/execute_import",
"1 records successfully imported", "1 records successfully imported",
@@ -700,10 +711,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
// For this test, we force the display of an error message if this field is set // For this test, we force the display of an error message if this field is set
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Selection"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Selection");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent, target.querySelector(".o_import_data_content .alert-danger").textContent,
"The file contains blocking errors (see below)", "The file contains blocking errors (see below)",
@@ -730,7 +743,9 @@ QUnit.module("Base Import Tests", (hooks) => {
"prevent option is selected by default" "prevent option is selected by default"
); );
editSelect(target, ".o_import_field_selection select", "item_2"); editSelect(target, ".o_import_field_selection select", "item_2");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-info").textContent, target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.", "Everything seems valid.",
@@ -774,10 +789,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
// For this test, we force the display of an error message if this field is set // For this test, we force the display of an error message if this field is set
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Bar"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Bar");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent, target.querySelector(".o_import_data_content .alert-danger").textContent,
"The file contains blocking errors (see below)", "The file contains blocking errors (see below)",
@@ -789,7 +806,9 @@ QUnit.module("Base Import Tests", (hooks) => {
"options are 'prevent', choose a default boolean value or 'skip'" "options are 'prevent', choose a default boolean value or 'skip'"
); );
editSelect(target, ".o_import_field_boolean select", "false"); editSelect(target, ".o_import_field_boolean select", "false");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-info").textContent, target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.", "Everything seems valid.",
@@ -837,10 +856,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
// For this test, we force the display of an error message if this field is set // For this test, we force the display of an error message if this field is set
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Many2Many"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Many2Many");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent, target.querySelector(".o_import_data_content .alert-danger").textContent,
"The file contains blocking errors (see below)", "The file contains blocking errors (see below)",
@@ -852,14 +873,18 @@ QUnit.module("Base Import Tests", (hooks) => {
"options are 'prevent', choose a default boolean value or 'skip'" "options are 'prevent', choose a default boolean value or 'skip'"
); );
editSelect(target, ".o_import_field_many2many select", "name_create_enabled_fields"); editSelect(target, ".o_import_field_many2many select", "name_create_enabled_fields");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-info").textContent, target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.", "Everything seems valid.",
"import is now successful" "import is now successful"
); );
editSelect(target, ".o_import_field_many2many select", "import_skip_records"); editSelect(target, ".o_import_field_many2many select", "import_skip_records");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-info").textContent, target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.", "Everything seems valid.",
@@ -914,8 +939,10 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await click(target.querySelector(".o_control_panel button:nth-child(1)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(1)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent, target.querySelector(".o_import_data_content .alert-danger").textContent,
"The file contains blocking errors (see below)", "The file contains blocking errors (see below)",
@@ -991,7 +1018,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
assert.strictEqual( assert.strictEqual(
target.querySelector("input#o_import_batch_limit").value, target.querySelector("input#o_import_batch_limit").value,
"2000", "2000",
@@ -1004,7 +1031,9 @@ QUnit.module("Base Import Tests", (hooks) => {
); );
await editInput(target, "input#o_import_batch_limit", 1); await editInput(target, "input#o_import_batch_limit", 1);
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-info").textContent, target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.", "Everything seems valid.",
@@ -1068,9 +1097,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await editInput(target, "input#o_import_batch_limit", 1); await editInput(target, "input#o_import_batch_limit", 1);
await click(target.querySelector(".o_control_panel button:first-child")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
// Since a nextTick is added to each batch, we must wait twice before the end of the second batch // Since a nextTick is added to each batch, we must wait twice before the end of the second batch
await nextTick(); await nextTick();
await nextTick(); await nextTick();
@@ -1086,7 +1117,8 @@ QUnit.module("Base Import Tests", (hooks) => {
"a message is shown to indicate the user to resume from the third row" "a message is shown to indicate the user to resume from the third row"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel button:first-child").textContent, target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
.textContent,
"Resume", "Resume",
"button contains the right text" "button contains the right text"
); );
@@ -1157,9 +1189,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await editInput(target, "input#o_import_batch_limit", 1); await editInput(target, "input#o_import_batch_limit", 1);
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
// Since a nextTick is added to each batch, we must wait twice before the end of the second batch // Since a nextTick is added to each batch, we must wait twice before the end of the second batch
await nextTick(); await nextTick();
await nextTick(); await nextTick();
@@ -1169,7 +1203,8 @@ QUnit.module("Base Import Tests", (hooks) => {
"Everything seems valid." "Everything seems valid."
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel button:first-child").textContent, target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
.textContent,
"Import", "Import",
"after testing, 'Resume' text is not shown" "after testing, 'Resume' text is not shown"
); );
@@ -1245,7 +1280,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(
target,
".o_control_panel_main_buttons .d-none input[type='file']",
file
);
assert.strictEqual( assert.strictEqual(
target.querySelector( target.querySelector(
@@ -1261,7 +1300,9 @@ QUnit.module("Base Import Tests", (hooks) => {
"The relational field should be selected by default and the name should be the full path." "The relational field should be selected by default and the name should be the full path."
); );
await click(target.querySelector(".o_control_panel button:first-child")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
} }
); );
@@ -1320,10 +1361,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
// For this test, we force the display of an error message if this field is set // For this test, we force the display of an error message if this field is set
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Many2Many"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Many2Many");
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(2)")
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent, target.querySelector(".o_import_data_content .alert-danger").textContent,
@@ -1387,13 +1430,17 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await editInput(target, ".o_import_date_format#date_format-3", "YYYYMMDD"); await editInput(target, ".o_import_date_format#date_format-3", "YYYYMMDD");
// Parse the file again with the updated date format to check that // Parse the file again with the updated date format to check that
// the format is correctly formatted in the UI // the format is correctly formatted in the UI
await click(target.querySelector(".o_import_formatting button")); await click(target.querySelector(".o_import_formatting button"));
await click(target.querySelector(".o_control_panel button:nth-child(2)")); await click(
$(target).find(
".o_control_panel_main_buttons > div:visible > button:contains(Import)"
)[0]
);
assert.verifySteps(["execute_import"]); assert.verifySteps(["execute_import"]);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_date_format").value, target.querySelector(".o_import_date_format").value,
@@ -1412,7 +1459,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Bar"); await editSelectMenu(target, ".o_import_data_content .o_select_menu", "Bar");
assert.containsN( assert.containsN(
target, target,
@@ -1444,7 +1491,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input // Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" }); const file = new File(["fake_file"], "fake_file.csv", { type: "text/plain" });
await editInput(target, "input[type='file']", file); await editInput(target, ".o_control_panel_collapsed_create input[type='file']", file);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_import_date_format").list.id, target.querySelector(".o_import_date_format").list.id,
"list-3", "list-3",
@@ -5,10 +5,9 @@ import { importRecordsItem } from "@base_import/import_records/import_records";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { click, getFixture, selectDropdownItem } from "@web/../tests/helpers/utils"; import { click, getFixture, selectDropdownItem } from "@web/../tests/helpers/utils";
import { toggleFavoriteMenu } from "@web/../tests/search/helpers"; import { toggleActionMenu } from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { clearRegistryWithCleanup } from "@web/../tests/helpers/mock_env";
const favoriteMenuRegistry = registry.category("favoriteMenu");
let serverData; let serverData;
let target; let target;
@@ -27,12 +26,14 @@ QUnit.module("Base Import Tests", (hooks) => {
}, },
}; };
setupViewRegistries(); setupViewRegistries();
favoriteMenuRegistry.add("import-menu", importRecordsItem); const cogMenuRegistry = registry.category("cogMenu");
clearRegistryWithCleanup(cogMenuRegistry);
cogMenuRegistry.add("import-menu", importRecordsItem);
}); });
QUnit.module("ImportRecords"); QUnit.module("ImportRecords");
QUnit.test("import in favorite dropdown in list", async function (assert) { QUnit.test("import in cog menu dropdown in list", async function (assert) {
assert.expect(3); assert.expect(3);
const actionService = { const actionService = {
@@ -56,14 +57,14 @@ QUnit.module("Base Import Tests", (hooks) => {
}, },
}); });
await toggleFavoriteMenu(target); await toggleActionMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu"); assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsOnce(target, ".o_import_menu"); assert.containsOnce(target, ".o_import_menu");
await click(target.querySelector(".o_import_menu")); await click(target.querySelector(".o_import_menu"));
}); });
QUnit.test( QUnit.test(
'import favorite dropdown item should not be in list with create="0"', 'import should not be available in cog menu dropdown in list with create="0"',
async function (assert) { async function (assert) {
await makeView({ await makeView({
type: "list", type: "list",
@@ -75,14 +76,14 @@ QUnit.module("Base Import Tests", (hooks) => {
}, },
}); });
await toggleFavoriteMenu(target); await toggleActionMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu"); assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu"); assert.containsNone(target, ".o_import_menu");
} }
); );
QUnit.test( QUnit.test(
'import favorite dropdown item should not be in list with import="0"', 'import should not be available in cog menu dropdown in list with import="0"',
async function (assert) { async function (assert) {
await makeView({ await makeView({
type: "list", type: "list",
@@ -94,13 +95,13 @@ QUnit.module("Base Import Tests", (hooks) => {
}, },
}); });
await toggleFavoriteMenu(target); await toggleActionMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu"); assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu"); assert.containsNone(target, ".o_import_menu");
} }
); );
QUnit.test("import in favorite dropdown in kanban", async function (assert) { QUnit.test("import in cog menu dropdown in kanban", async function (assert) {
assert.expect(3); assert.expect(3);
const actionService = { const actionService = {
@@ -131,14 +132,14 @@ QUnit.module("Base Import Tests", (hooks) => {
}, },
}); });
await toggleFavoriteMenu(target); await toggleActionMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu"); assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsOnce(target, ".o_import_menu"); assert.containsOnce(target, ".o_import_menu");
await click(target.querySelector(".o_import_menu")); await click(target.querySelector(".o_import_menu"));
}); });
QUnit.test( QUnit.test(
'import favorite dropdown item should not be in list with create="0"', 'import should not be available in cog menu dropdown in kanban with create="0"',
async function (assert) { async function (assert) {
await makeView({ await makeView({
type: "kanban", type: "kanban",
@@ -156,15 +157,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window", actionType: "ir.actions.act_window",
}, },
}); });
// Cog menu will not show when empty
await toggleFavoriteMenu(target); assert.containsNone(target, ".o_cp_action_menus");
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
} }
); );
QUnit.test( QUnit.test(
'import dropdown favorite should not be in kanban with import="0"', 'import should not be available in cog menu dropdown in kanban with import="0"',
async function (assert) { async function (assert) {
await makeView({ await makeView({
type: "kanban", type: "kanban",
@@ -182,15 +181,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window", actionType: "ir.actions.act_window",
}, },
}); });
// Cog menu will not show when empty
await toggleFavoriteMenu(target); assert.containsNone(target, ".o_cp_action_menus");
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
} }
); );
QUnit.test( QUnit.test(
"import should not be available in favorite dropdown in pivot (other than kanban or list)", "import should not be available in cog menu dropdown in pivot (other than kanban or list)",
async function (assert) { async function (assert) {
serverData.models.foo.fields.foobar = { serverData.models.foo.fields.foobar = {
string: "Fubar", string: "Fubar",
@@ -207,15 +204,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window", actionType: "ir.actions.act_window",
}, },
}); });
// Cog menu will not show when empty
await toggleFavoriteMenu(target); assert.containsNone(target, ".o_cp_action_menus");
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
} }
); );
QUnit.test( QUnit.test(
"import should not be available in favorite dropdown in dialog view", "import should not be available in cog menu dropdown in dialog view",
async function (assert) { async function (assert) {
serverData.models.bar = { serverData.models.bar = {
fields: { fields: {
@@ -244,8 +239,8 @@ QUnit.module("Base Import Tests", (hooks) => {
await selectDropdownItem(target, "m2o", "Search More..."); await selectDropdownItem(target, "m2o", "Search More...");
const dialog = target.querySelector(".modal"); const dialog = target.querySelector(".modal");
await toggleFavoriteMenu(dialog); await toggleActionMenu(dialog);
assert.containsOnce(dialog, ".o_favorite_menu .o-dropdown--menu"); assert.containsOnce(dialog, ".o_cp_action_menus .o-dropdown--menu");
assert.containsNone(dialog, ".o_import_menu"); assert.containsNone(dialog, ".o_import_menu");
} }
); );
@@ -12,10 +12,7 @@ import {
applyGroup, applyGroup,
removeFacet, removeFacet,
toggleAddCustomGroup, toggleAddCustomGroup,
toggleComparisonMenu, toggleSearchBarMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
@@ -142,13 +139,11 @@ QUnit.module("Board", (hooks) => {
await click(document.querySelector(".o_column_sortable")); await click(document.querySelector(".o_column_sortable"));
// Group It // Group It
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
await applyGroup(target); await applyGroup(target);
// add this action to dashboard // add this action to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter"); await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter");
await testUtils.fields.editInput($(".o_add_to_board input"), "a name"); await testUtils.fields.editInput($(".o_add_to_board input"), "a name");
await testUtils.dom.click($(".o_add_to_board .dropdown-menu button")); await testUtils.dom.click($(".o_add_to_board .dropdown-menu button"));
@@ -202,11 +197,10 @@ QUnit.module("Board", (hooks) => {
var filter_count = 0; var filter_count = 0;
// Add a first filter // Add a first filter
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter on a"); await toggleMenuItem(target, "Filter on a");
// Add it to dashboard // Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter"); await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter");
await testUtils.dom.click($(".o_add_to_board .dropdown-menu button")); await testUtils.dom.click($(".o_add_to_board .dropdown-menu button"));
@@ -214,11 +208,10 @@ QUnit.module("Board", (hooks) => {
await removeFacet(target); await removeFacet(target);
// Add the second filter // Add the second filter
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter on b"); await toggleMenuItem(target, "Filter on b");
// Add it to dashboard // Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent( await testUtils.dom.triggerEvent(
target.querySelector(".o_add_to_board button.dropdown-toggle"), target.querySelector(".o_add_to_board button.dropdown-toggle"),
"mouseenter" "mouseenter"
@@ -263,11 +256,10 @@ QUnit.module("Board", (hooks) => {
}); });
// Add a filter // Add a filter
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter"); await toggleMenuItem(target, "Filter");
// Add it to dashboard // Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent( await testUtils.dom.triggerEvent(
target.querySelector(".o_add_to_board button.dropdown-toggle"), target.querySelector(".o_add_to_board button.dropdown-toggle"),
"mouseenter" "mouseenter"
@@ -292,7 +284,7 @@ QUnit.module("Board", (hooks) => {
type: "ir.actions.act_window", type: "ir.actions.act_window",
views: [[false, "pivot"]], views: [[false, "pivot"]],
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
assert.containsNone(target, ".o_add_to_board"); assert.containsNone(target, ".o_add_to_board");
// Sanity check // Sanity check
@@ -302,7 +294,7 @@ QUnit.module("Board", (hooks) => {
type: "ir.actions.act_window", type: "ir.actions.act_window",
views: [[false, "pivot"]], views: [[false, "pivot"]],
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
assert.containsOnce(target, ".o_add_to_board"); assert.containsOnce(target, ".o_add_to_board");
}); });
@@ -357,16 +349,14 @@ QUnit.module("Board", (hooks) => {
}); });
// filter on July 2020 // filter on July 2020
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "July"); await toggleMenuItemOption(target, "Date", "July");
// compare July 2020 to June 2020 // compare July 2020 to June 2020
await toggleComparisonMenu(target); await toggleMenuItem(target.querySelector(".o_comparison_menu"), 0);
await toggleMenuItem(target, 0);
// add the view to the dashboard // add the view to the dashboard
await toggleFavoriteMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle")); await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input"); const input = target.querySelector(".o_add_to_board .dropdown-menu input");
@@ -403,7 +393,7 @@ QUnit.module("Board", (hooks) => {
views: [[false, "pivot"]], views: [[false, "pivot"]],
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle")); await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input"); const input = target.querySelector(".o_add_to_board .dropdown-menu input");
await testUtils.fields.editInput(input, "Pipeline"); await testUtils.fields.editInput(input, "Pipeline");
@@ -445,7 +435,7 @@ QUnit.module("Board", (hooks) => {
context: { search_default_filter: 1 }, context: { search_default_filter: 1 },
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle")); await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input"); const input = target.querySelector(".o_add_to_board .dropdown-menu input");
await testUtils.fields.editInput(input, "Pipeline"); await testUtils.fields.editInput(input, "Pipeline");
+4 -1
View File
@@ -131,7 +131,10 @@ QUnit.module("Board", (hooks) => {
return Promise.resolve(true); return Promise.resolve(true);
} }
if (args.method === "get_views" && args.model == "partner") { if (args.method === "get_views" && args.model == "partner") {
assert.deepEqual(args.kwargs.views.find((v) => v[1] === 'list'), [4, "list"]); assert.deepEqual(
args.kwargs.views.find((v) => v[1] === "list"),
[4, "list"]
);
} }
}, },
}); });
@@ -3,8 +3,7 @@
import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
import { menuService } from "@web/webclient/menus/menu_service"; import { menuService } from "@web/webclient/menus/menu_service";
import { import {
toggleFilterMenu, toggleSearchBarMenu,
toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
@@ -115,7 +114,7 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bar"); await toggleMenuItem(target, "Bar");
await toggleMenuItem(target, "Date Field"); await toggleMenuItem(target, "Date Field");
@@ -123,7 +122,6 @@ QUnit.module("Views", (hooks) => {
await toggleMenuItemOption(target, "Date Field", "Year"); await toggleMenuItemOption(target, "Date Field", "Year");
await toggleFilterMenu(target);
await toggleMenuItem(target, "Forecast Filter"); await toggleMenuItem(target, "Forecast Filter");
unpatchDate(); unpatchDate();
@@ -98,7 +98,7 @@ QUnit.module('Google Calendar', {
}, function () { }, function () {
QUnit.test('sync google calendar', async function (assert) { QUnit.test('sync google calendar', async function (assert) {
assert.expect(11); assert.expect(13);
let id = 7; let id = 7;
await makeView({ await makeView({
@@ -136,8 +136,11 @@ QUnit.module('Google Calendar', {
// sync_data was called a first time without filter, event from google calendar was created twice // sync_data was called a first time without filter, event from google calendar was created twice
assert.containsN(target, '.fc-event-container', 4, "should display 4 events on the month"); assert.containsN(target, '.fc-event-container', 4, "should display 4 events on the month");
await click(target.querySelector('.o_calendar_button_next')); await click(target.querySelector('.ui-datepicker-next'));
await click(target.querySelector('.o_calendar_button_prev')); await click(target.querySelector('.ui-datepicker-calendar > tbody > tr:nth-child(2) > td:nth-child(4) > a'));
await click(target.querySelector('.o_view_scale_selector .dropdown-toggle'));
await click(target.querySelector('.o_scale_button_month'));
await click(target.querySelector('.o_calendar_button_today'));
assert.verifySteps([ assert.verifySteps([
'/google_calendar/sync_data', '/google_calendar/sync_data',
@@ -148,8 +151,10 @@ QUnit.module('Google Calendar', {
'/web/dataset/call_kw/calendar.event/search_read', '/web/dataset/call_kw/calendar.event/search_read',
'/google_calendar/sync_data', '/google_calendar/sync_data',
'/web/dataset/call_kw/calendar.event/search_read', '/web/dataset/call_kw/calendar.event/search_read',
"/google_calendar/sync_data",
"/web/dataset/call_kw/calendar.event/search_read",
], 'should do a search_read before and after the call to sync_data'); ], 'should do a search_read before and after the call to sync_data');
assert.containsN(target, '.fc-event-container', 6, "should now display 6 events on the month"); assert.containsN(target, '.fc-event-container', 7, "should now display 7 events on the month");
}); });
}); });
@@ -214,22 +214,22 @@ QUnit.test("many2many_avatar_employee widget in form view", async function (asse
}); });
assert.containsN( assert.containsN(
document.body, document.body,
".o_field_many2many_avatar_employee .badge", ".o_field_many2many_avatar_employee .o_tag",
2, 2,
"should have 2 records" "should have 2 records"
); );
assert.strictEqual( assert.strictEqual(
document document
.querySelector(".o_field_many2many_avatar_employee .badge img") .querySelector(".o_field_many2many_avatar_employee .o_tag img")
.getAttribute("data-src"), .getAttribute("data-src"),
`/web/image/hr.employee.public/${employeeId_1}/avatar_128` `/web/image/hr.employee.public/${employeeId_1}/avatar_128`
); );
await dom.click( await dom.click(
document.querySelector(".o_field_many2many_avatar_employee .badge .o_m2m_avatar") document.querySelector(".o_field_many2many_avatar_employee .o_tag .o_m2m_avatar")
); );
await dom.click( await dom.click(
document.querySelectorAll(".o_field_many2many_avatar_employee .badge .o_m2m_avatar")[1] document.querySelectorAll(".o_field_many2many_avatar_employee .o_tag .o_m2m_avatar")[1]
); );
assert.verifySteps([ assert.verifySteps([
`read m2x.avatar.employee ${avatarId_1}`, `read m2x.avatar.employee ${avatarId_1}`,
@@ -413,19 +413,19 @@ QUnit.test(
res_id: avatarId, res_id: avatarId,
views: [[false, "form"]], views: [[false, "form"]],
}); });
assert.containsN(document.body, ".o_field_many2many_avatar_employee .badge", 2); assert.containsN(document.body, ".o_field_many2many_avatar_employee .o_tag", 2);
assert.strictEqual( assert.strictEqual(
document document
.querySelector(".o_field_many2many_avatar_employee .badge img") .querySelector(".o_field_many2many_avatar_employee .o_tag img")
.getAttribute("data-src"), .getAttribute("data-src"),
`/web/image/hr.employee.public/${employeeId_1}/avatar_128` `/web/image/hr.employee.public/${employeeId_1}/avatar_128`
); );
await dom.click( await dom.click(
document.querySelector(".o_field_many2many_avatar_employee .badge .o_m2m_avatar") document.querySelector(".o_field_many2many_avatar_employee .o_tag .o_m2m_avatar")
); );
await dom.click( await dom.click(
document.querySelectorAll(".o_field_many2many_avatar_employee .badge .o_m2m_avatar")[1] document.querySelectorAll(".o_field_many2many_avatar_employee .o_tag .o_m2m_avatar")[1]
); );
assert.verifySteps([ assert.verifySteps([
`read m2x.avatar.employee ${employeeId_1}`, `read m2x.avatar.employee ${employeeId_1}`,
@@ -82,10 +82,5 @@ registry.category("web_tour.tours").add('hr_holidays_tour', {
trigger: 'button[name="action_approve"]', trigger: 'button[name="action_approve"]',
content: _t("Let's approve it"), content: _t("Let's approve it"),
position: 'bottom' position: 'bottom'
},
{
trigger: 'a[data-menu-xmlid="hr_holidays.menu_hr_holidays_root"]',
content: _t("State is now confirmed. We can go back to the calendar"),
position: 'bottom'
} }
]}); ]});
@@ -147,9 +147,4 @@ registry.category("web_tour.tours").add('hr_skills_tour', {
run: () => {}, run: () => {},
}, },
...stepUtils.saveForm(), ...stepUtils.saveForm(),
{
content: "Go back to employees",
trigger: 'a[data-menu-xmlid="hr.menu_hr_root"]',
run: "click",
}
]}); ]});
@@ -46,9 +46,9 @@ function compileChatter(node, params) {
hasParentReloadOnFollowersUpdate, hasParentReloadOnFollowersUpdate,
hasParentReloadOnMessagePosted, hasParentReloadOnMessagePosted,
isAttachmentBoxVisibleInitially, isAttachmentBoxVisibleInitially,
threadId: "__comp__.props.record.model.root.resId or undefined", threadId: "__comp__.props.record.resId or undefined",
threadModel: "__comp__.props.record.model.root.resModel", threadModel: "__comp__.props.record.resModel",
webRecord: "__comp__.props.record.model.root", webRecord: "__comp__.props.record",
saveRecord: "() => __comp__.saveButtonClicked and __comp__.saveButtonClicked()", saveRecord: "() => __comp__.saveButtonClicked and __comp__.saveButtonClicked()",
}); });
const chatterContainerHookXml = createElement("div"); const chatterContainerHookXml = createElement("div");
@@ -63,8 +63,8 @@ function compileAttachmentPreview(node, params) {
const webClientViewAttachmentViewContainerXml = createElement("t"); const webClientViewAttachmentViewContainerXml = createElement("t");
setAttributes(webClientViewAttachmentViewContainerXml, { setAttributes(webClientViewAttachmentViewContainerXml, {
"t-component": "__comp__.mailComponents.AttachmentView", "t-component": "__comp__.mailComponents.AttachmentView",
threadId: "__comp__.props.record.model.root.resId or undefined", threadId: "__comp__.props.record.resId or undefined",
threadModel: "__comp__.props.record.model.root.resModel", threadModel: "__comp__.props.record.resModel",
}); });
append(webClientViewAttachmentViewContainerHookXml, webClientViewAttachmentViewContainerXml); append(webClientViewAttachmentViewContainerHookXml, webClientViewAttachmentViewContainerXml);
return webClientViewAttachmentViewContainerHookXml; return webClientViewAttachmentViewContainerHookXml;
@@ -1994,6 +1994,6 @@ QUnit.test(
await click(".o-mail-NotificationItem:contains(General)"); await click(".o-mail-NotificationItem:contains(General)");
await click(".o-mail-ChatWindow [title='Open in Discuss']"); await click(".o-mail-ChatWindow [title='Open in Discuss']");
await click(".o-mail-DiscussCategoryItem:contains(General) [title='Channel settings']"); await click(".o-mail-DiscussCategoryItem:contains(General) [title='Channel settings']");
assert.strictEqual($(".breadcrumb").text(), "DiscussGeneral"); assert.strictEqual($(".o_breadcrumb").text(), "DiscussGeneral");
} }
); );
@@ -190,10 +190,10 @@ QUnit.test("Composer type is kept when switching from aside to bottom", async (a
}); });
assert.hasClass( assert.hasClass(
$("button:contains(Log note)"), $("button:contains(Log note)"),
"btn-odoo", "btn-primary",
"Active button should be the log note button" "Active button should be the log note button"
); );
assert.doesNotHaveClass($("button:contains(Send message)"), "btn-odoo"); assert.doesNotHaveClass($("button:contains(Send message)"), "btn-primary");
}); });
QUnit.test("chatter: drop attachments", async (assert) => { QUnit.test("chatter: drop attachments", async (assert) => {
@@ -54,5 +54,8 @@ QUnit.test("Manage Messages", async (assert) => {
await click(dropdownItems[0]); await click(dropdownItems[0]);
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.verifySteps(["message_read"]); assert.verifySteps(["message_read"]);
assert.strictEqual($(".breadcrumb-item.active")[0].innerText.trim(), "Manage Messages"); assert.strictEqual(
target.querySelector(".o_breadcrumb .active > span").innerText.trim(),
"Manage Messages"
);
}); });
@@ -330,9 +330,9 @@ QUnit.test(
views: [[false, "form"]], views: [[false, "form"]],
}); });
assert.strictEqual( assert.strictEqual(
$(".o_field_many2many_avatar_user.o_field_widget .badge img")[0].getAttribute( document.body
"data-src" .querySelector(".o_field_many2many_avatar_user.o_field_widget .o_avatar img")
), .getAttribute("data-src"),
`/web/image/res.users/${userId}/avatar_128` `/web/image/res.users/${userId}/avatar_128`
); );
} }
@@ -374,7 +374,7 @@ QUnit.test("many2many_avatar_user widget in form view", async (assert) => {
res_id: avatarUserId, res_id: avatarUserId,
views: [[false, "form"]], views: [[false, "form"]],
}); });
await click(document.body, ".o_field_many2many_avatar_user .badge .o_m2m_avatar"); await click(document.body, ".o_field_many2many_avatar_user .o_avatar img");
assert.containsOnce($, ".o-mail-ChatWindow"); assert.containsOnce($, ".o-mail-ChatWindow");
assert.strictEqual($(".o-mail-ChatWindow-name").text(), "Partner 1"); assert.strictEqual($(".o-mail-ChatWindow-name").text(), "Partner 1");
}); });
@@ -70,12 +70,12 @@ QUnit.test("Form view not scrolled when switching record", async (assert) => {
}, },
{ resIds: [partnerId_1, partnerId_2] } { resIds: [partnerId_1, partnerId_2] }
); );
assert.strictEqual($(".breadcrumb-item.active").text(), "Partner 1"); assert.strictEqual($(".o_breadcrumb .active").text(), "Partner 1");
assert.strictEqual($(".o_content")[0].scrollTop, 0); assert.strictEqual($(".o_content")[0].scrollTop, 0);
$(".o_content")[0].scrollTop = 150; $(".o_content")[0].scrollTop = 150;
await click(".o_pager_next"); await click(".o_pager_next");
assert.strictEqual($(".breadcrumb-item.active").text(), "Partner 2"); assert.strictEqual($(".o_breadcrumb .active").text(), "Partner 2");
assert.strictEqual($(".o_content")[0].scrollTop, 0); assert.strictEqual($(".o_content")[0].scrollTop, 0);
await click(".o_pager_previous"); await click(".o_pager_previous");
@@ -16,5 +16,5 @@ class TestUserModifyOwnProfile(HttpCase):
# avoid 'reload_context' action in the middle of the tour to ease steps and form save checks # avoid 'reload_context' action in the middle of the tour to ease steps and form save checks
with patch.object(Users, 'preference_save', lambda self: True): with patch.object(Users, 'preference_save', lambda self: True):
self.start_tour("/web", "mail/static/tests/tours/user_modify_own_profile_tour.js", login="demo") self.start_tour("/web", "mail/static/tests/tours/user_modify_own_profile_tour.js", login="demo", step_delay=100)
self.assertEqual(self.env.ref('base.user_demo').email, "updatedemail@example.com") self.assertEqual(self.env.ref('base.user_demo').email, "updatedemail@example.com")
@@ -38,7 +38,7 @@ registry.category("web_tour.tours").add('project_tour', {
actions.auto('.modal:visible .btn.btn-primary'); actions.auto('.modal:visible .btn.btn-primary');
}, },
}, { }, {
trigger: ".o_kanban_project_tasks .o_column_quick_create .input-group .o_input", trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_header input",
content: Markup(_t("Add columns to organize your tasks into <b>stages</b> <i>e.g. New - In Progress - Done</i>.")), content: Markup(_t("Add columns to organize your tasks into <b>stages</b> <i>e.g. New - In Progress - Done</i>.")),
position: 'bottom', position: 'bottom',
run: "text Test", run: "text Test",
@@ -46,7 +46,7 @@ registry.category("web_tour.tours").add('project_tour', {
trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_add", trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_add",
position: 'right', position: 'right',
}, { }, {
trigger: ".o_kanban_project_tasks .o_column_quick_create .input-group .o_input", trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_header input",
extra_trigger: '.o_kanban_group', extra_trigger: '.o_kanban_group',
content: Markup(_t("Add columns to organize your tasks into <b>stages</b> <i>e.g. New - In Progress - Done</i>.")), content: Markup(_t("Add columns to organize your tasks into <b>stages</b> <i>e.g. New - In Progress - Done</i>.")),
position: 'bottom', position: 'bottom',
@@ -2,7 +2,7 @@
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
import { setupControlPanelServiceRegistry, toggleGroupByMenu, toggleMenuItem, toggleMenuItemOption } from "@web/../tests/search/helpers"; import { setupControlPanelServiceRegistry, toggleSearchBarMenu, toggleMenuItem, toggleMenuItemOption } from "@web/../tests/search/helpers";
import { makeView } from "@web/../tests/views/helpers"; import { makeView } from "@web/../tests/views/helpers";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { makeFakeNotificationService, fakeCookieService } from "@web/../tests/helpers/mock_services"; import { makeFakeNotificationService, fakeCookieService } from "@web/../tests/helpers/mock_services";
@@ -133,7 +133,7 @@ QUnit.module("Project", {}, () => {
} }
async function openGroupByMainMenu(target) { async function openGroupByMainMenu(target) {
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
} }
async function openGroupByDateMenu(target) { async function openGroupByDateMenu(target) {
@@ -164,12 +164,8 @@ QUnit.module("Project", {}, () => {
QUnit.test("check that removing the group by 'Date: Month > Stage' in the search bar triggers a notification", async function (assert) { QUnit.test("check that removing the group by 'Date: Month > Stage' in the search bar triggers a notification", async function (assert) {
const stepsTriggeringNotification = async () => { const stepsTriggeringNotification = async () => {
const removeFilterXpath = `//div[contains(@class, 'o_searchview_facet')] // There's only one possibility here
[.//span[@class='o_facet_value'] await click(target, ".o_facet_remove");
[contains(., 'Date: Month')]]
/i[contains(@class, 'o_facet_remove')]`;
const removeFilterElement = getFirstElementForXpath(target, removeFilterXpath);
await click(removeFilterElement);
}; };
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert); await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
}); });
@@ -216,7 +212,7 @@ QUnit.module("Project", {}, () => {
function checkGroupByOrder(assert) { function checkGroupByOrder(assert) {
const dateSearchFacetXpath = `//div[contains(@class, 'o_searchview_facet')] const dateSearchFacetXpath = `//div[contains(@class, 'o_searchview_facet')]
[.//span[@class='o_facet_value'] [.//small[@class='o_facet_value']
[contains(., 'Date: Month')]]`; [contains(., 'Date: Month')]]`;
const dateSearchFacetElement = getFirstElementForXpath(target, dateSearchFacetXpath); const dateSearchFacetElement = getFirstElementForXpath(target, dateSearchFacetXpath);
const dateSearchFacetParts = dateSearchFacetElement.querySelectorAll('.o_facet_value'); const dateSearchFacetParts = dateSearchFacetElement.querySelectorAll('.o_facet_value');
@@ -16,7 +16,7 @@ registry.category("web_tour.tours").add('burndown_chart_tour', {
trigger: '.o_kanban_record:contains("Burndown Chart Test") .o_kanban_manage_reporting div[role="menuitem"] a:contains("Burndown Chart")', trigger: '.o_kanban_record:contains("Burndown Chart Test") .o_kanban_manage_reporting div[role="menuitem"] a:contains("Burndown Chart")',
}, { }, {
content: 'The sort buttons are not rendered', content: 'The sort buttons are not rendered',
trigger: '.o_cp_bottom_left:not(:has(.btn-group[role=toolbar][aria-label="Sort graph"]))', trigger: '.o_graph_renderer:not(:has(.btn-group[role=toolbar][aria-label="Sort graph"]))',
extra_trigger: '.o_graph_renderer', extra_trigger: '.o_graph_renderer',
}, { }, {
content: 'Remove the project search "Burndown Chart Test"', content: 'Remove the project search "Burndown Chart Test"',
@@ -35,8 +35,8 @@ registry.category("web_tour.tours").add('burndown_chart_tour', {
content: 'A "The Burndown Chart must be grouped by Date and Stage" notification is shown when trying to remove the group by "Date: Month > Stage"', content: 'A "The Burndown Chart must be grouped by Date and Stage" notification is shown when trying to remove the group by "Date: Month > Stage"',
trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date and Stage") button.o_notification_close', trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date and Stage") button.o_notification_close',
}, { }, {
content: 'Open the group by menu', content: 'Open the search panel menu',
trigger: '.o_group_by_menu button', trigger: '.o_control_panel .o_searchview_dropdown_toggler',
}, { }, {
content: 'The Stage group menu item is invisible', content: 'The Stage group menu item is invisible',
trigger: '.o_group_by_menu:not(:has(.o_menu_item:contains("Stage")))', trigger: '.o_group_by_menu:not(:has(.o_menu_item:contains("Stage")))',
@@ -56,8 +56,8 @@ registry.category("web_tour.tours").add('burndown_chart_tour', {
content: 'A "The Burndown Chart must be grouped by Date" notification is shown when trying to remove the group by "Date: Month > Stage"', content: 'A "The Burndown Chart must be grouped by Date" notification is shown when trying to remove the group by "Date: Month > Stage"',
trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date") button.o_notification_close', trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date") button.o_notification_close',
}, { }, {
content: 'Open the filter menu', content: 'Open the search panel menu',
trigger: '.o_filter_menu button', trigger: '.o_control_panel .o_searchview_dropdown_toggler',
}, { }, {
content: 'Open the Date filter sub menu', content: 'Open the Date filter sub menu',
trigger: '.o_filter_menu button.o_menu_item:contains("Date")', trigger: '.o_filter_menu button.o_menu_item:contains("Date")',
@@ -73,7 +73,10 @@ registry.category("web_tour.tours").add('burndown_chart_tour', {
}, { }, {
content: 'Close the Date filter menu', content: 'Close the Date filter menu',
trigger: '.o_graph_renderer', trigger: '.o_graph_renderer',
}, {
content: 'Open the search panel menu',
trigger: '.o_control_panel .o_searchview_dropdown_toggler',
}, { }, {
content: 'The comparison menu is not rendered', content: 'The comparison menu is not rendered',
trigger: '.o_search_options:not(:has(.o_comparison_menu))', trigger: ':not(:has(.o_comparison_menu))',
}]}); }]});
@@ -62,38 +62,23 @@ const projectSharingSteps = [...stepUtils.goToAppSteps("project.menu_main_pm", '
trigger: 'iframe ol.breadcrumb > li.o_back_button > a:contains(Project Sharing)', trigger: 'iframe ol.breadcrumb > li.o_back_button > a:contains(Project Sharing)',
content: 'Go back to the kanban view', content: 'Go back to the kanban view',
}, { }, {
trigger: 'iframe .o_filter_menu > button', trigger: 'iframe .o_searchview_dropdown_toggler',
content: 'click on filter menu in the search view', content: 'open the search panel menu',
}, { }, {
trigger: 'iframe .o_filter_menu > .dropdown-menu > .dropdown-item:first-child', trigger: 'iframe .o_filter_menu .dropdown-item:first-child',
content: 'click on the first item in the filter menu', content: 'click on the first item in the filter menu',
}, { }, {
trigger: 'iframe .o_group_by_menu > button', trigger: 'iframe .o_group_by_menu .dropdown-item:first-child',
content: 'click on group by menu in the search view',
}, {
trigger: 'iframe .o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
content: 'click on the first item in the group by menu', content: 'click on the first item in the group by menu',
}, {
trigger: 'iframe .o_favorite_menu > button',
content: 'click on the favorite menu in the search view',
}, { }, {
trigger: 'iframe .o_favorite_menu .o_add_favorite > button', trigger: 'iframe .o_favorite_menu .o_add_favorite > button',
content: 'click to "save current search" button in favorite menu', content: 'click to "save current search" button in favorite menu',
}, { }, {
trigger: 'iframe .o_filter_menu > button', trigger: 'iframe .o_filter_menu .dropdown-item:first-child',
content: 'click on filter menu in the search view',
}, {
trigger: 'iframe .o_filter_menu > .dropdown-menu > .dropdown-item:first-child',
content: 'click on the first item in the filter menu', content: 'click on the first item in the filter menu',
}, { }, {
trigger: 'iframe .o_group_by_menu > button', trigger: 'iframe .o_group_by_menu .dropdown-item:first-child',
content: 'click on group by menu in the search view',
}, {
trigger: 'iframe .o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
content: 'click on the first item in the group by menu', content: 'click on the first item in the group by menu',
}, {
trigger: 'iframe .o_favorite_menu > button',
content: 'click on the favorite menu in the search view',
}, { }, {
trigger: 'iframe .o_favorite_menu .o_add_favorite > button', trigger: 'iframe .o_favorite_menu .o_add_favorite > button',
content: 'click to "save current search" button in favorite menu', content: 'click to "save current search" button in favorite menu',
@@ -14,8 +14,8 @@ PurchaseAdditionalTourSteps.include({
_get_purchase_stock_steps: function () { _get_purchase_stock_steps: function () {
this._super.apply(this, arguments); this._super.apply(this, arguments);
return [{ return [{
trigger: ".oe_button_box button[name='action_view_picking']", trigger: ".o-form-buttonbox button[name='action_view_picking']",
extra_trigger: ".oe_button_box button[name='action_view_picking']", extra_trigger: ".o-form-buttonbox button[name='action_view_picking']",
content: _t("Receive the ordered products."), content: _t("Receive the ordered products."),
position: "bottom", position: "bottom",
run: 'click', run: 'click',
@@ -185,7 +185,7 @@ registry.category("web_tour.tours").add('sale_timesheet_tour', {
content: 'Set Project name', content: 'Set Project name',
run: 'text Project with employee mapping', run: 'text Project with employee mapping',
}, { }, {
trigger: '.dropdown-item[data-menu-xmlid="project.menu_main_pm"]', trigger: '[data-menu-xmlid="project.menu_projects"]',
content: 'Select Project main menu', content: 'Select Project main menu',
}, { }, {
trigger: '.o_kanban_record:contains("Project for Freeman") .o_dropdown_kanban .dropdown-toggle', trigger: '.o_kanban_record:contains("Project for Freeman") .o_dropdown_kanban .dropdown-toggle',
@@ -231,7 +231,7 @@ registry.category("web_tour.tours").add('sale_timesheet_tour', {
// timer: 300, // timer: 300,
isCheck: true, isCheck: true,
}, { }, {
trigger: ".o_rightpanel_section .oe_button_box .o_stat_text:contains('Sales Orders')", trigger: ".o_rightpanel_section .o-form-buttonbox .o_stat_text:contains('Sales Orders')",
content: 'Check the user sees Sales Orders Stat Button', content: 'Check the user sees Sales Orders Stat Button',
isCheck: true, isCheck: true,
}, { }, {
@@ -174,7 +174,7 @@ QUnit.test(
const serverData = getServerData(spreadsheetData); const serverData = getServerData(spreadsheetData);
const fixture = getFixture(); const fixture = getFixture();
await createSpreadsheetDashboard({ serverData }); await createSpreadsheetDashboard({ serverData });
const year = fixture.querySelector(".o_cp_top_right input.o_datetime_input"); const year = fixture.querySelector(".o_control_panel_actions input.o_datetime_input");
const this_year = luxon.DateTime.local().year; const this_year = luxon.DateTime.local().year;
assert.equal(year.value, String(this_year)); assert.equal(year.value, String(this_year));
const input = fixture.querySelector("input.o_datetime_input"); const input = fixture.querySelector("input.o_datetime_input");
@@ -183,10 +183,10 @@ QUnit.test(
await nextTick(); await nextTick();
assert.equal(year.value, String(this_year - 1)); assert.equal(year.value, String(this_year - 1));
assert.containsOnce(fixture, ".o_cp_top_right .fa-times"); assert.containsOnce(fixture, ".o_control_panel_actions .fa-times");
await click(fixture.querySelector(".o_cp_top_right .fa-times")); await click(fixture.querySelector(".o_control_panel_actions .fa-times"));
assert.containsNone(fixture, ".o_cp_top_right .fa-times"); assert.containsNone(fixture, ".o_control_panel_actions .fa-times");
assert.equal(year.placeholder, "Select year..."); assert.equal(year.placeholder, "Select year...");
} }
); );
@@ -88,10 +88,10 @@ QUnit.module(
assert.containsN(target, '.o_data_row', 3, "should have 3 records"); assert.containsN(target, '.o_data_row', 3, "should have 3 records");
// Create a new line... // Create a new line...
await click(target.querySelector(".o_list_button_add")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"));
await editInput(target, "[name=name] input", 'Bilou'); await editInput(target, "[name=name] input", 'Bilou');
await editInput(target, "[name=age] input", '24'); await editInput(target, "[name=age] input", '24');
await click(target.querySelector(".o_list_button_save")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"));
// Check new record is in the list // Check new record is in the list
assert.containsN(target, '.o_data_row', 4, "should now have 4 records"); assert.containsN(target, '.o_data_row', 4, "should now have 4 records");
@@ -117,10 +117,10 @@ QUnit.module(
// Create a new line for an existing record... // Create a new line for an existing record...
let name = serverData.models.person.records[2].name, age = '72'; let name = serverData.models.person.records[2].name, age = '72';
await click(target.querySelector(".o_list_button_add")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"));
await editInput(target, "[name=name] input", name); await editInput(target, "[name=name] input", name);
await editInput(target, "[name=age] input", age); await editInput(target, "[name=age] input", age);
await click(target.querySelector(".o_list_button_save")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"));
// Check we still have 3 records... // Check we still have 3 records...
assert.containsN(target, '.o_data_row', 3, "should still have 3 records"); assert.containsN(target, '.o_data_row', 3, "should still have 3 records");
@@ -157,7 +157,7 @@ QUnit.module(
await click(target, ".o_group_field_row_add a"); await click(target, ".o_group_field_row_add a");
await editInput(target, "[name=name] input", name); await editInput(target, "[name=name] input", name);
await editInput(target, "[name=age] input", age); await editInput(target, "[name=age] input", age);
await click(target.querySelector(".o_list_button_save")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"));
// Check we have 2 records... // Check we have 2 records...
assert.containsN(target, '.o_data_row', 2, "should have 2 records"); assert.containsN(target, '.o_data_row', 2, "should have 2 records");
@@ -167,7 +167,7 @@ QUnit.module(
await click(target, ".o_group_field_row_add a"); await click(target, ".o_group_field_row_add a");
await editInput(target, "[name=name] input", name); await editInput(target, "[name=name] input", name);
await editInput(target, "[name=age] input", age); await editInput(target, "[name=age] input", age);
await click(target.querySelector(".o_list_button_save")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"));
// Check we still have 2 records... // Check we still have 2 records...
assert.containsN(target, '.o_data_row', 2, "should still have 2 records"); assert.containsN(target, '.o_data_row', 2, "should still have 2 records");
@@ -177,7 +177,7 @@ QUnit.module(
await editInput(target, "[name=name] input", name); await editInput(target, "[name=name] input", name);
await editInput(target, "[name=age] input", age); await editInput(target, "[name=age] input", age);
await editInput(target, "[name=job] input", "Soldier"); // let it in its original group await editInput(target, "[name=job] input", "Soldier"); // let it in its original group
await click(target.querySelector(".o_list_button_save")); await click(target.querySelector(".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"));
// Check we have 3 records... // Check we have 3 records...
assert.containsN(target, '.o_data_row', 3, "should have 3 records"); assert.containsN(target, '.o_data_row', 3, "should have 3 records");
@@ -7,7 +7,7 @@
steps: [ steps: [
{ {
trigger: '.o_kanban_record', trigger: '.o_kanban_record',
extra_trigger:'.breadcrumb', extra_trigger: '.o_breadcrumb',
}, },
{ {
trigger: '.nav-item > a:contains("Inventory")', trigger: '.nav-item > a:contains("Inventory")',
@@ -205,7 +205,7 @@ registry.category("web_tour.tours").add('survey_tour_test_survey_form_triggers',
run: () => {}, // it's a check run: () => {}, // it's a check
}, { }, {
content: 'Go back to Kanban View', content: 'Go back to Kanban View',
trigger: 'a[data-menu-xmlid="survey.menu_surveys"]', trigger: '[data-menu-xmlid="survey.menu_survey_form"]',
}, { }, {
content: "Check that we arrived on the kanban view", content: "Check that we arrived on the kanban view",
trigger: ".o-kanban-button-new", trigger: ".o-kanban-button-new",
@@ -14,6 +14,7 @@ import {
} from "@web/../tests/helpers/utils"; } from "@web/../tests/helpers/utils";
import { doAction } from "@web/../tests/webclient/helpers"; import { doAction } from "@web/../tests/webclient/helpers";
import { session } from "@web/session"; import { session } from "@web/session";
import { toggleSearchBarMenu } from "@web/../tests/search/helpers";
let serverData; let serverData;
let pyEnv; let pyEnv;
@@ -511,19 +512,19 @@ QUnit.module("test_mail", {}, function () {
const { webClient } = await start({ serverData, mockRPC }); const { webClient } = await start({ serverData, mockRPC });
await doAction(webClient, 1); await doAction(webClient, 1);
await toggleSearchBarMenu(document);
assert.containsN( assert.containsN(
document.body, document.body,
".o_search_options .dropdown button:visible", ".o_cp_searchview .o_dropdown_container",
2, 2,
"only two elements should be available in view search" "only two elements should be available in view search"
); );
assert.isVisible( assert.isVisible(
document.querySelector(".o_search_options .dropdown.o_filter_menu > button"), document.querySelector(".o_cp_searchview .o_dropdown_container.o_filter_menu"),
"filter should be available in view search" "filter should be available in view search"
); );
assert.isVisible( assert.isVisible(
document.querySelector(".o_search_options .dropdown.o_favorite_menu > button"), document.querySelector(".o_cp_searchview .o_dropdown_container.o_favorite_menu"),
"favorites should be available in view search" "favorites should be available in view search"
); );
}); });
@@ -15,7 +15,7 @@ QUnit.test(
const o_view_controller = document.querySelector(".o_view_controller"); const o_view_controller = document.querySelector(".o_view_controller");
const o_content = o_view_controller.querySelector(".o_content"); const o_content = o_view_controller.querySelector(".o_content");
const o_cp_item = o_view_controller.querySelector( const o_cp_item = o_view_controller.querySelector(
".o_control_panel .breadcrumb-item.active" ".o_control_panel .o_breadcrumb .active"
); );
const initialXCpItem = o_cp_item.getBoundingClientRect().x; const initialXCpItem = o_cp_item.getBoundingClientRect().x;
const o_header_cell = o_content.querySelector(".o_activity_type_cell"); const o_header_cell = o_content.querySelector(".o_activity_type_cell");
@@ -34,7 +34,8 @@ export class Popover extends Component {
} }
// reset all arrow classes // reset all arrow classes
const arrowEl = el.getElementsByClassName('popover-arrow')[0]; const arrowEl = el.querySelector(".popover-arrow");
arrowEl.className = "popover-arrow";
switch (position) { switch (position) {
case "tm": // top-middle case "tm": // top-middle
case "bm": // bottom-middle case "bm": // bottom-middle
@@ -23,7 +23,7 @@ export class CogMenu extends Component {
static template = "web.CogMenu"; static template = "web.CogMenu";
static components = { static components = {
Dropdown, Dropdown,
} };
static props = { static props = {
slots: { type: Object, optional: true }, slots: { type: Object, optional: true },
}; };
@@ -75,14 +75,18 @@ export class ControlPanel extends Component {
useEffect(() => { useEffect(() => {
// on small screen, clean-up the dropdown elements // on small screen, clean-up the dropdown elements
const dropdownButtons = this.mainButtons.el.querySelectorAll(".o_control_panel_collapsed_create.dropdown-menu button"); const dropdownButtons = this.mainButtons.el.querySelectorAll(
".o_control_panel_collapsed_create.dropdown-menu button"
);
if (!dropdownButtons.length) { if (!dropdownButtons.length) {
this.mainButtons.el this.mainButtons.el
.querySelectorAll(".o_control_panel_collapsed_create.dropdown-menu, .o_control_panel_collapsed_create.dropdown-toggle") .querySelectorAll(
".o_control_panel_collapsed_create.dropdown-menu, .o_control_panel_collapsed_create.dropdown-toggle"
)
.forEach((el) => el.classList.add("d-none")); .forEach((el) => el.classList.add("d-none"));
this.mainButtons.el this.mainButtons.el
.querySelectorAll(".o_control_panel_collapsed_create.btn-group") .querySelectorAll(".o_control_panel_collapsed_create.btn-group")
.forEach((el) => el.classList.remove("btn-group")); .forEach((el) => el.classList.remove("btn-group"));
return; return;
} }
for (const button of dropdownButtons) { for (const button of dropdownButtons) {
@@ -190,7 +194,7 @@ export class ControlPanel extends Component {
/** /**
* @param {KeyboardEvent} ev * @param {KeyboardEvent} ev
*/ */
onBottomLeftKeydown(ev) { onMainButtonsKeydown(ev) {
const hotkey = getActiveHotkey(ev); const hotkey = getActiveHotkey(ev);
if (hotkey === "arrowdown") { if (hotkey === "arrowdown") {
this.env.searchModel.trigger("focus-view"); this.env.searchModel.trigger("focus-view");
@@ -5,7 +5,7 @@
<div class="o_control_panel d-flex flex-column gap-3 gap-lg-1 px-3 pt-2 pb-3" t-ref="root"> <div class="o_control_panel d-flex flex-column gap-3 gap-lg-1 px-3 pt-2 pb-3" t-ref="root">
<div class="o_control_panel_main d-flex flex-wrap flex-lg-nowrap justify-content-between align-items-lg-start gap-3 flex-grow-1"> <div class="o_control_panel_main d-flex flex-wrap flex-lg-nowrap justify-content-between align-items-lg-start gap-3 flex-grow-1">
<div class="o_control_panel_breadcrumbs d-flex align-items-center gap-1 order-0 h-lg-100"> <div class="o_control_panel_breadcrumbs d-flex align-items-center gap-1 order-0 h-lg-100">
<div class="o_control_panel_main_buttons d-flex gap-1 d-empty-none d-print-none" t-ref="mainButtons"> <div class="o_control_panel_main_buttons d-flex gap-1 d-empty-none d-print-none" t-ref="mainButtons" t-on-keydown="onMainButtonsKeydown">
<div class="btn-group d-xl-none o_control_panel_collapsed_create"> <div class="btn-group d-xl-none o_control_panel_collapsed_create">
<t t-slot="control-panel-create-button"/> <t t-slot="control-panel-create-button"/>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split o_control_panel_collapsed_create" data-bs-toggle="dropdown" aria-expanded="false"> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split o_control_panel_collapsed_create" data-bs-toggle="dropdown" aria-expanded="false">
@@ -79,7 +79,7 @@
<t t-set="collapsedBreadcrumbs" t-value="breadcrumbs.slice(0, -3).reverse()"/> <t t-set="collapsedBreadcrumbs" t-value="breadcrumbs.slice(0, -3).reverse()"/>
<t t-set="breadcrumb" t-value="currentBreadcrumbs[0] || {}"/> <t t-set="breadcrumb" t-value="currentBreadcrumbs[0] || {}"/>
<div t-if="collapsedBreadcrumbs.length || visiblePathBreadcrumbs.length" class="d-flex flex-row flex-md-column align-self-stretch justify-content-between min-w-0"> <div t-if="collapsedBreadcrumbs.length || visiblePathBreadcrumbs.length" class="o_breadcrumb d-flex flex-row flex-md-column align-self-stretch justify-content-between min-w-0">
<t t-if="env.isSmall"> <t t-if="env.isSmall">
<t t-set="previousBreadcrumb" t-value="visiblePathBreadcrumbs.slice(-1)"/> <t t-set="previousBreadcrumb" t-value="visiblePathBreadcrumbs.slice(-1)"/>
<button class="o_back_button btn btn-link px-1" t-on-click.prevent="() => this.onBreadcrumbClicked(previousBreadcrumb.jsId)"> <button class="o_back_button btn btn-link px-1" t-on-click.prevent="() => this.onBreadcrumbClicked(previousBreadcrumb.jsId)">
@@ -101,22 +101,22 @@
</Dropdown> </Dropdown>
</li> </li>
<t t-foreach="visiblePathBreadcrumbs" t-as="breadcrumb" t-key="breadcrumb.jsId"> <t t-foreach="visiblePathBreadcrumbs" t-as="breadcrumb" t-key="breadcrumb.jsId">
<li class="breadcrumb-item d-inline-flex min-w-0" t-att-data-hotkey="breadcrumb_last and 'b'" t-on-click.prevent="() => this.onBreadcrumbClicked(breadcrumb.jsId)"> <li class="breadcrumb-item d-inline-flex min-w-0" t-att-class="{ o_back_button: breadcrumb_last }" t-att-data-hotkey="breadcrumb_last and 'b'" t-on-click.prevent="() => this.onBreadcrumbClicked(breadcrumb.jsId)">
<a href="#" class="fw-bold text-truncate" t-att-data-tooltip="'Back to &quot;' + breadcrumb.name + '&quot;'"><t t-call="web.Breadcrumb.Name"/></a> <a href="#" class="fw-bold text-truncate" t-att-data-tooltip="'Back to &quot;' + breadcrumb.name + '&quot;'"><t t-call="web.Breadcrumb.Name"/></a>
</li> </li>
</t> </t>
</ol> </ol>
</t> </t>
<div class="d-flex gap-1"> <div class="d-flex gap-1">
<div class="active d-flex gap-2 align-items-center min-w-0 lh-sm"> <div class="o_last_breadcrumb_item active d-flex gap-2 align-items-center min-w-0 lh-sm">
<span class="min-w-0 text-truncate" t-call="web.Breadcrumb.Name"/> <span class="min-w-0 text-truncate" t-call="web.Breadcrumb.Name"/>
</div> </div>
<t t-call="web.Breadcrumb.Actions"/> <t t-call="web.Breadcrumb.Actions"/>
</div> </div>
</div> </div>
<div t-else="" class="d-flex gap-1"> <div t-else="" class="o_breadcrumb d-flex gap-1">
<div class="active d-flex fs-4 min-w-0 align-items-center"> <div class="o_last_breadcrumb_item active d-flex fs-4 min-w-0 align-items-center">
<span class="min-w-0 text-truncate" t-call="web.Breadcrumb.Name"/> <span class="min-w-0 text-truncate" t-call="web.Breadcrumb.Name"/>
</div> </div>
<t t-call="web.Breadcrumb.Actions"/> <t t-call="web.Breadcrumb.Actions"/>
@@ -97,7 +97,7 @@
</div> </div>
<SearchBarMenu/> <SearchBarMenu/>
</div> </div>
<t t-portal="'.o_control_panel_navigation'"> <t t-portal="'.o_control_panel_navigation,.o_searchview'">
<button t-attf-class="btn btn-secondary {{state.showSearchBar?'d-md-none active':''}}" t-on-click="onToggleSearchBar"> <button t-attf-class="btn btn-secondary {{state.showSearchBar?'d-md-none active':''}}" t-on-click="onToggleSearchBar">
<i class="fa fa-fw fa-search"/> <i class="fa fa-fw fa-search"/>
</button> </button>
@@ -1,9 +1,8 @@
/** @odoo-module **/ /** @odoo-module **/
import { AdvancedSearchDialog } from "@web/search/filter_menu/advanced_search_dialog";
import { Component } from "@odoo/owl"; import { Component } from "@odoo/owl";
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
import { Domain } from "@web/core/domain"; import { DomainSelectorDialog } from "../../core/domain_selector_dialog/domain_selector_dialog";
import { Dropdown } from "@web/core/dropdown/dropdown"; import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item"; import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
@@ -12,6 +11,8 @@ import { useBus, useService } from "@web/core/utils/hooks";
import { CustomGroupByItem } from "@web/search/group_by_menu/custom_group_by_item"; import { CustomGroupByItem } from "@web/search/group_by_menu/custom_group_by_item";
import { SearchDropdownItem } from "@web/search/search_dropdown_item/search_dropdown_item"; import { SearchDropdownItem } from "@web/search/search_dropdown_item/search_dropdown_item";
import { FACET_ICONS, GROUPABLE_TYPES } from "@web/search/utils/misc"; import { FACET_ICONS, GROUPABLE_TYPES } from "@web/search/utils/misc";
import { useGetDefaultLeafDomain } from "@web/core/domain_selector/utils";
import { _t } from "@web/core/l10n/translation";
const favoriteMenuRegistry = registry.category("favoriteMenu"); const favoriteMenuRegistry = registry.category("favoriteMenu");
@@ -29,7 +30,7 @@ export class SearchBarMenu extends Component {
this.facet_icons = FACET_ICONS; this.facet_icons = FACET_ICONS;
// Filter // Filter
this.dialogService = useService("dialog"); this.dialogService = useService("dialog");
this.notification = useService("notification"); this.getDefaultLeafDomain = useGetDefaultLeafDomain();
// GroupBy // GroupBy
const fields = []; const fields = [];
for (const [fieldName, field] of Object.entries(this.env.searchModel.searchViewFields)) { for (const [fieldName, field] of Object.entries(this.env.searchModel.searchViewFields)) {
@@ -51,33 +52,23 @@ export class SearchBarMenu extends Component {
); );
} }
onAdvancedSearchClick() { async onAddCustomFilterClick() {
const domains = [this.env.searchModel._getDomain({ withGlobal: false })]; const { domainEvalContext: context, resModel } = this.env.searchModel;
if (this.env.searchModel.comparison && !this.env.searchModel.globalComparison) { const domain = await this.getDefaultLeafDomain(resModel);
const { range } = this.env.searchModel.getFullComparison(); this.dialogService.add(DomainSelectorDialog, {
domains.push(range); resModel,
} defaultConnector: "|",
const domain = Domain.and(domains).toString();
this.dialogService.add(AdvancedSearchDialog, {
domain, domain,
onConfirm: (domain) => this.onConfirm(domain), context,
resModel: this.env.searchModel.resModel, onConfirm: (domain) => this.env.searchModel.splitAndAddDomain(domain),
disableConfirmButton: (domain) => domain === `[]`,
title: _t("Add Custom Filter"),
confirmButtonText: _t("Add"),
discardButtonText: _t("Cancel"),
isDebugMode: !!this.env.debug, isDebugMode: !!this.env.debug,
}); });
} }
async onConfirm(domain) {
const isValid = await this.env.searchModel.isValidDomain(domain);
if (!isValid) {
this.notification.add(this.env._t("Domain is invalid. Please correct it"), {
type: "danger",
});
return false;
}
this.env.searchModel.createAdvancedDomain(domain);
return true;
}
/** /**
* @param {Object} param0 * @param {Object} param0
* @param {number} param0.itemId * @param {number} param0.itemId
@@ -54,7 +54,7 @@
<t t-if="filterItems.length"> <t t-if="filterItems.length">
<div role="separator" class="dropdown-divider"/> <div role="separator" class="dropdown-divider"/>
</t> </t>
<DropdownItem onSelected.bind="onAdvancedSearchClick">Advanced Search</DropdownItem> <DropdownItem onSelected.bind="onAddCustomFilterClick">Add Custom Filter</DropdownItem>
</div> </div>
</t> </t>
<!-- GroupBy --> <!-- GroupBy -->
@@ -65,6 +65,7 @@ export class CalendarController extends Component {
createRecord: this.createRecord.bind(this), createRecord: this.createRecord.bind(this),
deleteRecord: this.deleteRecord.bind(this), deleteRecord: this.deleteRecord.bind(this),
editRecord: this.editRecord.bind(this), editRecord: this.editRecord.bind(this),
setDate: this.setDate.bind(this),
displayName: this.displayName, displayName: this.displayName,
}; };
} }
@@ -62,4 +62,7 @@
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
background-color: var(--o-input-background-color, transparent); background-color: var(--o-input-background-color, transparent);
} }
&.o_field_widget.o_field_many2many_tags_avatar .o_field_many2many_selection .o-autocomplete {
height: inherit;
}
} }
@@ -11,7 +11,7 @@
<div class="o_pie_info"> <div class="o_pie_info">
<span class="o_pie_value" t-esc="props.record.data[props.name] + '%'"/> <span class="o_pie_value" t-esc="props.record.data[props.name] + '%'"/>
<span class="o_pie_text" t-esc="props.string"/> <span class="o_pie_text ms-1" t-esc="props.string"/>
</div> </div>
</t> </t>
@@ -170,10 +170,7 @@ export class FormCompiler extends ViewCompiler {
} }
compileButton(el, params) { compileButton(el, params) {
const compiled = super.compileButton(el, params); return super.compileButton(el, params);
compiled.setAttribute("disable", "__comp__.props.disableViewButtons");
compiled.setAttribute("enable", "__comp__.props.enableViewButtons");
return compiled;
} }
/** /**
@@ -648,9 +645,12 @@ export class FormCompiler extends ViewCompiler {
append(sheetBG, sheetFG); append(sheetBG, sheetFG);
for (const child of el.childNodes) { for (const child of el.childNodes) {
const compiled = this.compileNode(child, params); const compiled = this.compileNode(child, params);
if (!compiled || compiled.nodeName === "ButtonBox") { if (!compiled) {
continue; continue;
} }
if (compiled.nodeName === "ButtonBox") {
compiled.setAttribute("t-if", "__comp__.env.inDialog");
}
if (getTag(child, true) === "field") { if (getTag(child, true) === "field") {
compiled.setAttribute("showTooltip", true); compiled.setAttribute("showTooltip", true);
} }
@@ -23,7 +23,7 @@ import { Field } from "@web/views/fields/field";
import { CogMenu } from "@web/search/cog_menu/cog_menu"; import { CogMenu } from "@web/search/cog_menu/cog_menu";
import { ActionMenusItems } from "@web/search/cog_menu/action_menus_items"; import { ActionMenusItems } from "@web/search/cog_menu/action_menus_items";
import { Component, onRendered, useEffect, useRef, useState } from "@odoo/owl"; import { Component, onRendered, useEffect, useRef } from "@odoo/owl";
import { useViewCompiler } from "../view_compiler"; import { useViewCompiler } from "../view_compiler";
import { FormCompiler } from "./form_compiler"; import { FormCompiler } from "./form_compiler";
import { evalDomain } from "../utils"; import { evalDomain } from "../utils";
@@ -108,9 +108,6 @@ export class FormController extends Component {
this.user = useService("user"); this.user = useService("user");
this.viewService = useService("view"); this.viewService = useService("view");
this.ui = useService("ui"); this.ui = useService("ui");
this.state = useState({
isDisabled: false,
});
useBus(this.ui.bus, "resize", this.render); useBus(this.ui.bus, "resize", this.render);
this.archInfo = this.props.archInfo; this.archInfo = this.props.archInfo;
@@ -120,6 +117,8 @@ export class FormController extends Component {
this.canCreate = create && !this.props.preventCreate; this.canCreate = create && !this.props.preventCreate;
this.canEdit = edit && !this.props.preventEdit; this.canEdit = edit && !this.props.preventEdit;
this.disabledButtons = null;
let mode = this.props.mode || "edit"; let mode = this.props.mode || "edit";
if (!this.canEdit) { if (!this.canEdit) {
mode = "readonly"; mode = "readonly";
@@ -198,8 +197,8 @@ export class FormController extends Component {
this.buttonBoxTemplate = buttonBoxTemplates.ButtonBox; this.buttonBoxTemplate = buttonBoxTemplates.ButtonBox;
} }
const rootRef = useRef("root"); this.rootRef = useRef("root");
useViewButtons(this.model, rootRef, { useViewButtons(this.model, this.rootRef, {
beforeExecuteAction: this.beforeExecuteActionButton.bind(this), beforeExecuteAction: this.beforeExecuteActionButton.bind(this),
afterExecuteAction: this.afterExecuteActionButton.bind(this), afterExecuteAction: this.afterExecuteActionButton.bind(this),
}); });
@@ -213,7 +212,7 @@ export class FormController extends Component {
}; };
useSetupView({ useSetupView({
rootRef, rootRef: this.rootRef,
beforeLeave: () => this.beforeLeave(), beforeLeave: () => this.beforeLeave(),
beforeUnload: (ev) => this.beforeUnload(ev), beforeUnload: (ev) => this.beforeUnload(ev),
getLocalState: () => { getLocalState: () => {
@@ -248,9 +247,11 @@ export class FormController extends Component {
(isInEdition) => { (isInEdition) => {
if ( if (
!isInEdition && !isInEdition &&
!rootRef.el.querySelector(".o_content").contains(document.activeElement) !this.rootRef.el
.querySelector(".o_content")
.contains(document.activeElement)
) { ) {
const elementToFocus = rootRef.el.querySelector( const elementToFocus = this.rootRef.el.querySelector(
".o_content button.btn-primary" ".o_content button.btn-primary"
); );
if (elementToFocus) { if (elementToFocus) {
@@ -398,11 +399,18 @@ export class FormController extends Component {
} }
disableButtons() { disableButtons() {
this.state.isDisabled = true; const btns = [...this.rootRef.el.querySelectorAll("button:not([disabled])")];
for (const btn of btns) {
btn.setAttribute("disabled", "1");
}
this.disabledButtons = btns;
} }
enableButtons() { enableButtons() {
this.state.isDisabled = false; for (const btn of this.disabledButtons) {
btn.removeAttribute("disabled");
}
this.disabledButtons = null;
} }
async beforeExecuteActionButton(clickParams) { async beforeExecuteActionButton(clickParams) {
@@ -7,14 +7,14 @@
<Layout className="model.useSampleModel ? 'o_view_sample_data' : ''" display="display"> <Layout className="model.useSampleModel ? 'o_view_sample_data' : ''" display="display">
<t t-set-slot="control-panel-create-button"> <t t-set-slot="control-panel-create-button">
<t t-if="canCreate"> <t t-if="canCreate">
<button type="button" class="btn btn-secondary o_form_button_create" data-hotkey="c" t-on-click.stop="create" t-att-disabled="state.isDisabled">New</button> <button type="button" class="btn btn-secondary o_form_button_create" data-hotkey="c" t-on-click.stop="create">New</button>
</t> </t>
</t> </t>
<t t-set-slot="layout-buttons"> <t t-set-slot="layout-buttons">
<t t-if="env.inDialog"> <t t-if="env.inDialog">
<t t-if="footerArchInfo"> <t t-if="footerArchInfo">
<t t-component="props.Renderer" record="model.root" Compiler="props.Compiler" archInfo="footerArchInfo" enableViewButtons.bind="enableButtons" disableViewButtons.bind="disableButtons"/> <t t-component="props.Renderer" record="model.root" Compiler="props.Compiler" archInfo="footerArchInfo" />
</t> </t>
<t t-else=""> <t t-else="">
<t t-call="{{ props.buttonTemplate }}"/> <t t-call="{{ props.buttonTemplate }}"/>
@@ -47,15 +47,15 @@
<t t-set-slot="control-panel-status-indicator"> <t t-set-slot="control-panel-status-indicator">
<t t-if="canEdit"> <t t-if="canEdit">
<FormStatusIndicator model="model" discard.bind="discard" save.bind="saveButtonClicked" isDisabled="state.isDisabled" /> <FormStatusIndicator model="model" discard.bind="discard" save.bind="saveButtonClicked" />
</t> </t>
</t> </t>
<t t-set-slot="control-panel-create-button"> <t t-set-slot="control-panel-create-button">
<t t-if="canCreate"> <t t-if="canCreate">
<button type="button" class="btn btn-outline-primary o_form_button_create" data-hotkey="c" t-on-click.stop="create" t-att-disabled="state.isDisabled">New</button> <button type="button" class="btn btn-outline-primary o_form_button_create" data-hotkey="c" t-on-click.stop="create">New</button>
</t> </t>
</t> </t>
<t t-component="props.Renderer" record="model.root" Compiler="props.Compiler" archInfo="archInfo" translateAlert="translateAlert" enableViewButtons.bind="enableButtons" disableViewButtons.bind="disableButtons" onNotebookPageChange.bind="onNotebookPageChange" activeNotebookPages="props.state and props.state.activeNotebookPages"/> <t t-component="props.Renderer" record="model.root" Compiler="props.Compiler" archInfo="archInfo" translateAlert="translateAlert" onNotebookPageChange.bind="onNotebookPageChange" activeNotebookPages="props.state and props.state.activeNotebookPages"/>
</Layout> </Layout>
</div> </div>
</div> </div>
@@ -114,8 +114,6 @@ FormRenderer.props = {
// Template props : added by the FormCompiler // Template props : added by the FormCompiler
class: { type: String, optional: 1 }, class: { type: String, optional: 1 },
translateAlert: { type: [Object, { value: null }], optional: true }, translateAlert: { type: [Object, { value: null }], optional: true },
enableViewButtons: { type: Function, optional: true },
disableViewButtons: { type: Function, optional: true },
onNotebookPageChange: { type: Function, optional: true }, onNotebookPageChange: { type: Function, optional: true },
activeNotebookPages: { type: Object, optional: true }, activeNotebookPages: { type: Object, optional: true },
setFieldAsDirty: { type: Function, optional: true }, setFieldAsDirty: { type: Function, optional: true },
@@ -123,6 +121,4 @@ FormRenderer.props = {
FormRenderer.defaultProps = { FormRenderer.defaultProps = {
activeNotebookPages: {}, activeNotebookPages: {},
onNotebookPageChange: () => {}, onNotebookPageChange: () => {},
enableViewButtons: () => {},
disableViewButtons: () => {},
}; };
@@ -1,6 +1,6 @@
/** @odoo-module **/ /** @odoo-module **/
import { Component, useState } from "@odoo/owl"; import { Component, useEffect, useRef, useState } from "@odoo/owl";
import { useBus } from "@web/core/utils/hooks"; import { useBus } from "@web/core/utils/hooks";
export class FormStatusIndicator extends Component { export class FormStatusIndicator extends Component {
@@ -13,6 +13,18 @@ export class FormStatusIndicator extends Component {
"FIELD_IS_DIRTY", "FIELD_IS_DIRTY",
(ev) => (this.state.fieldIsDirty = ev.detail) (ev) => (this.state.fieldIsDirty = ev.detail)
); );
useEffect(
() => {
if (!this.props.model.root.isNew && this.indicatorMode === "invalid") {
this.saveButton.el.setAttribute("disabled", "1");
} else {
this.saveButton.el.removeAttribute("disabled");
}
},
() => [this.props.model.root.isValid]
);
this.saveButton = useRef("save");
} }
get displayButtons() { get displayButtons() {
@@ -43,5 +55,4 @@ FormStatusIndicator.props = {
model: Object, model: Object,
save: Function, save: Function,
discard: Function, discard: Function,
isDisabled: Boolean,
}; };
@@ -7,17 +7,16 @@
<button <button
type="button" type="button"
class="o_form_button_save btn btn-light px-1 py-0 lh-sm" class="o_form_button_save btn btn-light px-1 py-0 lh-sm"
t-att-disabled="props.isDisabled || !props.model.root.isNew and indicatorMode === 'invalid'"
data-hotkey="s" data-hotkey="s"
t-on-click.stop="save" t-on-click.stop="save"
data-tooltip="Save manually" data-tooltip="Save manually"
aria-label="Save manually"> aria-label="Save manually"
t-ref="save">
<i class="fa fa-cloud-upload fa-fw" /> <i class="fa fa-cloud-upload fa-fw" />
</button> </button>
<button <button
type="button" type="button"
class="o_form_button_cancel btn btn-light px-1 py-0 lh-sm" class="o_form_button_cancel btn btn-light px-1 py-0 lh-sm"
t-att-disabled="props.isDisabled"
data-hotkey="j" data-hotkey="j"
t-on-click.stop="discard" t-on-click.stop="discard"
data-tooltip="Discard changes" data-tooltip="Discard changes"
@@ -2,7 +2,7 @@
<templates xml:space="preserve"> <templates xml:space="preserve">
<t t-name="web.PivotView.Buttons" owl="1"> <t t-name="web.PivotView.Buttons" owl="1">
<div class="d-flex gap-1 mt-2 mx-3 mb-3"> <div class="o_pivot_buttons d-flex gap-1 mt-2 mx-3 mb-3">
<div class="btn-group" role="toolbar" aria-label="Main actions"> <div class="btn-group" role="toolbar" aria-label="Main actions">
<t t-call="web.ReportViewMeasures"> <t t-call="web.ReportViewMeasures">
<t t-set="measures" t-value="model.metaData.measures"/> <t t-set="measures" t-value="model.metaData.measures"/>
@@ -39,9 +39,7 @@
</t> </t>
<t t-else="" t-call="web.NoContentHelper"/> <t t-else="" t-call="web.NoContentHelper"/>
</t> </t>
<t t-if="model.hasData() and model.metaData.activeMeasures.length"> <t t-component="props.Renderer" model="model"/>
<t t-component="props.Renderer" model="model"/>
</t>
</Layout> </Layout>
</div> </div>
</t> </t>
@@ -3,8 +3,7 @@
<t t-name="web.PivotRenderer" owl="1"> <t t-name="web.PivotRenderer" owl="1">
<t t-call="web.PivotView.Buttons"/> <t t-call="web.PivotView.Buttons"/>
<div class="o_pivot table-responsive mx-3"> <div t-if="model.hasData() and model.metaData.activeMeasures.length" class="o_pivot table-responsive mx-3">
<table <table
class="table-hover table table-sm table-bordered table-borderless bg-view" class="table-hover table table-sm table-bordered table-borderless bg-view"
t-att-class="{ o_enable_linking: !model.metaData.disableLinking }" t-att-class="{ o_enable_linking: !model.metaData.disableLinking }"
@@ -100,8 +100,6 @@ export class ViewButton extends Component {
this.env[DROPDOWN].close(); this.env[DROPDOWN].close();
} }
}, },
disableAction: this.props.disable,
enableAction: this.props.enable,
}); });
} }
@@ -143,9 +141,7 @@ ViewButton.props = [
"clickParams?", "clickParams?",
"icon?", "icon?",
"defaultRank?", "defaultRank?",
"disable?",
"disabled?", "disabled?",
"enable?",
"size?", "size?",
"tabindex?", "tabindex?",
"title?", "title?",
@@ -158,6 +154,4 @@ ViewButton.defaultProps = {
tag: "button", tag: "button",
className: "", className: "",
clickParams: {}, clickParams: {},
disable: () => {},
enable: () => {},
}; };
@@ -7,7 +7,6 @@ import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_d
import { status, useEnv, useSubEnv } from "@odoo/owl"; import { status, useEnv, useSubEnv } from "@odoo/owl";
function disableButtons(el) { function disableButtons(el) {
// WOWL: can we do this non-imperatively?
const btns = [...el.querySelectorAll("button:not([disabled])")]; const btns = [...el.querySelectorAll("button:not([disabled])")];
for (const btn of btns) { for (const btn of btns) {
btn.setAttribute("disabled", "1"); btn.setAttribute("disabled", "1");
@@ -15,15 +14,12 @@ function disableButtons(el) {
return btns; return btns;
} }
function enableButtons(el, manuallyDisabledButtons, enableAction) { function enableButtons(el, manuallyDisabledButtons) {
if (el) { if (el) {
for (const btn of manuallyDisabledButtons) { for (const btn of manuallyDisabledButtons) {
btn.removeAttribute("disabled"); btn.removeAttribute("disabled");
} }
} }
if (enableAction) {
enableAction();
}
} }
function undefinedAsTrue(val) { function undefinedAsTrue(val) {
@@ -41,17 +37,8 @@ export function useViewButtons(model, ref, options = {}) {
}); });
const afterExecuteAction = options.afterExecuteAction || (() => {}); const afterExecuteAction = options.afterExecuteAction || (() => {});
useSubEnv({ useSubEnv({
async onClickViewButton({ async onClickViewButton({ clickParams, getResParams, beforeExecute }) {
clickParams,
getResParams,
beforeExecute,
disableAction,
enableAction,
}) {
const manuallyDisabledButtons = disableButtons(getEl()); const manuallyDisabledButtons = disableButtons(getEl());
if (disableAction) {
disableAction();
}
async function execute() { async function execute() {
let _continue = true; let _continue = true;
@@ -61,7 +48,7 @@ export function useViewButtons(model, ref, options = {}) {
_continue = _continue && undefinedAsTrue(await beforeExecuteAction(clickParams)); _continue = _continue && undefinedAsTrue(await beforeExecuteAction(clickParams));
if (!_continue) { if (!_continue) {
enableButtons(getEl(), manuallyDisabledButtons, enableAction); enableButtons(getEl(), manuallyDisabledButtons);
return; return;
} }
const closeDialog = clickParams.close && env.closeDialog; const closeDialog = clickParams.close && env.closeDialog;
@@ -103,7 +90,7 @@ export function useViewButtons(model, ref, options = {}) {
if (closeDialog) { if (closeDialog) {
closeDialog(); closeDialog();
} }
enableButtons(getEl(), manuallyDisabledButtons, enableAction); enableButtons(getEl(), manuallyDisabledButtons);
if (error) { if (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@@ -124,7 +111,7 @@ export function useViewButtons(model, ref, options = {}) {
}; };
dialog.add(ConfirmationDialog, dialogProps, { onClose: resolve }); dialog.add(ConfirmationDialog, dialogProps, { onClose: resolve });
}); });
enableButtons(getEl(), manuallyDisabledButtons, enableAction); enableButtons(getEl(), manuallyDisabledButtons);
} else { } else {
return execute(); return execute();
} }
@@ -514,7 +514,8 @@ function makeActionManager(env) {
viewProps.resId = action.res_id; viewProps.resId = action.res_id;
} }
viewProps.noBreadcrumbs = action.context.no_breadcrumbs; viewProps.noBreadcrumbs =
"no_breadcrumbs" in action.context ? action.context.no_breadcrumbs : target === "new";
delete action.context.no_breadcrumbs; delete action.context.no_breadcrumbs;
return { return {
props: viewProps, props: viewProps,
@@ -379,17 +379,15 @@ QUnit.module("DebugMenu", (hooks) => {
await doAction(webClient, 1234); await doAction(webClient, 1234);
await click(target.querySelector(".o_debug_manager button")); await click(target.querySelector(".o_debug_manager button"));
await click(target.querySelector(".o_debug_manager .dropdown-item")); await click(target.querySelector(".o_debug_manager .dropdown-item"));
assert.containsN(target, ".breadcrumb-item", 2); assert.containsOnce(target, ".breadcrumb-item");
assert.strictEqual( assert.containsOnce(target, ".o_breadcrumb .active");
target.querySelector(".breadcrumb-item.active").textContent, assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
"Edit view"
);
assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "18"); assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "18");
await click(target, ".breadcrumb .o_back_button"); await click(target, ".breadcrumb .o_back_button");
assert.containsOnce(target, ".breadcrumb-item"); assert.containsOnce(target, ".o_breadcrumb .active");
assert.strictEqual( assert.strictEqual(
target.querySelector(".breadcrumb-item.active").textContent, target.querySelector(".o_breadcrumb .active").textContent,
"Reporting Ponies" "Reporting Ponies"
); );
}); });
@@ -425,11 +423,9 @@ QUnit.module("DebugMenu", (hooks) => {
await click(target.querySelector(".o_debug_manager button")); await click(target.querySelector(".o_debug_manager button"));
await click(target.querySelector(".o_debug_manager .dropdown-item")); await click(target.querySelector(".o_debug_manager .dropdown-item"));
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsN(target, ".breadcrumb-item", 2); assert.containsOnce(target, ".breadcrumb-item");
assert.strictEqual( assert.containsOnce(target, ".o_breadcrumb .active");
target.querySelector(".breadcrumb-item.active").textContent, assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
"Edit view"
);
assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "293"); assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "293");
}); });
@@ -490,11 +486,9 @@ QUnit.module("DebugMenu", (hooks) => {
await click(target.querySelector(".o_debug_manager button")); await click(target.querySelector(".o_debug_manager button"));
await click(target.querySelector(".o_debug_manager .dropdown-item")); await click(target.querySelector(".o_debug_manager .dropdown-item"));
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsN(target, ".breadcrumb-item", 2); assert.containsOnce(target, ".breadcrumb-item");
assert.strictEqual( assert.containsOnce(target, ".o_breadcrumb .active");
target.querySelector(".breadcrumb-item.active").textContent, assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
"Edit view"
);
assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "293"); assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "293");
}); });
+24 -8
View File
@@ -384,10 +384,24 @@ export function click(el, selector, skipVisibilityCheck = false) {
} }
export function clickCreate(htmlElement) { export function clickCreate(htmlElement) {
if (htmlElement.querySelectorAll(".o_form_button_create").length) { if (
return click(htmlElement, ".o_form_button_create"); htmlElement.querySelectorAll(
} else if (htmlElement.querySelectorAll(".o_list_button_create").length) { ".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_form_button_create"
return click(htmlElement, ".o_list_button_create"); ).length
) {
return click(
htmlElement,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_form_button_create"
);
} else if (
htmlElement.querySelectorAll(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_create"
).length
) {
return click(
htmlElement,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_create"
);
} else { } else {
throw new Error("No edit button found to be clicked."); throw new Error("No edit button found to be clicked.");
} }
@@ -407,8 +421,10 @@ export async function clickSave(htmlElement) {
} }
if (htmlElement.querySelectorAll(".o_form_button_save").length) { if (htmlElement.querySelectorAll(".o_form_button_save").length) {
return click(htmlElement, ".o_form_button_save"); return click(htmlElement, ".o_form_button_save");
} else if (htmlElement.querySelectorAll(".o_list_button_save").length) { }
return click(htmlElement, ".o_list_button_save"); const listSaveButtons = htmlElement.querySelectorAll(".o_list_button_save");
if (listSaveButtons.length) {
return listSaveButtons.length >= 2 ? click(listSaveButtons[1]) : click(listSaveButtons[0]);
} else { } else {
throw new Error("No save button found to be clicked."); throw new Error("No save button found to be clicked.");
} }
@@ -420,8 +436,8 @@ export async function clickDiscard(htmlElement) {
} }
if (htmlElement.querySelectorAll(".o_form_button_cancel").length) { if (htmlElement.querySelectorAll(".o_form_button_cancel").length) {
return click(htmlElement, ".o_form_button_cancel"); return click(htmlElement, ".o_form_button_cancel");
} else if (htmlElement.querySelectorAll(".o_list_button_discard").length) { } else if ($(htmlElement).find(".o_list_button_discard:visible").length) {
return click(htmlElement, ".o_list_button_discard"); return click($(htmlElement).find(".o_list_button_discard:visible").get(0));
} else { } else {
throw new Error("No discard button found to be clicked."); throw new Error("No discard button found to be clicked.");
} }
@@ -1,12 +1,8 @@
/** @odoo-module **/ /** @odoo-module **/
import { click, getFixture, triggerEvent, nextTick } from "@web/../tests/helpers/utils"; import { getFixture, nextTick } from "@web/../tests/helpers/utils";
import { ControlPanel } from "@web/search/control_panel/control_panel"; import { ControlPanel } from "@web/search/control_panel/control_panel";
import { import { makeWithSearch, setupControlPanelServiceRegistry } from "@web/../tests/search/helpers";
editSearch,
makeWithSearch,
setupControlPanelServiceRegistry,
} from "@web/../tests/search/helpers";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { uiService } from "@web/core/ui/ui_service"; import { uiService } from "@web/core/ui/ui_service";
@@ -42,86 +38,6 @@ QUnit.module("Search", (hooks) => {
QUnit.module("Control Panel (mobile)"); QUnit.module("Control Panel (mobile)");
QUnit.test("Display control panel mobile", async (assert) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
searchMenuTypes: ["filter"],
searchViewId: false,
});
assert.containsOnce(target, ".breadcrumb");
assert.containsOnce(target, ".o_enable_searchview");
assert.containsNone(target, ".o_searchview");
assert.containsNone(target, ".o_toggle_searchview_full");
await click(target, ".o_enable_searchview");
assert.containsNone(target, ".breadcrumb");
assert.containsOnce(target, ".o_enable_searchview");
assert.containsOnce(target, ".o_searchview");
assert.containsOnce(target, ".o_toggle_searchview_full");
await click(target, ".o_toggle_searchview_full");
assert.containsOnce(document.body, ".o_searchview.o_mobile_search");
assert.containsN(document.body, ".o_mobile_search .o_mobile_search_button", 2);
assert.strictEqual(
document.body.querySelector(".o_mobile_search_header").textContent.trim(),
"FILTER CLEAR"
);
assert.containsOnce(document.body, ".o_searchview.o_mobile_search .o_cp_searchview");
assert.containsOnce(document.body, ".o_searchview.o_mobile_search .o_mobile_search_footer");
await click(document.body.querySelector(".o_mobile_search_button"));
assert.containsNone(target, ".breadcrumb");
assert.containsOnce(target, ".o_enable_searchview");
assert.containsOnce(target, ".o_searchview");
assert.containsOnce(target, ".o_toggle_searchview_full");
await click(target, ".o_enable_searchview");
assert.containsOnce(target, ".breadcrumb");
assert.containsOnce(target, ".o_enable_searchview");
assert.containsNone(target, ".o_searchview");
assert.containsNone(target, ".o_toggle_searchview_full");
});
QUnit.test("Make a simple search in mobile mode", async (assert) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
searchMenuTypes: ["filter"],
searchViewFields: {
birthday: { string: "Birthday", type: "date", store: true, sortable: true },
},
searchViewArch: `
<search>
<field name="birthday"/>
</search>
`,
});
assert.containsNone(target, ".o_searchview");
await click(target, ".o_enable_searchview");
assert.containsOnce(target, ".o_searchview");
const input = target.querySelector(".o_searchview input");
assert.containsNone(target, ".o_searchview_autocomplete");
await editSearch(target, "2022-02-14");
assert.strictEqual(input.value, "2022-02-14", "input value should be updated");
assert.containsOnce(target, ".o_searchview_autocomplete");
await triggerEvent(input, null, "keydown", { key: "Escape" });
assert.containsNone(target, ".o_searchview_autocomplete");
await click(target, ".o_enable_searchview");
assert.containsNone(target, ".o_searchview");
});
QUnit.test("Control panel is shown/hide on top when scrolling", async (assert) => { QUnit.test("Control panel is shown/hide on top when scrolling", async (assert) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
@@ -92,63 +92,59 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsNone(target, ".o_calendar_button_prev", "prev button should be hidden"); assert.containsNone(target, ".o_calendar_button_prev", "prev button should be hidden");
assert.containsNone(target, ".o_calendar_button_next", "next button should be hidden"); assert.containsNone(target, ".o_calendar_button_next", "next button should be hidden");
await click(target, ".o_calendar_container .o_other_calendar_panel");
assert.isVisible( assert.isVisible(
target.querySelector( target.querySelector(
".o_cp_bottom_left .o_calendar_buttons .o_view_scale_selector + button.o_cp_today_button" ".o_calendar_container .o_calendar_sidebar_container button.o_calendar_button_today"
), ),
"today button should be visible near the calendar buttons (bottom left corner)" "today button should be visible"
); );
// Test all views // Test all views
// displays month mode by default // displays month mode by default
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridWeek-view",
"should display the current week"
);
assert.equal( assert.equal(
target.querySelector(".breadcrumb-item").textContent, target.querySelector(
"undefined (Dec 11 – 17, 2016)" ".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Week",
"should display the current week"
); );
// switch to day mode // switch to day mode
await click(target, ".o_control_panel .scale_button_selection"); await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_control_panel .o_scale_button_day"); await click(target, ".o_calendar_sidebar_container .o_scale_button_day");
await nextTick(); await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridDay-view",
"should display the current day"
);
assert.equal( assert.equal(
target.querySelector(".breadcrumb-item").textContent, target.querySelector(
"undefined (December 12, 2016)" ".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Day",
"should display the current day"
); );
// switch to month mode // switch to month mode
await click(target, ".o_control_panel .scale_button_selection"); await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_control_panel .o_scale_button_month"); await click(target, ".o_calendar_sidebar_container .o_scale_button_month");
await nextTick(); await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-dayGridMonth-view",
"should display the current month"
);
assert.equal( assert.equal(
target.querySelector(".breadcrumb-item").textContent, target.querySelector(
"undefined (December 2016)" ".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Month",
"should display the current month"
); );
// switch to year mode // switch to year mode
await click(target, ".o_control_panel .scale_button_selection"); await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_control_panel .o_scale_button_year"); await click(target, ".o_calendar_sidebar_container .o_scale_button_year");
await nextTick(); await nextTick();
assert.containsOnce( assert.equal(
target, target.querySelector(
".fc-view-container > .fc-dayGridYear-view", ".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Year",
"should display the current year" "should display the current year"
); );
assert.equal(target.querySelector(".breadcrumb-item").textContent, "undefined (2016)");
}); });
QUnit.test("calendar: popover is rendered as dialog in mobile", async function (assert) { QUnit.test("calendar: popover is rendered as dialog in mobile", async function (assert) {
@@ -186,7 +182,9 @@ QUnit.module("Views", ({ beforeEach }) => {
await swipeRight(target, ".o_calendar_widget"); await swipeRight(target, ".o_calendar_widget");
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-11"); assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-11");
await click(target, ".o_other_calendar_panel");
await click(target, ".o_calendar_button_today"); await click(target, ".o_calendar_button_today");
await click(target, ".o_other_calendar_panel");
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-12"); assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-12");
}); });
@@ -358,7 +356,6 @@ QUnit.module("Views", ({ beforeEach }) => {
// Should display year view // Should display year view
assert.containsOnce(target, ".fc-dayGridYear-view"); assert.containsOnce(target, ".fc-dayGridYear-view");
assert.containsN(target, ".fc-month-container", 12); assert.containsN(target, ".fc-month-container", 12);
assert.equal(target.querySelector(".breadcrumb-item").textContent, "undefined (2016)");
// Tap on a date // Tap on a date
await tap(target, ".fc-day-top[data-date='2016-02-05']"); await tap(target, ".fc-day-top[data-date='2016-02-05']");
@@ -368,19 +365,14 @@ QUnit.module("Views", ({ beforeEach }) => {
// Should display day view // Should display day view
assert.containsNone(target, ".fc-dayGridYear-view"); assert.containsNone(target, ".fc-dayGridYear-view");
assert.containsOnce(target, ".fc-timeGridDay-view"); assert.containsOnce(target, ".fc-timeGridDay-view");
assert.equal( assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-02-05");
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 5, 2016)"
);
// Change scale to month // Change scale to month
await click(target, ".o_calendar_container .o_other_calendar_panel");
await changeScale(target, "month"); await changeScale(target, "month");
await click(target, ".o_calendar_container .o_other_calendar_panel");
assert.containsNone(target, ".fc-timeGridDay-view"); assert.containsNone(target, ".fc-timeGridDay-view");
assert.containsOnce(target, ".fc-dayGridMonth-view"); assert.containsOnce(target, ".fc-dayGridMonth-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 2016)"
);
// Tap on a date // Tap on a date
await tap(target, ".fc-day-top[data-date='2016-02-10']"); await tap(target, ".fc-day-top[data-date='2016-02-10']");
@@ -389,9 +381,6 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsNone(target, ".fc-dayGridMonth-view"); assert.containsNone(target, ".fc-dayGridMonth-view");
assert.containsOnce(target, ".fc-timeGridDay-view"); assert.containsOnce(target, ".fc-timeGridDay-view");
assert.equal( assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-02-10");
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 10, 2016)"
);
}); });
}); });
@@ -29,7 +29,7 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
QUnit.module("StatusBarField"); QUnit.module("StatusBarField");
QUnit.test("statusbar is rendered correclty on small devices", async (assert) => { QUnit.test("statusbar is rendered correctly on small devices", async (assert) => {
await makeView({ await makeView({
type: "form", type: "form",
resModel: "partner", resModel: "partner",
@@ -75,20 +75,20 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
); );
assert.containsN( assert.containsN(
fixture, fixture,
".o_statusbar_status .dropdown-menu .btn", ".o_statusbar_status .dropdown-menu .dropdown-item",
3, 3,
"should have 3 status" "should have 3 status"
); );
assert.containsN( assert.containsN(
fixture, fixture,
".o_statusbar_status .btn.disabled", ".o_statusbar_status .dropdown-item.disabled",
3, 3,
"all status should be disabled" "all status should be disabled"
); );
assert.hasClass( assert.hasClass(
fixture.querySelector(".o_statusbar_status .btn:nth-child(3)"), fixture.querySelector(".o_statusbar_status .dropdown-item:nth-child(3)"),
"btn-primary", "active",
"active status should be btn-primary" "active status should be set"
); );
}); });
@@ -131,30 +131,30 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
); );
assert.containsN( assert.containsN(
fixture, fixture,
".o_statusbar_status .dropdown-menu .btn", ".o_statusbar_status .dropdown-menu .dropdown-item",
3, 3,
"statusbar widget dropdown menu should have 3 buttons" "statusbar widget dropdown menu should have 3 items"
); );
assert.strictEqual( assert.strictEqual(
fixture fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[0] .querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[0]
.textContent.trim(), .textContent.trim(),
"first record", "first record",
"statusbar widget dropdown first button should display the first record display_name" "statusbar widget dropdown first item should display the first record display_name"
); );
assert.strictEqual( assert.strictEqual(
fixture fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[1] .querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[1]
.textContent.trim(), .textContent.trim(),
"second record", "second record",
"statusbar widget dropdown second button should display the second record display_name" "statusbar widget dropdown second item should display the second record display_name"
); );
assert.strictEqual( assert.strictEqual(
fixture fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[2] .querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[2]
.textContent.trim(), .textContent.trim(),
"aaa", "aaa",
"statusbar widget dropdown third button should display the third record display_name" "statusbar widget dropdown third item should display the third record display_name"
); );
}); });
@@ -175,34 +175,34 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
await click(fixture, ".o_statusbar_status .dropdown-toggle"); await click(fixture, ".o_statusbar_status .dropdown-toggle");
assert.hasClass( assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(3)"), fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(3)"),
"btn-primary" "active"
); );
assert.hasClass( assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(3)"), fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(3)"),
"disabled" "disabled"
); );
assert.containsN( assert.containsN(
fixture, fixture,
".o_statusbar_status .btn-secondary:not(.dropdown-toggle):not(.disabled)", ".o_statusbar_status .dropdown-item:not(.dropdown-toggle):not(.disabled):not(.active)",
2, 2,
"other status should be btn-secondary and not disabled" "other status should be active and not disabled"
); );
await click( await click(
fixture.querySelector( fixture.querySelector(
".o_statusbar_status .btn-secondary:not(.dropdown-toggle):not(.disabled)" ".o_statusbar_status .dropdown-item:not(.dropdown-toggle):not(.disabled):not(.active)"
) )
); );
await click(fixture, ".o_statusbar_status .dropdown-toggle"); await click(fixture, ".o_statusbar_status .dropdown-toggle");
assert.hasClass( assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(1)"), fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(1)"),
"btn-primary" "active"
); );
assert.hasClass( assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(1)"), fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(1)"),
"disabled" "disabled"
); );
}); });
@@ -61,13 +61,13 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
assert.containsN(fixture, ".o_data_row", 4); assert.containsN(fixture, ".o_data_row", 4);
assert.containsNone(fixture, ".o_list_selection_box"); assert.containsNone(fixture, ".o_list_selection_box");
assert.containsOnce(fixture, ".o_control_panel .o_cp_bottom_right"); assert.containsOnce(fixture, ".o_control_panel .fa-search");
// select a record // select a record
await triggerEvents(fixture, ".o_data_row:nth-child(1)", ["touchstart", "touchend"]); await triggerEvents(fixture, ".o_data_row:nth-child(1)", ["touchstart", "touchend"]);
assert.containsOnce(fixture, ".o_list_selection_box"); assert.containsOnce(fixture, ".o_list_selection_box");
assert.containsNone(fixture, ".o_list_selection_box .o_list_select_domain"); assert.containsNone(fixture, ".o_list_selection_box .o_list_select_domain");
assert.containsNone(fixture, ".o_control_panel .o_cp_bottom_right"); assert.containsNone(fixture, ".o_control_panel .fa-search");
assert.ok( assert.ok(
fixture.querySelector(".o_list_selection_box").textContent.includes("1 selected") fixture.querySelector(".o_list_selection_box").textContent.includes("1 selected")
); );
@@ -94,7 +94,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
// unselect all // unselect all
await click(fixture, ".o_list_unselect_all"); await click(fixture, ".o_list_unselect_all");
assert.containsNone(fixture, ".o_list_selection_box"); assert.containsNone(fixture, ".o_list_selection_box");
assert.containsOnce(fixture, ".o_control_panel .o_cp_bottom_right"); assert.containsOnce(fixture, ".o_control_panel .fa-search");
}); });
QUnit.test("selection box is properly displayed (multi pages)", async function (assert) { QUnit.test("selection box is properly displayed (multi pages)", async function (assert) {
@@ -72,7 +72,7 @@ QUnit.test("Burger Menu on an App", async (assert) => {
document.body.querySelector(".o_burger_menu nav.o_burger_menu_content li").textContent, document.body.querySelector(".o_burger_menu nav.o_burger_menu_content li").textContent,
"SubMenu" "SubMenu"
); );
assert.hasClass(document.body.querySelector(".o_burger_menu_content"), "o_burger_menu_dark"); assert.hasClass(document.body.querySelector(".o_burger_menu_content"), "o_burger_menu_app");
await click(document.body, ".o_burger_menu_topbar"); await click(document.body, ".o_burger_menu_topbar");
assert.doesNotHaveClass( assert.doesNotHaveClass(
@@ -81,7 +81,7 @@ QUnit.test("Burger Menu on an App", async (assert) => {
); );
await click(document.body, ".o_burger_menu_topbar"); await click(document.body, ".o_burger_menu_topbar");
assert.hasClass(document.body.querySelector(".o_burger_menu_content"), "o_burger_menu_dark"); assert.hasClass(document.body.querySelector(".o_burger_menu_content"), "o_burger_menu_app");
}); });
QUnit.test("Burger Menu on an App without SubMenu", async (assert) => { QUnit.test("Burger Menu on an App without SubMenu", async (assert) => {
@@ -2,7 +2,6 @@
import { getFixture, patchDate, patchWithCleanup } from "@web/../tests/helpers/utils"; import { getFixture, patchDate, patchWithCleanup } from "@web/../tests/helpers/utils";
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { import {
getFacetTexts, getFacetTexts,
makeWithSearch, makeWithSearch,
@@ -12,6 +11,7 @@ import {
toggleFilterMenu, toggleFilterMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers"; } from "./helpers";
let target; let target;
@@ -51,12 +51,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "comparison"], searchMenuTypes: ["filter", "comparison"],
searchViewId: false, searchViewId: false,
}); });
assert.containsOnce(target, ".dropdown.o_filter_menu"); assert.containsOnce(target, ".dropdown.o_filter_menu");
assert.containsNone(target, ".dropdown.o_comparison_menu"); // assert.containsNone(target, ".dropdown.o_comparison_menu"); // TODO: Logic not mock in makeWithSearchs
await toggleFilterMenu(target); await toggleFilterMenu(target);
await toggleMenuItem(target, "Birthday"); await toggleMenuItem(target, "Birthday");
await toggleMenuItemOption(target, "Birthday", "January"); await toggleMenuItemOption(target, "Birthday", "January");
@@ -65,7 +65,7 @@ QUnit.module("Search", (hooks) => {
target target
.querySelector("div.o_comparison_menu > button span") .querySelector("div.o_comparison_menu > button span")
.innerText.trim() .innerText.trim()
.toUpperCase() /** @todo why do I need to upperCase */, .toUpperCase(),
"COMPARISON" "COMPARISON"
); );
await toggleComparisonMenu(target); await toggleComparisonMenu(target);
@@ -87,7 +87,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "comparison"], searchMenuTypes: ["filter", "comparison"],
searchViewId: false, searchViewId: false,
}); });
@@ -106,7 +106,7 @@ QUnit.module("Search", (hooks) => {
await toggleComparisonMenu(target); await toggleComparisonMenu(target);
await toggleMenuItem(target, "Date: Previous Year"); await toggleMenuItem(target, "Date: Previous Year");
assert.deepEqual(getFacetTexts(target), [ assert.deepEqual(getFacetTexts(target), [
["Birthday: January 1997", "Date: December 1996"].join("or"), ["Birthday: January 1997", "Date: December 1996"].join("\nor\n"),
"Date: Previous Year", "Date: Previous Year",
]); ]);
await toggleFilterMenu(target); await toggleFilterMenu(target);
+14 -32
View File
@@ -1,10 +1,8 @@
/** @odoo-module **/ /** @odoo-module **/
import { click, getFixture, mount, nextTick } from "@web/../tests/helpers/utils"; import { click, getFixture, nextTick } from "@web/../tests/helpers/utils";
import { ControlPanel } from "@web/search/control_panel/control_panel"; import { ControlPanel } from "@web/search/control_panel/control_panel";
import { makeWithSearch, setupControlPanelServiceRegistry } from "./helpers"; import { makeWithSearch, setupControlPanelServiceRegistry } from "./helpers";
import { Component, xml } from "@odoo/owl";
import { makeTestEnv } from "../helpers/mock_env";
let target; let target;
let serverData; let serverData;
@@ -39,16 +37,15 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: [], searchMenuTypes: [],
}); });
assert.containsOnce(target, ".o_cp_top"); assert.containsOnce(target, ".o_control_panel_breadcrumbs");
assert.containsOnce(target, ".o_cp_top_left"); assert.containsOnce(target, ".o_control_panel_actions");
assert.strictEqual(target.querySelector(".o_cp_top_right").innerHTML, ""); assert.strictEqual(target.querySelector(".o_control_panel_actions").innerHTML, "");
assert.containsOnce(target, ".o_cp_bottom"); assert.containsOnce(target, ".o_control_panel_navigation");
assert.containsOnce(target, ".o_cp_bottom_left"); assert.strictEqual(target.querySelector(".o_control_panel_navigation").innerHTML, "");
assert.containsOnce(target, ".o_cp_bottom_right");
assert.containsNone(target, ".o_cp_switch_buttons"); assert.containsNone(target, ".o_cp_switch_buttons");
assert.containsOnce(target, ".breadcrumb"); assert.containsOnce(target, ".o_breadcrumb");
}); });
QUnit.test("breadcrumbs", async (assert) => { QUnit.test("breadcrumbs", async (assert) => {
@@ -65,8 +62,9 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: [], searchMenuTypes: [],
}); });
assert.containsN(target, ".breadcrumb li.breadcrumb-item", 2); const breadcrumbsSelector = ".o_breadcrumb li.breadcrumb-item, .o_breadcrumb .active";
const breadcrumbItems = target.querySelectorAll("li.breadcrumb-item"); assert.containsN(target, breadcrumbsSelector, 2);
const breadcrumbItems = target.querySelectorAll(breadcrumbsSelector);
assert.strictEqual(breadcrumbItems[0].innerText, "Previous"); assert.strictEqual(breadcrumbItems[0].innerText, "Previous");
assert.hasClass(breadcrumbItems[1], "active"); assert.hasClass(breadcrumbItems[1], "active");
assert.strictEqual(breadcrumbItems[1].innerText, "Current"); assert.strictEqual(breadcrumbItems[1].innerText, "Current");
@@ -93,7 +91,10 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: [], searchMenuTypes: [],
}); });
assert.containsOnce(target, ".o_cp_switch_buttons"); assert.containsOnce(
target,
".o_control_panel_navigation .d-xl-inline-flex.o_cp_switch_buttons"
);
assert.containsN(target, ".o_switch_view", 2); assert.containsN(target, ".o_switch_view", 2);
const views = target.querySelectorAll(".o_switch_view"); const views = target.querySelectorAll(".o_switch_view");
@@ -134,23 +135,4 @@ QUnit.module("Search", (hooks) => {
await nextTick(); await nextTick();
assert.containsNone(target, ".o_pager"); assert.containsNone(target, ".o_pager");
}); });
QUnit.test("control panel without bottom-right specifics", async (assert) => {
class CustomPage extends Component {}
CustomPage.components = { ControlPanel };
CustomPage.template = xml`
<ControlPanel display="{'top-right':false}">
<t t-set-slot="control-panel-bottom-right">
<div class="o_new_bottom_right">Something else</div>
</t>
</ControlPanel>
`;
// Minimal config, still needs at least an empty breadcrumbs to setup a control_panel
const env = await makeTestEnv();
Object.assign(env, { config: { breadcrumbs: [] } });
await mount(CustomPage, target, { env });
assert.containsOnce(target, ".o_new_bottom_right");
assert.containsNone(target, ".o_cp_switch_buttons");
assert.containsNone(target, ".o_pager");
});
}); });
@@ -3,7 +3,6 @@
import { getFixture, patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils"; import { getFixture, patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { FavoriteMenu } from "@web/search/favorite_menu/favorite_menu"; import { FavoriteMenu } from "@web/search/favorite_menu/favorite_menu";
import { useSetupAction } from "@web/webclient/actions/action_hook"; import { useSetupAction } from "@web/webclient/actions/action_hook";
import { import {
@@ -16,10 +15,12 @@ import {
setupControlPanelServiceRegistry, setupControlPanelServiceRegistry,
toggleFavoriteMenu, toggleFavoriteMenu,
toggleSaveFavorite, toggleSaveFavorite,
toggleSearchBarMenu,
validateSearch, validateSearch,
} from "./helpers"; } from "./helpers";
import { Component, xml } from "@odoo/owl"; import { Component, xml } from "@odoo/owl";
import { SearchBar } from "@web/search/search_bar/search_bar";
const serviceRegistry = registry.category("services"); const serviceRegistry = registry.category("services");
/** /**
@@ -79,7 +80,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
config: { config: {
@@ -87,7 +88,7 @@ QUnit.module("Search", (hooks) => {
}, },
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
assert.strictEqual( assert.strictEqual(
target.querySelector('.o_add_favorite input[type="text"]').value, target.querySelector('.o_add_favorite input[type="text"]').value,
@@ -107,12 +108,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
const checkboxes = target.querySelectorAll('input[type="checkbox"]'); const checkboxes = target.querySelectorAll('input[type="checkbox"]');
@@ -211,8 +212,8 @@ QUnit.module("Search", (hooks) => {
} }
}, },
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["favorite"], searchMenuTypes: ["filter", "favorite"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
@@ -224,7 +225,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Filter"]); assert.deepEqual(getFacetTexts(target), ["Filter"]);
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite"); await editFavoriteName(target, "My favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -245,7 +246,7 @@ QUnit.module("Search", (hooks) => {
} }
}, },
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -262,7 +263,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo\na"]); assert.deepEqual(getFacetTexts(target), ["Foo\na"]);
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite"); await editFavoriteName(target, "My favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -312,7 +313,7 @@ QUnit.module("Search", (hooks) => {
} }
}, },
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
irFilters: [ irFilters: [
@@ -328,7 +329,7 @@ QUnit.module("Search", (hooks) => {
], ],
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
// first try: should fail // first try: should fail
@@ -345,44 +346,47 @@ QUnit.module("Search", (hooks) => {
} }
); );
QUnit.test("undefined name for filter shows notification and not error", async function (assert) { QUnit.test(
assert.expect(2); "undefined name for filter shows notification and not error",
async function (assert) {
assert.expect(2);
serviceRegistry.add( serviceRegistry.add(
"notification", "notification",
{ {
start() { start() {
return { return {
add(message, options) { add(message, options) {
assert.strictEqual( assert.strictEqual(
message, message,
"A name for your favorite filter is required.", "A name for your favorite filter is required.",
"The notification should match: A name for your favorite filter is required." "The notification should match: A name for your favorite filter is required."
); );
assert.deepEqual(options, { type: "danger" }); assert.deepEqual(options, { type: "danger" });
}, },
}; };
},
}, },
}, { force: true }
{ force: true } );
);
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
mockRPC: (_, args) => { mockRPC: (_, args) => {
if (args.model === "ir.filters" && args.method === "create_or_replace") { if (args.model === "ir.filters" && args.method === "create_or_replace") {
return 7; // fake serverSideId return 7; // fake serverSideId
} }
}, },
resModel: "foo", resModel: "foo",
Component: FavoriteMenu, Component: FavoriteMenu,
searchViewId: false, searchViewId: false,
}); });
await toggleFavoriteMenu(target); await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await saveFavorite(target); await saveFavorite(target);
}); }
);
QUnit.skip("save search filter in modal", async function (assert) { QUnit.skip("save search filter in modal", async function (assert) {
/** @todo I don't know yet how to convert this test */ /** @todo I don't know yet how to convert this test */
@@ -1,7 +1,6 @@
/** @odoo-module **/ /** @odoo-module **/
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { getFixture, patchWithCleanup } from "../helpers/utils"; import { getFixture, patchWithCleanup } from "../helpers/utils";
import { import {
applyGroup, applyGroup,
@@ -11,9 +10,10 @@ import {
makeWithSearch, makeWithSearch,
setupControlPanelServiceRegistry, setupControlPanelServiceRegistry,
toggleAddCustomGroup, toggleAddCustomGroup,
toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
toggleSearchBarMenu,
} from "./helpers"; } from "./helpers";
import { SearchBar } from "@web/search/search_bar/search_bar";
let target; let target;
let serverData; let serverData;
@@ -52,12 +52,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
const customGroupByItem = target.querySelector(".o_add_custom_group_menu"); const customGroupByItem = target.querySelector(".o_add_custom_group_menu");
assert.strictEqual(customGroupByItem.innerText.trim(), "Add Custom Group"); assert.strictEqual(customGroupByItem.innerText.trim(), "Add Custom Group");
@@ -85,7 +85,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewFields: { searchViewFields: {
@@ -94,7 +94,7 @@ QUnit.module("Search", (hooks) => {
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
assert.deepEqual( assert.deepEqual(
@@ -116,7 +116,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewFields: { searchViewFields: {
@@ -130,7 +130,7 @@ QUnit.module("Search", (hooks) => {
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
assert.deepEqual( assert.deepEqual(
@@ -152,7 +152,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewFields: { searchViewFields: {
@@ -160,7 +160,7 @@ QUnit.module("Search", (hooks) => {
id: { sortable: true, string: "ID", type: "integer" }, id: { sortable: true, string: "ID", type: "integer" },
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.deepEqual(controlPanel.env.searchModel.groupBy, []); assert.deepEqual(controlPanel.env.searchModel.groupBy, []);
assert.containsNone(target, ".o_menu_item"); assert.containsNone(target, ".o_menu_item");
@@ -184,14 +184,14 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewFields: { searchViewFields: {
date: { sortable: true, name: "date", string: "Super Date", type: "date" }, date: { sortable: true, name: "date", string: "Super Date", type: "date" },
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
const addCustomGroupMenu = target.querySelector(".o_add_custom_group_menu"); const addCustomGroupMenu = target.querySelector(".o_add_custom_group_menu");
@@ -220,7 +220,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewFields: { searchViewFields: {
candle_light: { candle_light: {
@@ -231,7 +231,7 @@ QUnit.module("Search", (hooks) => {
}, },
}); });
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
await applyGroup(target); await applyGroup(target);
@@ -3,7 +3,6 @@
import { click, getFixture, patchDate } from "@web/../tests/helpers/utils"; import { click, getFixture, patchDate } from "@web/../tests/helpers/utils";
import { createWebClient, doAction } from "@web/../tests/webclient/helpers"; import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { FavoriteMenu } from "@web/search/favorite_menu/favorite_menu"; import { FavoriteMenu } from "@web/search/favorite_menu/favorite_menu";
import { SearchBar } from "@web/search/search_bar/search_bar"; import { SearchBar } from "@web/search/search_bar/search_bar";
import { import {
@@ -16,6 +15,7 @@ import {
toggleComparisonMenu, toggleComparisonMenu,
toggleFavoriteMenu, toggleFavoriteMenu,
toggleMenuItem, toggleMenuItem,
DropDownMenusTestComponent,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
import { Component, onWillUpdateProps, xml } from "@odoo/owl"; import { Component, onWillUpdateProps, xml } from "@odoo/owl";
@@ -28,6 +28,7 @@ function getDomain(comp) {
let serverData; let serverData;
let target; let target;
QUnit.module("Search", (hooks) => { QUnit.module("Search", (hooks) => {
hooks.beforeEach(async () => { hooks.beforeEach(async () => {
target = getFixture(); target = getFixture();
@@ -64,7 +65,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
config: { config: {
@@ -97,7 +98,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
config: { config: {
@@ -208,7 +209,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"], searchMenuTypes: ["favorite"],
searchViewId: false, searchViewId: false,
irFilters: [ irFilters: [
@@ -241,7 +242,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"], searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"],
searchViewId: false, searchViewId: false,
irFilters: [ irFilters: [
@@ -9,7 +9,6 @@ import {
patchWithCleanup, patchWithCleanup,
} from "@web/../tests/helpers/utils"; } from "@web/../tests/helpers/utils";
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { import {
getFacetTexts, getFacetTexts,
isItemSelected, isItemSelected,
@@ -20,6 +19,7 @@ import {
toggleFilterMenu, toggleFilterMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers"; } from "./helpers";
function getDomain(controlPanel) { function getDomain(controlPanel) {
@@ -68,7 +68,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
}); });
@@ -83,7 +83,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -109,7 +109,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -132,7 +132,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo"]); assert.deepEqual(getFacetTexts(target), ["Foo"]);
assert.containsOnce( assert.containsOnce(
target.querySelector(".o_searchview .o_searchview_facet"), target.querySelector(".o_searchview .o_searchview_facet"),
"span.fa.fa-filter.o_searchview_facet_label" ".o_searchview_facet_label"
); );
assert.ok(isItemSelected(target, "Foo")); assert.ok(isItemSelected(target, "Foo"));
assert.deepEqual(getDomain(controlPanel), [["foo", "=", "qsdf"]]); assert.deepEqual(getDomain(controlPanel), [["foo", "=", "qsdf"]]);
@@ -152,7 +152,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -382,7 +382,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -416,7 +416,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -443,7 +443,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -469,7 +469,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -493,7 +493,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -519,7 +519,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -547,7 +547,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), [ assert.deepEqual(getFacetTexts(target), [
"Filter Group 1", "Filter Group 1",
"Filter 1 Group 2orFilter 2 GROUP 2", "Filter 1 Group 2\nor\nFilter 2 GROUP 2",
]); ]);
}); });
@@ -557,7 +557,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewArch: ` searchViewArch: `
@@ -600,7 +600,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
}); });
@@ -628,7 +628,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
}); });
await toggleFilterMenu(target); await toggleFilterMenu(target);
@@ -652,7 +652,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
}); });
await toggleFilterMenu(target); await toggleFilterMenu(target);
@@ -670,7 +670,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
}); });
await toggleFilterMenu(target); await toggleFilterMenu(target);
@@ -696,7 +696,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -756,7 +756,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewId: false, searchViewId: false,
searchViewArch: `<search />`, searchViewArch: `<search />`,
@@ -781,7 +781,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"], searchMenuTypes: ["filter"],
searchViewId: false, searchViewId: false,
searchViewArch: `<search />`, searchViewArch: `<search />`,
@@ -1,7 +1,6 @@
/** @odoo-module **/ /** @odoo-module **/
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { getFixture, patchWithCleanup } from "../helpers/utils"; import { getFixture, patchWithCleanup } from "../helpers/utils";
import { import {
getFacetTexts, getFacetTexts,
@@ -13,6 +12,7 @@ import {
toggleGroupByMenu, toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers"; } from "./helpers";
let target; let target;
@@ -54,7 +54,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewFields: {}, searchViewFields: {},
@@ -74,7 +74,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
}); });
@@ -90,7 +90,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -115,7 +115,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -141,7 +141,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo"]); assert.deepEqual(getFacetTexts(target), ["Foo"]);
assert.containsOnce( assert.containsOnce(
target.querySelector(".o_searchview .o_searchview_facet"), target.querySelector(".o_searchview .o_searchview_facet"),
"span.oi.oi-group.o_searchview_facet_label" ".o_searchview_facet_label"
); );
assert.ok(isItemSelected(target, "Foo")); assert.ok(isItemSelected(target, "Foo"));
@@ -158,7 +158,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -184,7 +184,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -218,7 +218,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -245,19 +245,19 @@ QUnit.module("Search", (hooks) => {
const steps = [ const steps = [
{ {
description: "Year", description: "Year",
facetTexts: ["Date: Year>Date: Week"], facetTexts: ["Date: Year\n>\nDate: Week"],
selectedoptions: ["Year", "Week"], selectedoptions: ["Year", "Week"],
groupBy: ["date_field:year", "date_field:week"], groupBy: ["date_field:year", "date_field:week"],
}, },
{ {
description: "Month", description: "Month",
facetTexts: ["Date: Year>Date: Month>Date: Week"], facetTexts: ["Date: Year\n>\nDate: Month\n>\nDate: Week"],
selectedoptions: ["Year", "Month", "Week"], selectedoptions: ["Year", "Month", "Week"],
groupBy: ["date_field:year", "date_field:month", "date_field:week"], groupBy: ["date_field:year", "date_field:month", "date_field:week"],
}, },
{ {
description: "Week", description: "Week",
facetTexts: ["Date: Year>Date: Month"], facetTexts: ["Date: Year\n>\nDate: Month"],
selectedoptions: ["Year", "Month"], selectedoptions: ["Year", "Month"],
groupBy: ["date_field:year", "date_field:month"], groupBy: ["date_field:year", "date_field:month"],
}, },
@@ -286,7 +286,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -309,43 +309,49 @@ QUnit.module("Search", (hooks) => {
// select option 'week' // select option 'week'
await toggleMenuItemOption(target, "Date", "Week"); await toggleMenuItemOption(target, "Date", "Week");
assert.deepEqual(getFacetTexts(target), ["Bar>Date: Week"]); assert.deepEqual(getFacetTexts(target), ["Bar\n>\nDate: Week"]);
// select option 'day' // select option 'day'
await toggleMenuItemOption(target, "Date", "Day"); await toggleMenuItemOption(target, "Date", "Day");
assert.deepEqual(getFacetTexts(target), ["Bar>Date: Week>Date: Day"]); assert.deepEqual(getFacetTexts(target), ["Bar\n>\nDate: Week\n>\nDate: Day"]);
// select option 'year' // select option 'year'
await toggleMenuItemOption(target, "Date", "Year"); await toggleMenuItemOption(target, "Date", "Year");
assert.deepEqual(getFacetTexts(target), ["Bar>Date: Year>Date: Week>Date: Day"]); assert.deepEqual(getFacetTexts(target), [
"Bar\n>\nDate: Year\n>\nDate: Week\n>\nDate: Day",
]);
// select 'Foo' // select 'Foo'
await toggleMenuItem(target, "Foo"); await toggleMenuItem(target, "Foo");
assert.deepEqual(getFacetTexts(target), ["Bar>Date: Year>Date: Week>Date: Day>Foo"]); assert.deepEqual(getFacetTexts(target), [
"Bar\n>\nDate: Year\n>\nDate: Week\n>\nDate: Day\n>\nFoo",
]);
// select option 'quarter' // select option 'quarter'
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Quarter"); await toggleMenuItemOption(target, "Date", "Quarter");
assert.deepEqual(getFacetTexts(target), [ assert.deepEqual(getFacetTexts(target), [
"Bar>Date: Year>Date: Quarter>Date: Week>Date: Day>Foo", "Bar\n>\nDate: Year\n>\nDate: Quarter\n>\nDate: Week\n>\nDate: Day\n>\nFoo",
]); ]);
// unselect 'Bar' // unselect 'Bar'
await toggleMenuItem(target, "Bar"); await toggleMenuItem(target, "Bar");
assert.deepEqual(getFacetTexts(target), [ assert.deepEqual(getFacetTexts(target), [
"Date: Year>Date: Quarter>Date: Week>Date: Day>Foo", "Date: Year\n>\nDate: Quarter\n>\nDate: Week\n>\nDate: Day\n>\nFoo",
]); ]);
// unselect option 'week' // unselect option 'week'
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Week"); await toggleMenuItemOption(target, "Date", "Week");
assert.deepEqual(getFacetTexts(target), ["Date: Year>Date: Quarter>Date: Day>Foo"]); assert.deepEqual(getFacetTexts(target), [
"Date: Year\n>\nDate: Quarter\n>\nDate: Day\n>\nFoo",
]);
}); });
QUnit.test("default groupbys can be ordered", async function (assert) { QUnit.test("default groupbys can be ordered", async function (assert) {
@@ -354,7 +360,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -371,7 +377,7 @@ QUnit.module("Search", (hooks) => {
"date_field:week", "date_field:week",
"birthday:month", "birthday:month",
]); ]);
assert.deepEqual(getFacetTexts(target), ["Date: Week>Birthday: Month"]); assert.deepEqual(getFacetTexts(target), ["Date: Week\n>\nBirthday: Month"]);
}); });
QUnit.test("a separator in groupbys does not cause problems", async function (assert) { QUnit.test("a separator in groupbys does not cause problems", async function (assert) {
@@ -380,7 +386,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -407,7 +413,7 @@ QUnit.module("Search", (hooks) => {
assert.ok(isItemSelected(target, "Date")); assert.ok(isItemSelected(target, "Date"));
assert.ok(isItemSelected(target, "Bar")); assert.ok(isItemSelected(target, "Bar"));
assert.ok(isOptionSelected(target, "Date", "Day"), "selected"); assert.ok(isOptionSelected(target, "Date", "Day"), "selected");
assert.deepEqual(getFacetTexts(target), ["Date: Day>Bar"]); assert.deepEqual(getFacetTexts(target), ["Date: Day\n>\nBar"]);
await toggleMenuItemOption(target, "Date", "Quarter"); await toggleMenuItemOption(target, "Date", "Quarter");
@@ -415,7 +421,7 @@ QUnit.module("Search", (hooks) => {
assert.ok(isItemSelected(target, "Bar")); assert.ok(isItemSelected(target, "Bar"));
assert.ok(isOptionSelected(target, "Date", "Quarter"), "selected"); assert.ok(isOptionSelected(target, "Date", "Quarter"), "selected");
assert.ok(isOptionSelected(target, "Date", "Day"), "selected"); assert.ok(isOptionSelected(target, "Date", "Day"), "selected");
assert.deepEqual(getFacetTexts(target), ["Date: Quarter>Date: Day>Bar"]); assert.deepEqual(getFacetTexts(target), ["Date: Quarter\n>\nDate: Day\n>\nBar"]);
await toggleMenuItem(target, "Bar"); await toggleMenuItem(target, "Bar");
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
@@ -424,7 +430,7 @@ QUnit.module("Search", (hooks) => {
assert.notOk(isItemSelected(target, "Bar")); assert.notOk(isItemSelected(target, "Bar"));
assert.ok(isOptionSelected(target, "Date", "Quarter"), "selected"); assert.ok(isOptionSelected(target, "Date", "Quarter"), "selected");
assert.ok(isOptionSelected(target, "Date", "Day"), "selected"); assert.ok(isOptionSelected(target, "Date", "Day"), "selected");
assert.deepEqual(getFacetTexts(target), ["Date: Quarter>Date: Day"]); assert.deepEqual(getFacetTexts(target), ["Date: Quarter\n>\nDate: Day"]);
await removeFacet(target); await removeFacet(target);
@@ -445,7 +451,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -467,7 +473,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
@@ -490,7 +496,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
@@ -514,7 +520,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "foo", resModel: "foo",
Component: ControlPanel, Component: DropDownMenusTestComponent,
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
+49 -6
View File
@@ -21,6 +21,11 @@ import { popoverService } from "@web/core/popover/popover_service";
import { registry } from "@web/core/registry"; import { registry } from "@web/core/registry";
import { CustomFavoriteItem } from "@web/search/favorite_menu/custom_favorite_item"; import { CustomFavoriteItem } from "@web/search/favorite_menu/custom_favorite_item";
import { WithSearch } from "@web/search/with_search/with_search"; import { WithSearch } from "@web/search/with_search/with_search";
import { FilterMenu } from "@web/search/filter_menu/filter_menu";
import { GroupByMenu } from "@web/search/group_by_menu/group_by_menu";
import { ComparisonMenu } from "@web/search/comparison_menu/comparison_menu";
import { FavoriteMenu } from "@web/search/favorite_menu/favorite_menu";
import { SearchBar } from "@web/search/search_bar/search_bar";
import { getDefaultConfig } from "@web/views/view"; import { getDefaultConfig } from "@web/views/view";
import { viewService } from "@web/views/view_service"; import { viewService } from "@web/views/view_service";
import { actionService } from "@web/webclient/actions/action_service"; import { actionService } from "@web/webclient/actions/action_service";
@@ -196,7 +201,18 @@ export function getMenuItemTexts(target) {
} }
export function getButtons(el) { export function getButtons(el) {
return [...el.querySelector(`div.o_cp_bottom div.o_cp_buttons`).children]; return [...el.querySelectorAll(`div.o_control_panel_breadcrumbs button`)];
}
export function getVisibleButtons(el) {
return [
...$(el).find(
[
"div.o_control_panel_breadcrumbs button:visible", // button in the breadcrumbs
"div.o_control_panel_actions button:visible", // buttons for list selection
].join(",")
),
];
} }
/** Filter menu */ /** Filter menu */
@@ -280,7 +296,7 @@ export async function applyGroup(el) {
} }
export async function groupByMenu(el, fieldName) { export async function groupByMenu(el, fieldName) {
await toggleGroupByMenu(el); await toggleSearchBarMenu(el);
await toggleAddCustomGroup(el); await toggleAddCustomGroup(el);
await selectGroup(el, fieldName); await selectGroup(el, fieldName);
await applyGroup(el); await applyGroup(el);
@@ -331,7 +347,7 @@ export function getFacetTexts(target) {
export async function removeFacet(el, facetFinder = 0) { export async function removeFacet(el, facetFinder = 0) {
const facet = findItem(el, `div.o_searchview_facet`, facetFinder); const facet = findItem(el, `div.o_searchview_facet`, facetFinder);
await click(facet.querySelector("i.o_facet_remove")); await click(facet.querySelector(".o_facet_remove"));
} }
export async function editSearch(el, value) { export async function editSearch(el, value) {
@@ -384,7 +400,34 @@ export async function editPager(el, value) {
* @param {string} [menuFinder="Action"] * @param {string} [menuFinder="Action"]
* @returns {Promise} * @returns {Promise}
*/ */
export async function toggleActionMenu(el, menuFinder = "Action") { export async function toggleActionMenu(el) {
const dropdown = findItem(el, `.o_cp_action_menus button`, menuFinder); await click(el.querySelector(".o_cp_action_menus .dropdown-toggle"));
await click(dropdown);
} }
/** SearchBarMenu */
export async function toggleSearchBarMenu(el) {
await click(findItem(el, `.o_searchview_dropdown_toggler`));
}
export class DropDownMenusTestComponent extends Component {
get components() {
const componentMapping = {
filter: FilterMenu,
groupBy: GroupByMenu,
comparison: ComparisonMenu,
favorite: FavoriteMenu,
};
return (
Array.from(this.env.searchModel.searchMenuTypes).map(
(comp) => componentMapping[comp]
) || []
);
}
}
DropDownMenusTestComponent.template = xml`
<SearchBar/>
<t t-foreach="components" t-as="component" t-key="component">
<t t-component="component"/>
</t>
`;
DropDownMenusTestComponent.components = { SearchBar };
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,5 @@
/** @odoo-module **/ /** @odoo-module **/
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { import {
click, click,
getFixture, getFixture,
@@ -9,7 +8,6 @@ import {
nextTick, nextTick,
patchDate, patchDate,
patchTimeZone, patchTimeZone,
patchWithCleanup,
triggerEvent, triggerEvent,
} from "../helpers/utils"; } from "../helpers/utils";
import { import {
@@ -18,9 +16,8 @@ import {
makeWithSearch, makeWithSearch,
removeFacet, removeFacet,
setupControlPanelServiceRegistry, setupControlPanelServiceRegistry,
toggleComparisonMenu,
toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
toggleSearchBarMenu,
validateSearch, validateSearch,
} from "./helpers"; } from "./helpers";
@@ -32,7 +29,8 @@ function getDomain(controlPanel) {
return controlPanel.env.searchModel.domain; return controlPanel.env.searchModel.domain;
} }
import { onWillUpdateProps } from "@odoo/owl"; import { Component, onWillUpdateProps, xml } from "@odoo/owl";
import { SearchBar } from "@web/search/search_bar/search_bar";
let target; let target;
let serverData; let serverData;
@@ -143,7 +141,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -161,7 +159,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
context: { search_default_date_group_by: 1 }, context: { search_default_date_group_by: 1 },
@@ -190,7 +188,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], searchMenuTypes: ["groupBy"],
searchViewId: false, searchViewId: false,
context: { context: {
@@ -236,7 +234,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -248,7 +246,7 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select
assert.deepEqual( assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, " ")), getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Birthday 07/15/1983"], ["Birthday 07/15/1983"],
"The format of the date in the facet should be in locale" "The format of the date in the facet should be in locale"
); );
@@ -265,8 +263,8 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select
assert.deepEqual( assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, " ")), getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Birth DateTime\n07/15/1983 00:00:00"], ["Birth DateTime 07/15/1983 00:00:00"],
"The format of the datetime in the facet should be in locale" "The format of the datetime in the facet should be in locale"
); );
@@ -279,7 +277,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -324,7 +322,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -352,19 +350,20 @@ QUnit.module("Search", (hooks) => {
assert.expect(8); assert.expect(8);
let updateCount = 0; let updateCount = 0;
patchWithCleanup(ControlPanel.prototype, { class TestComponent extends Component {
setup() { setup() {
this._super();
onWillUpdateProps(() => { onWillUpdateProps(() => {
updateCount++; updateCount++;
}); });
}, }
}); }
TestComponent.template = xml`<SearchBar/>`;
TestComponent.components = { SearchBar };
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: TestComponent,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -378,8 +377,8 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
assert.deepEqual( assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, "")), getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["BarFirst record"] ["Bar First record"]
); );
assert.strictEqual(updateCount, 1); assert.strictEqual(updateCount, 1);
@@ -396,8 +395,8 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
assert.deepEqual( assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, "")), getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["BarFirst recordorSecond record"] ["Bar First record or Second record"]
); );
assert.strictEqual(updateCount, 2); assert.strictEqual(updateCount, 2);
@@ -410,19 +409,20 @@ QUnit.module("Search", (hooks) => {
assert.expect(2); assert.expect(2);
let updateCount = 0; let updateCount = 0;
patchWithCleanup(ControlPanel.prototype, { class TestComponent extends Component {
setup() { setup() {
this._super();
onWillUpdateProps(() => { onWillUpdateProps(() => {
updateCount++; updateCount++;
}); });
}, }
}); }
TestComponent.template = xml`<SearchBar/>`;
TestComponent.components = { SearchBar };
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: TestComponent,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -440,7 +440,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -487,7 +487,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -588,7 +588,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -610,7 +610,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -647,7 +647,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -672,7 +672,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -719,7 +719,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -759,7 +759,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -801,7 +801,7 @@ QUnit.module("Search", (hooks) => {
serverData, serverData,
mockRPC, mockRPC,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -840,7 +840,7 @@ QUnit.module("Search", (hooks) => {
serverData, serverData,
mockRPC, mockRPC,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -867,7 +867,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -895,7 +895,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -926,7 +926,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: /*xml*/ ` searchViewArch: /*xml*/ `
@@ -989,7 +989,7 @@ QUnit.module("Search", (hooks) => {
serverData, serverData,
mockRPC, mockRPC,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
}); });
@@ -1029,18 +1029,18 @@ QUnit.module("Search", (hooks) => {
serverData, serverData,
mockRPC, mockRPC,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
context: { search_default_company: 1 }, context: { search_default_company: 1 },
}); });
await nextTick(); await nextTick();
assert.containsNone(target, ".o_control_panel"); assert.containsNone(target, ".o_cp_searchview");
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_control_panel"); assert.containsOnce(target, ".o_cp_searchview");
assert.strictEqual(getFacetTexts(target)[0].replace("\n", ""), "CompanyFirst record"); assert.strictEqual(getFacetTexts(target)[0].replace("\n", ""), "CompanyFirst record");
}); });
@@ -1050,7 +1050,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1147,7 +1147,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1211,7 +1211,7 @@ QUnit.module("Search", (hooks) => {
]); ]);
// expand the selection properties // expand the selection properties
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a"); await editSearch(target, "a");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li"); items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1233,7 +1233,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getDomain(controlPanel), expectedDomain); assert.deepEqual(getDomain(controlPanel), expectedDomain);
// select the selection option "A" // select the selection option "A"
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a"); await editSearch(target, "a");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
await click(target.querySelector(".o_searchview_input_container li:nth-child(4)")); await click(target.querySelector(".o_searchview_input_container li:nth-child(4)"));
@@ -1257,7 +1257,7 @@ QUnit.module("Search", (hooks) => {
await click(target.querySelector(".o_facet_remove")); await click(target.querySelector(".o_facet_remove"));
// search a many2one value // search a many2one value
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "Ali"); await editSearch(target, "Ali");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
await click(target.querySelector("li:nth-child(2) .o_expand")); await click(target.querySelector("li:nth-child(2) .o_expand"));
@@ -1270,7 +1270,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getDomain(controlPanel), expectedDomain); assert.deepEqual(getDomain(controlPanel), expectedDomain);
// search a tag value // search a tag value
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "A"); await editSearch(target, "A");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li"); items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1290,7 +1290,7 @@ QUnit.module("Search", (hooks) => {
]; ];
assert.deepEqual(getDomain(controlPanel), expectedDomain); assert.deepEqual(getDomain(controlPanel), expectedDomain);
// add the tag "B" // add the tag "B"
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "B"); await editSearch(target, "B");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li"); items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1402,7 +1402,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: [], searchMenuTypes: [],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1414,7 +1414,7 @@ QUnit.module("Search", (hooks) => {
context: { active_id: 2 }, context: { active_id: 2 },
}); });
await click(target.querySelector(".o_control_panel")); await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a"); await editSearch(target, "a");
await click(target.querySelector(".o_expand")); await click(target.querySelector(".o_expand"));
@@ -1427,7 +1427,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model) searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model)
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1490,7 +1490,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({ const controlPanel = await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
@@ -1527,7 +1527,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model) searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model)
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1543,7 +1543,7 @@ QUnit.module("Search", (hooks) => {
".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label" ".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label"
); );
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Company"); await toggleMenuItem(target, "Company");
assert.deepEqual(getFacetTexts(target), ["My favorite", "Company"]); assert.deepEqual(getFacetTexts(target), ["My favorite", "Company"]);
@@ -1562,7 +1562,7 @@ QUnit.module("Search", (hooks) => {
await click(target.querySelector(".modal footer button")); await click(target.querySelector(".modal footer button"));
assert.containsNone(target, ".modal"); assert.containsNone(target, ".modal");
assert.deepEqual(getFacetTexts(target), ["Bool>Company", 'Foo contains "abc"']); assert.deepEqual(getFacetTexts(target), ["Bool\n>\nCompany", 'Foo contains "abc"']);
}); });
QUnit.test("edit a date filter with comparison active", async function (assert) { QUnit.test("edit a date filter with comparison active", async function (assert) {
@@ -1570,7 +1570,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchMenuTypes: ["filter", "comparison"], searchMenuTypes: ["filter", "comparison"],
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
@@ -1588,8 +1588,8 @@ QUnit.module("Search", (hooks) => {
".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label" ".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label"
); );
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target); await toggleMenuItem(target, "Birthday: Previous Period");
assert.deepEqual(getFacetTexts(target), [ assert.deepEqual(getFacetTexts(target), [
"Birthday: April 2023", "Birthday: April 2023",
@@ -1628,7 +1628,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({ await makeWithSearch({
serverData, serverData,
resModel: "partner", resModel: "partner",
Component: ControlPanel, Component: SearchBar,
searchViewId: false, searchViewId: false,
searchViewArch: ` searchViewArch: `
<search> <search>
@@ -1650,7 +1650,7 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "ArrowDown" }); await triggerEvent(searchInput, null, "keydown", { key: "ArrowDown" });
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select
assert.deepEqual(getFacetTexts(target), ["Foo\nabcordef"]); assert.deepEqual(getFacetTexts(target), ["Foo\nabc\nor\ndef"]);
await click(target, ".o_facet_with_domain .o_searchview_facet_label"); await click(target, ".o_facet_with_domain .o_searchview_facet_label");
assert.containsN(target, ".o_domain_leaf", 2); assert.containsN(target, ".o_domain_leaf", 2);
@@ -777,50 +777,8 @@ QUnit.module("Views", ({ beforeEach }) => {
} }
); );
QUnit.test(`breadcrumbs are updated with the displayed period`, async (assert) => {
await makeView({
type: "calendar",
resModel: "event",
serverData,
arch: `
<calendar date_start="start" date_stop="stop" all_day="allday" />
`,
});
// displays week mode by default
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").textContent,
"undefined (Dec 11 – 17, 2016)",
"should display the current week"
);
// switch to day mode
await changeScale(target, "day");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").textContent,
"undefined (December 12, 2016)",
"should display the current day"
);
// switch to month mode
await changeScale(target, "month");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").textContent,
"undefined (December 2016)",
"should display the current month"
);
// switch to year mode
await changeScale(target, "year");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").textContent,
"undefined (2016)",
"should display the current year"
);
});
QUnit.test(`create and change events`, async (assert) => { QUnit.test(`create and change events`, async (assert) => {
assert.expect(28); assert.expect(30);
await makeView({ await makeView({
type: "calendar", type: "calendar",
@@ -999,9 +957,26 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsN(target, ".fc-event-container .fc-event", 10, "should display 10 events"); assert.containsN(target, ".fc-event-container .fc-event", 10, "should display 10 events");
// move to next month // move to next month
await navigate(target, "next"); await navigate(target, "next");
assert.containsN(
target,
".fc-event-container .fc-event",
10,
"should still display 10 events"
);
await pickDate(target, "2017-01-01");
assert.containsN(
target,
".o_calendar_sidebar tr:has(.ui-state-active) td",
7,
"week scale should highlight 7 days in mini calendar"
);
await changeScale(target, "month");
assert.containsNone(target, ".fc-event-container .fc-event", "should display 0 events"); assert.containsNone(target, ".fc-event-container .fc-event", "should display 0 events");
await navigate(target, "prev"); await navigate(target, "prev");
await pickDate(target, "2016-12-27");
await changeScale(target, "month");
await selectDateRange(target, "2016-12-20", "2016-12-21"); await selectDateRange(target, "2016-12-20", "2016-12-21");
await editInput(target, ".o-calendar-quick-create--input", "test"); await editInput(target, ".o-calendar-quick-create--input", "test");
await click(target, ".o-calendar-quick-create--create-btn"); await click(target, ".o-calendar-quick-create--create-btn");
@@ -3403,7 +3378,8 @@ QUnit.module("Views", ({ beforeEach }) => {
// select filter for partner 1, 2 and 4 // select filter for partner 1, 2 and 4
await toggleSectionFilter(target, "partner_ids"); await toggleSectionFilter(target, "partner_ids");
await toggleFilter(target, "partner_id", 4); await toggleFilter(target, "partner_id", 4);
await navigate(target, "prev"); await pickDate(target, "2016-12-05");
await changeScale(target, "week");
assert.containsN(target, ".o_calendar_filter_item", 6, "should display 6 filter items"); assert.containsN(target, ".o_calendar_filter_item", 6, "should display 6 filter items");
assert.containsN(target, ".fc-event", 2, "should display 2 events"); assert.containsN(target, ".fc-event", 2, "should display 2 events");
const events = target.querySelectorAll(".fc-event .o_event_title"); const events = target.querySelectorAll(".fc-event .o_event_title");
@@ -3999,7 +3975,7 @@ QUnit.module("Views", ({ beforeEach }) => {
}); });
QUnit.test(`initial_date given in the context`, async (assert) => { QUnit.test(`initial_date given in the context`, async (assert) => {
assert.expect(1); assert.expect(2);
serverData.views = { serverData.views = {
"event,1,calendar": `<calendar date_start="start" date_stop="stop" mode="day"/>`, "event,1,calendar": `<calendar date_start="start" date_stop="stop" mode="day"/>`,
"event,false,search": `<search />`, "event,false,search": `<search />`,
@@ -4018,8 +3994,13 @@ QUnit.module("Views", ({ beforeEach }) => {
await doAction(webClient, 1); await doAction(webClient, 1);
await nextTick(); await nextTick();
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"context initial date (January 30, 2016)", "context initial date",
"should display name passed in the context"
);
assert.strictEqual(
target.querySelector(".o_calendar_renderer .fc-day-header").textContent,
"January 30, 2016",
"should display day passed in the context" "should display day passed in the context"
); );
}); });
@@ -508,7 +508,7 @@ export async function changeScale(target, scale) {
} }
export async function navigate(target, direction) { export async function navigate(target, direction) {
await click(target, `.o_calendar_navigation_buttons .o_calendar_button_${direction}`); await click(target, `.o_calendar_mini .ui-datepicker-${direction}`);
} }
export function findFilterPanelSection(target, sectionName) { export function findFilterPanelSection(target, sectionName) {
@@ -376,7 +376,10 @@ QUnit.module("Fields", (hooks) => {
resId: 1, resId: 1,
}); });
await click(target, ".o_form_button_create"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_form_button_create"
);
await click(target, ".o_field_many2one[name='product_id'] input"); await click(target, ".o_field_many2one[name='product_id'] input");
await click( await click(
target.querySelector(".o_field_many2one[name='product_id'] .dropdown-item") target.querySelector(".o_field_many2one[name='product_id'] .dropdown-item")
@@ -474,7 +477,7 @@ QUnit.module("Fields", (hooks) => {
); );
}); });
QUnit.test('isUploading state should be set to false after upload', async function(assert) { QUnit.test("isUploading state should be set to false after upload", async function (assert) {
assert.expect(1); assert.expect(1);
serverData.models.partner.onchanges = { serverData.models.partner.onchanges = {
document: function (obj) { document: function (obj) {
@@ -498,7 +501,7 @@ QUnit.module("Fields", (hooks) => {
await editInput(target, ".o_field_binary .o_input_file", file); await editInput(target, ".o_field_binary .o_input_file", file);
assert.equal( assert.equal(
target.querySelector(".o_select_file_button").innerText, target.querySelector(".o_select_file_button").innerText,
"UPLOAD YOUR FILE", "Upload your file",
"displayed value should be upload your file" "displayed value should be upload your file"
); );
}); });
@@ -224,7 +224,11 @@ QUnit.module("Fields", (hooks) => {
</tree>`, </tree>`,
domain: [["id", "<", 0]], domain: [["id", "<", 0]],
}); });
await click(target.querySelector(".o_list_button_add")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"
)
);
const date_column_width = target const date_column_width = target
.querySelector('.o_list_table thead th[data-name="date_field"]') .querySelector('.o_list_table thead th[data-name="date_field"]')
.style.width.replace("px", ""); .style.width.replace("px", "");
@@ -268,7 +268,11 @@ QUnit.module("Fields", (hooks) => {
); );
await editInput(target, 'div[name="float_field"] input', "18.8958938598598"); await editInput(target, 'div[name="float_field"] input', "18.8958938598598");
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_widget").textContent, target.querySelector(".o_field_widget").textContent,
"18.896", "18.896",
@@ -652,7 +652,7 @@ QUnit.module("Fields", (hooks) => {
); );
await clickSave(target); await clickSave(target);
await click(target, ".o_form_button_create"); await click(target, ".o_control_panel_main_buttons .d-none .o_form_button_create");
assert.strictEqual( assert.strictEqual(
target.querySelector("img[data-alt='Binary file']").dataset.src, target.querySelector("img[data-alt='Binary file']").dataset.src,
"/web/static/img/placeholder.png", "/web/static/img/placeholder.png",
@@ -262,7 +262,11 @@ QUnit.module("Fields", (hooks) => {
"The value should be displayed properly in the input." "The value should be displayed properly in the input."
); );
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
assert.strictEqual( assert.strictEqual(
target.querySelector("td:not(.o_list_record_selector)").textContent, target.querySelector("td:not(.o_list_record_selector)").textContent,
"-28", "-28",
@@ -181,7 +181,11 @@ QUnit.module("Fields", (hooks) => {
); );
// save and check the result // save and check the result
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
assert.strictEqual( assert.strictEqual(
target.querySelectorAll(".o_field_widget .badge:not(:empty)").length, target.querySelectorAll(".o_field_widget .badge:not(:empty)").length,
3, 3,
@@ -59,13 +59,13 @@ QUnit.module("Fields", (hooks) => {
assert.containsN( assert.containsN(
target, target,
".o_field_many2many_tags_avatar.o_field_widget .o_avatar", ".o_field_many2many_tags_avatar.o_field_widget .o_avatar img",
2, 2,
"should have 2 records" "should have 2 records"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_many2many_tags_avatar.o_field_widget .o_avatar img").dataset target.querySelector(".o_field_many2many_tags_avatar.o_field_widget .o_avatar img")
.src, .dataset.src,
"/web/image/partner/2/avatar_128", "/web/image/partner/2/avatar_128",
"should have correct avatar image" "should have correct avatar image"
); );
@@ -116,13 +116,13 @@ QUnit.module("Fields", (hooks) => {
); );
assert.containsN( assert.containsN(
target, target,
".o_data_row:nth-child(2) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty)", ".o_data_row:nth-child(2) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty) img",
4, 4,
"should have 4 records" "should have 4 records"
); );
assert.containsN( assert.containsN(
target, target,
".o_data_row:nth-child(3) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty)", ".o_data_row:nth-child(3) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty) img",
5, 5,
"should have 5 records" "should have 5 records"
); );
@@ -175,7 +175,7 @@ QUnit.module("Fields", (hooks) => {
); );
assert.containsN( assert.containsN(
target, target,
".o_data_row:nth-child(4) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty)", ".o_data_row:nth-child(4) .o_field_many2many_tags_avatar .o_avatar:not(.o_m2m_avatar_empty) img",
4, 4,
"should have 4 records" "should have 4 records"
); );
@@ -213,16 +213,20 @@ QUnit.module("Fields", (hooks) => {
await click(target.querySelector(".o_data_row .o_many2many_tags_avatar_cell")); await click(target.querySelector(".o_data_row .o_many2many_tags_avatar_cell"));
assert.containsN( assert.containsN(
target, target,
".o_data_row.o_selected_row .o_many2many_tags_avatar_cell .o_avatar", ".o_data_row.o_selected_row .o_many2many_tags_avatar_cell .o_avatar img",
1, 1,
"should have 1 many2many badges in edit mode" "should have 1 many2many badges in edit mode"
); );
await selectDropdownItem(target, "partner_ids", "second record"); await selectDropdownItem(target, "partner_ids", "second record");
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
assert.containsN( assert.containsN(
target, target,
".o_data_row:first-child .o_field_many2many_tags_avatar .o_avatar", ".o_data_row:first-child .o_field_many2many_tags_avatar .o_avatar img",
2, 2,
"should have 2 records" "should have 2 records"
); );
@@ -333,13 +337,13 @@ QUnit.module("Fields", (hooks) => {
assert.containsN( assert.containsN(
target, target,
".o_kanban_record:nth-child(2) .o_field_many2many_tags_avatar .o_avatar", ".o_kanban_record:nth-child(2) .o_field_many2many_tags_avatar .o_avatar img",
2, 2,
"should have 2 records" "should have 2 records"
); );
assert.containsN( assert.containsN(
target, target,
".o_kanban_record:nth-child(3) .o_field_many2many_tags_avatar .o_avatar", ".o_kanban_record:nth-child(3) .o_field_many2many_tags_avatar .o_avatar img",
2, 2,
"should have 2 records" "should have 2 records"
); );
@@ -374,7 +378,7 @@ QUnit.module("Fields", (hooks) => {
assert.containsN( assert.containsN(
target, target,
".o_kanban_record:nth-child(4) .o_field_many2many_tags_avatar .o_avatar", ".o_kanban_record:nth-child(4) .o_field_many2many_tags_avatar .o_avatar img",
2, 2,
"should have 2 records" "should have 2 records"
); );
@@ -26,8 +26,7 @@ import {
import { import {
editSearch, editSearch,
getFacetTexts, getFacetTexts,
toggleFilterMenu, toggleSearchBarMenu,
toggleGroupByMenu,
toggleMenuItem, toggleMenuItem,
validateSearch, validateSearch,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
@@ -626,7 +625,7 @@ QUnit.module("Fields", (hooks) => {
const modal = target.querySelector(".modal"); const modal = target.querySelector(".modal");
await toggleFilterMenu(modal); await toggleSearchBarMenu(modal);
await toggleMenuItem(modal, "Filter"); await toggleMenuItem(modal, "Filter");
assert.strictEqual($("tr.o_data_row").length, 0, "should display 0 records"); assert.strictEqual($("tr.o_data_row").length, 0, "should display 0 records");
@@ -1767,7 +1766,10 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(target, ".o_data_row", 3); assert.containsN(target, ".o_data_row", 3);
await click(target, ".o_list_button_add"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"
);
assert.containsN(target, ".o_data_row", 4); assert.containsN(target, ".o_data_row", 4);
@@ -3980,32 +3982,14 @@ QUnit.module("Fields", (hooks) => {
await click(target, `.o_field_widget[name="trululu"] .o_m2o_dropdown_option_search_more`); await click(target, `.o_field_widget[name="trululu"] .o_m2o_dropdown_option_search_more`);
// dropdown selector // dropdown selector
const filterMenuCss = ".o_search_options > .o_filter_menu"; const searchDropdown = ".o_control_panel_actions .o-dropdown";
const groupByMenuCss = ".o_search_options > .o_group_by_menu";
await click(document.querySelector(`${filterMenuCss} > .dropdown-toggle`)); await click(document.querySelector(`${searchDropdown} .dropdown-toggle`));
assert.hasClass(document.querySelector(filterMenuCss), "show"); assert.hasClass(document.querySelector(searchDropdown), "show");
assert.isVisible( assert.isVisible(
document.querySelector(`${filterMenuCss} > .dropdown-menu`), document.querySelector(`${searchDropdown} > .dropdown-menu`),
"the filter dropdown menu should be visible" "the search bar dropdown menu should be visible"
);
assert.doesNotHaveClass(document.querySelector(groupByMenuCss), "show");
assert.isNotVisible(
document.querySelector(`${groupByMenuCss} > .dropdown-menu`),
"the Group by dropdown menu should be not visible"
);
await click(document.querySelector(`${groupByMenuCss} > .dropdown-toggle`));
assert.hasClass(document.querySelector(groupByMenuCss), "show");
assert.isVisible(
document.querySelector(`${groupByMenuCss} > .dropdown-menu`),
"the group by dropdown menu should be visible"
);
assert.doesNotHaveClass(document.querySelector(filterMenuCss), "show");
assert.isNotVisible(
document.querySelector(`${filterMenuCss} > .dropdown-menu`),
"the filter dropdown menu should be not visible"
); );
}); });
@@ -4198,7 +4182,7 @@ QUnit.module("Fields", (hooks) => {
await selectDropdownItem(target, "trululu", "Search More..."); await selectDropdownItem(target, "trululu", "Search More...");
const modal = target.querySelector(".modal"); const modal = target.querySelector(".modal");
await toggleGroupByMenu(modal); await toggleSearchBarMenu(modal);
await toggleMenuItem(modal, "Bar"); await toggleMenuItem(modal, "Bar");
await click(modal.querySelectorAll(".o_group_header")[1]); await click(modal.querySelectorAll(".o_group_header")[1]);
@@ -4371,20 +4355,23 @@ QUnit.module("Fields", (hooks) => {
const target = getFixture(); const target = getFixture();
await doAction(webClient, 1); await doAction(webClient, 1);
assert.containsOnce(target, "a.o_form_uri", "should display 1 m2o link in form"); assert.containsOnce(target, "a.o_form_uri", "should display 1 m2o link in form");
assert.containsN( assert.containsOnce(
target, target,
".breadcrumb-item", ".o_breadcrumb",
1,
"Should only contain one breadcrumb at the start" "Should only contain one breadcrumb at the start"
); );
await click(target.querySelector("a.o_form_uri")); await click(target.querySelector("a.o_form_uri"));
assert.verifySteps(["get_formview_action"]); assert.verifySteps(["get_formview_action"]);
assert.containsN( assert.containsOnce(
target, target,
".breadcrumb-item", ".breadcrumb-item",
2, "Should contain 1 breadcrumb link after the clicking on the link"
"Should contain 2 breadcrumbs after the clicking on the link" );
assert.containsOnce(
target,
".o_breadcrumb",
"Should also contain the active breadcrumb item"
); );
}); });
@@ -4440,7 +4427,7 @@ QUnit.module("Fields", (hooks) => {
await click(target, ".o_field_widget .o_external_button"); await click(target, ".o_field_widget .o_external_button");
assert.verifySteps(["get_formview_action"]); assert.verifySteps(["get_formview_action"]);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "first recordNew"); assert.strictEqual(target.querySelector(".breadcrumb").textContent, "first record");
}); });
QUnit.test("external_button opens a FormViewDialog in dialogs", async function (assert) { QUnit.test("external_button opens a FormViewDialog in dialogs", async function (assert) {
@@ -771,7 +771,11 @@ QUnit.module("Fields", (hooks) => {
</tree>`, </tree>`,
}); });
await click(target.querySelector(".o_list_button_add")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"
)
);
assert.containsOnce( assert.containsOnce(
target, target,
".o_selected_row .o_field_widget[name=float_field] input", ".o_selected_row .o_field_widget[name=float_field] input",
@@ -63,72 +63,15 @@ QUnit.module("Fields", (hooks) => {
"should have a pie chart" "should have a pie chart"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value") target.querySelector(".o_field_percent_pie.o_field_widget .o_pie_info .o_pie_value")
.textContent, .textContent,
"10%", "10%",
"should have 10% as pie value since int_field=10" "should have 10% as pie value since int_field=10"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style target.querySelector(".o_field_percent_pie.o_field_widget .o_pie").style.background,
.transform, "conic-gradient( var(--PercentPieField-color-active) 0% 10%, var(--PercentPieField-color-static) 0% 100% )",
"rotate(180deg)", "pie should have a background computed for its value of 10%"
"left mask should be covering the whole left side of the pie"
);
assert.strictEqual(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1].style
.transform,
"rotate(36deg)",
"right mask should be rotated from 360*(10/100) = 36 degrees"
);
assert.containsOnce(
target,
".o_field_percent_pie.o_field_widget .o_pie",
"should have a pie chart"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value")
.textContent,
"10%",
"should have 10% as pie value since int_field=10"
);
assert.ok(
String(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style
.transform
).includes("rotate(180deg)"),
"left mask should be covering the whole left side of the pie"
);
assert.ok(
String(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1]
.style.transform
).includes("rotate(36deg)"),
"right mask should be rotated from 360*(10/100) = 36 degrees"
);
assert.containsOnce(
target,
".o_field_percent_pie.o_field_widget .o_pie",
"should have a pie chart"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value")
.textContent,
"10%",
"should have 10% as pie value since int_field=10"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style
.transform,
"rotate(180deg)",
"left mask should be covering the whole left side of the pie"
);
assert.strictEqual(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1].style
.transform,
"rotate(36deg)",
"right mask should be rotated from 360*(10/100) = 36 degrees"
); );
}); });
@@ -154,117 +97,15 @@ QUnit.module("Fields", (hooks) => {
"should have a pie chart" "should have a pie chart"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value") target.querySelector(".o_field_percent_pie.o_field_widget .o_pie_info .o_pie_value")
.textContent,
"80%",
"should have 80% as pie value since int_field=80"
);
assert.ok(
String(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style
.transform
).includes("rotate(288deg)"),
"left mask should be rotated from 360*(80/100) = 288 degrees"
);
assert.hasClass(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1],
"o_full",
"right mask should be hidden since the value > 50%"
);
assert.containsOnce(
target,
".o_field_percent_pie.o_field_widget .o_pie",
"should have a pie chart"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value")
.textContent, .textContent,
"80%", "80%",
"should have 80% as pie value since int_field=80" "should have 80% as pie value since int_field=80"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style target.querySelector(".o_field_percent_pie.o_field_widget .o_pie").style.background,
.transform, "conic-gradient( var(--PercentPieField-color-active) 0% 80%, var(--PercentPieField-color-static) 0% 100% )",
"rotate(288deg)", "pie should have a background computed for its value of 80%"
"left mask should be rotated from 360*(80/100) = 288 degrees"
);
assert.hasClass(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1],
"o_full",
"right mask should be hidden since the value > 50%"
);
assert.containsOnce(
target,
".o_field_percent_pie.o_field_widget .o_pie",
"should have a pie chart"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_pie_value")
.textContent,
"80%",
"should have 80% as pie value since int_field=80"
);
assert.strictEqual(
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie .o_mask").style
.transform,
"rotate(288deg)",
"left mask should be rotated from 360*(80/100) = 288 degrees"
);
assert.hasClass(
target.querySelectorAll(".o_field_percent_pie.o_field_widget .o_pie .o_mask")[1],
"o_full",
"right mask should be hidden since the value > 50%"
); );
}); });
// TODO: This test would pass without any issue since all the classes and
// custom style attributes are correctly set on the widget in list
// view, but since the scss itself for this widget currently only
// applies inside the form view, the widget is unusable. This test can
// be uncommented when we refactor the scss files so that this widget
// stylesheet applies in both form and list view.
// QUnit.test('percentpie widget in editable list view', async function(assert) {
// assert.expect(10);
//
// var list = await createView({
// View: ListView,
// model: 'partner',
// data: this.data,
// arch: '<tree editable="bottom">' +
// '<field name="foo"/>' +
// '<field name="int_field" widget="percentpie"/>' +
// '</tree>',
// });
//
// assert.containsN(list, '.o_field_percent_pie .o_pie', 5,
// "should have five pie charts");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_pie_value').textContent,
// '10%', "should have 10% as pie value since int_field=10");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').attr('style'),
// 'rotate(180deg)', "left mask should be covering the whole left side of the pie");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'),
// 'rotate(36deg)', "right mask should be rotated from 360*(10/100) = 36 degrees");
//
// // switch to edit mode and check the result
// testUtils.dom.click( target.querySelector('tbody td:not(.o_list_record_selector)'));
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_pie_value').textContent,
// '10%', "should have 10% as pie value since int_field=10");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').attr('style'),
// 'rotate(180deg)', "left mask should be covering the whole right side of the pie");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'),
// 'rotate(36deg)', "right mask should be rotated from 360*(10/100) = 36 degrees");
//
// // save
// testUtils.dom.click( list.$buttons.find('.o_list_button_save'));
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_pie_value').textContent,
// '10%', "should have 10% as pie value since int_field=10");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').attr('style'),
// 'rotate(180deg)', "left mask should be covering the whole right side of the pie");
// assert.strictEqual(target.querySelector('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'),
// 'rotate(36deg)', "right mask should be rotated from 360*(10/100) = 36 degrees");
//
// list.destroy();
// });
}); });
@@ -140,7 +140,11 @@ QUnit.module("Fields", (hooks) => {
await editInput(cell, "input", "new"); await editInput(cell, "input", "new");
// save // save
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
cell = target.querySelector("tbody td:not(.o_list_record_selector)"); cell = target.querySelector("tbody td:not(.o_list_record_selector)");
assert.doesNotHaveClass( assert.doesNotHaveClass(
cell.parentElement, cell.parentElement,
@@ -343,7 +343,10 @@ QUnit.module("Fields", (hooks) => {
assert.verifySteps(['write [[1],{"selection":"1"}]']); assert.verifySteps(['write [[1],{"selection":"1"}]']);
assert.containsOnce(target, ".o_kanban_record .fa-star"); assert.containsOnce(target, ".o_kanban_record .fa-star");
await click(target, ".o-kanban-button-new"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o-kanban-button-new"
);
await click(target, ".o_kanban_quick_create .o_kanban_add"); await click(target, ".o_kanban_quick_create .o_kanban_add");
await click(target.querySelector(".o_priority a.o_priority_star.fa-star-o"), null, true); await click(target.querySelector(".o_priority a.o_priority_star.fa-star-o"), null, true);
assert.verifySteps(['write [[6],{"selection":"1"}]']); assert.verifySteps(['write [[6],{"selection":"1"}]']);
@@ -404,7 +407,10 @@ QUnit.module("Fields", (hooks) => {
); );
// save // save
await click(target, ".o_list_button_save"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
);
assert.containsN( assert.containsN(
target.querySelectorAll(".o_data_row")[0], target.querySelectorAll(".o_data_row")[0],
@@ -514,7 +520,10 @@ QUnit.module("Fields", (hooks) => {
); );
// save // save
await click(target, ".o_list_button_save"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
);
rows = target.querySelectorAll(".o_data_row"); rows = target.querySelectorAll(".o_data_row");
assert.containsN( assert.containsN(
@@ -1,9 +1,6 @@
/** @odoo-module **/ /** @odoo-module **/
import { import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
makeFakeLocalizationService,
makeFakeNotificationService,
} from "@web/../tests/helpers/mock_services";
import { import {
click, click,
clickSave, clickSave,
@@ -507,13 +504,6 @@ QUnit.module("Fields", (hooks) => {
"ProgressBarField: write gibbrish instead of int throws warning", "ProgressBarField: write gibbrish instead of int throws warning",
async function (assert) { async function (assert) {
serverData.models.partner.records[0].int_field = 99; serverData.models.partner.records[0].int_field = 99;
const mock = () => {
assert.step("Show error message");
return () => {};
};
registry.category("services").add("notification", makeFakeNotificationService(mock), {
force: true,
});
await makeView({ await makeView({
serverData, serverData,
@@ -535,7 +525,11 @@ QUnit.module("Fields", (hooks) => {
await editInput(target, ".o_progressbar_value .o_input", "trente sept virgule neuf"); await editInput(target, ".o_progressbar_value .o_input", "trente sept virgule neuf");
await clickSave(target); await clickSave(target);
assert.containsOnce(target, ".o_form_dirty", "The form has not been saved"); assert.containsOnce(target, ".o_form_dirty", "The form has not been saved");
assert.verifySteps(["Show error message"], "The error message was shown correctly"); assert.strictEqual(
target.querySelector(".o_form_button_save").disabled,
true,
"save button is disabled"
);
} }
); );
@@ -555,7 +549,8 @@ QUnit.module("Fields", (hooks) => {
}); });
assert.containsOnce( assert.containsOnce(
target, ".o_progressbar .bg-warning", target,
".o_progressbar .bg-warning",
"As the value has excedded the max value, the color should be set to bg-warning" "As the value has excedded the max value, the color should be set to bg-warning"
); );
} }
@@ -865,7 +865,7 @@ QUnit.module("Fields", (hooks) => {
mockRPC: (route, { method, args }) => { mockRPC: (route, { method, args }) => {
if (method === "onchange") { if (method === "onchange") {
return { return {
value: {reference: "partner,2"}, value: { reference: "partner,2" },
}; };
} else if (method === "create") { } else if (method === "create") {
assert.strictEqual(args.length, 1); assert.strictEqual(args.length, 1);
@@ -874,10 +874,16 @@ QUnit.module("Fields", (hooks) => {
}, },
}); });
await click(target, '.o_list_button_add'); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"
);
await click(target, '.o_list_char[name="display_name"] input'); await click(target, '.o_list_char[name="display_name"] input');
await editInput(target, '.o_list_char[name="display_name"] input', "Blabla"); await editInput(target, '.o_list_char[name="display_name"] input', "Blabla");
await click(target, '.o_list_button_save'); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
);
}); });
QUnit.test( QUnit.test(
@@ -82,14 +82,18 @@ QUnit.module("Fields", (hooks) => {
".o_field_widget.o_field_state_selection span.o_status.o_status_green", ".o_field_widget.o_field_state_selection span.o_status.o_status_green",
"should not have one green status since selection is the second, blocked state" "should not have one green status since selection is the second, blocked state"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
// Click on the status button to make the dropdown appear // Click on the status button to make the dropdown appear
await click(target, ".o_field_widget.o_field_state_selection .o_status"); await click(target, ".o_field_widget.o_field_state_selection .o_status");
assert.containsOnce(document.body, ".dropdown-menu", "there should be a dropdown"); assert.containsOnce(
document.body,
".o_content .dropdown-menu",
"there should be a dropdown"
);
assert.containsN( assert.containsN(
target, target,
".dropdown-menu .dropdown-item", ".o_content .dropdown-menu .dropdown-item",
3, 3,
"there should be three options in the dropdown" "there should be three options in the dropdown"
); );
@@ -100,8 +104,12 @@ QUnit.module("Fields", (hooks) => {
); );
// Click on the first option, "Normal" // Click on the first option, "Normal"
await click(target.querySelector(".dropdown-menu .dropdown-item")); await click(target.querySelector(".o_content .dropdown-menu .dropdown-item"));
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore"); assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsNone( assert.containsNone(
target, target,
".o_field_widget.o_field_state_selection span.o_status.o_status_red", ".o_field_widget.o_field_state_selection span.o_status.o_status_red",
@@ -118,7 +126,11 @@ QUnit.module("Fields", (hooks) => {
"should have one grey status since selection is the first, normal state" "should have one grey status since selection is the first, normal state"
); );
assert.containsNone(target, ".dropdown-menu", "there should still not be a dropdown"); assert.containsNone(
target,
".o_content .dropdown-menu",
"there should still not be a dropdown"
);
assert.containsNone( assert.containsNone(
target, target,
".o_field_widget.o_field_state_selection span.o_status.o_status_red", ".o_field_widget.o_field_state_selection span.o_status.o_status_red",
@@ -137,7 +149,7 @@ QUnit.module("Fields", (hooks) => {
// Click on the status button to make the dropdown appear // Click on the status button to make the dropdown appear
await click(target, ".o_field_widget.o_field_state_selection .o_status"); await click(target, ".o_field_widget.o_field_state_selection .o_status");
assert.containsOnce(target, ".dropdown-menu", "there should be a dropdown"); assert.containsOnce(target, ".o_content .dropdown-menu", "there should be a dropdown");
assert.containsN( assert.containsN(
target, target,
".dropdown-menu .dropdown-item", ".dropdown-menu .dropdown-item",
@@ -146,8 +158,12 @@ QUnit.module("Fields", (hooks) => {
); );
// Click on the last option, "Done" // Click on the last option, "Done"
await click(target, ".dropdown-menu .dropdown-item:last-child"); await click(target, ".o_content .dropdown-menu .dropdown-item:last-child");
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore"); assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsNone( assert.containsNone(
target, target,
".o_field_widget.o_field_state_selection span.o_status.o_status_red", ".o_field_widget.o_field_state_selection span.o_status.o_status_red",
@@ -163,7 +179,7 @@ QUnit.module("Fields", (hooks) => {
await click(target.querySelector(".o_form_button_save")); await click(target.querySelector(".o_form_button_save"));
assert.containsNone( assert.containsNone(
target, target,
".dropdown-menu", ".o_content .dropdown-menu",
"there should still not be a dropdown anymore" "there should still not be a dropdown anymore"
); );
assert.containsNone( assert.containsNone(
@@ -281,7 +297,7 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green", ".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green",
"should have one green status" "should have one green status"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
// Click on the status button to make the dropdown appear // Click on the status button to make the dropdown appear
let cell = target.querySelector("tbody td.o_state_selection_cell"); let cell = target.querySelector("tbody td.o_state_selection_cell");
@@ -293,16 +309,16 @@ QUnit.module("Fields", (hooks) => {
"o_selected_row", "o_selected_row",
"should not be in edit mode since we clicked on the state selection widget" "should not be in edit mode since we clicked on the state selection widget"
); );
assert.containsOnce(target, ".dropdown-menu", "there should be a dropdown"); assert.containsOnce(target, ".o_content .dropdown-menu", "there should be a dropdown");
assert.containsN( assert.containsN(
target, target,
".dropdown-menu .dropdown-item", ".o_content .dropdown-menu .dropdown-item",
3, 3,
"there should be three options in the dropdown" "there should be three options in the dropdown"
); );
// Click on the first option, "Normal" // Click on the first option, "Normal"
await click(target.querySelector(".dropdown-menu .dropdown-item")); await click(target.querySelector(".o_content .dropdown-menu .dropdown-item"));
assert.containsN( assert.containsN(
target, target,
".o_state_selection_cell .o_field_state_selection span.o_status", ".o_state_selection_cell .o_field_state_selection span.o_status",
@@ -319,7 +335,7 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green", ".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green",
"should still have one green status" "should still have one green status"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
assert.containsNone(target, "tr.o_selected_row", "should not be in edit mode"); assert.containsNone(target, "tr.o_selected_row", "should not be in edit mode");
// switch to edit mode and check the result // switch to edit mode and check the result
@@ -342,16 +358,16 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green", ".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green",
"should still have one green status" "should still have one green status"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
// Click on the status button to make the dropdown appear // Click on the status button to make the dropdown appear
await click( await click(
target.querySelector(".o_state_selection_cell .o_field_state_selection span.o_status") target.querySelector(".o_state_selection_cell .o_field_state_selection span.o_status")
); );
assert.containsOnce(target, ".dropdown-menu", "there should be a dropdown"); assert.containsOnce(target, ".o_content .dropdown-menu", "there should be a dropdown");
assert.containsN( assert.containsN(
target, target,
".dropdown-menu .dropdown-item", ".o_content .dropdown-menu .dropdown-item",
3, 3,
"there should be three options in the dropdown" "there should be three options in the dropdown"
); );
@@ -359,7 +375,11 @@ QUnit.module("Fields", (hooks) => {
// Click on another row // Click on another row
const lastCell = target.querySelectorAll("tbody td.o_state_selection_cell")[4]; const lastCell = target.querySelectorAll("tbody td.o_state_selection_cell")[4];
await click(lastCell); await click(lastCell);
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore"); assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
const firstCell = target.querySelector("tbody td.o_state_selection_cell"); const firstCell = target.querySelector("tbody td.o_state_selection_cell");
assert.doesNotHaveClass( assert.doesNotHaveClass(
firstCell.parentElement, firstCell.parentElement,
@@ -378,17 +398,21 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status" ".o_state_selection_cell .o_field_state_selection span.o_status"
)[3] )[3]
); );
assert.containsOnce(target, ".dropdown-menu", "there should be a dropdown"); assert.containsOnce(target, ".o_content .dropdown-menu", "there should be a dropdown");
assert.containsN( assert.containsN(
target, target,
".dropdown-menu .dropdown-item", ".o_content .dropdown-menu .dropdown-item",
3, 3,
"there should be three options in the dropdown" "there should be three options in the dropdown"
); );
// Click on the last option, "Done" // Click on the last option, "Done"
await click(target, ".dropdown-menu .dropdown-item:last-child"); await click(target, ".o_content .dropdown-menu .dropdown-item:last-child");
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore"); assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsN( assert.containsN(
target, target,
".o_state_selection_cell .o_field_state_selection span.o_status", ".o_state_selection_cell .o_field_state_selection span.o_status",
@@ -406,10 +430,14 @@ QUnit.module("Fields", (hooks) => {
2, 2,
"should now have two green status" "should now have two green status"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
// save // save
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
assert.containsN( assert.containsN(
target, target,
".o_state_selection_cell .o_field_state_selection span.o_status", ".o_state_selection_cell .o_field_state_selection span.o_status",
@@ -427,7 +455,7 @@ QUnit.module("Fields", (hooks) => {
2, 2,
"should have two green status" "should have two green status"
); );
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown"); assert.containsNone(target, ".o_content .dropdown-menu", "there should not be a dropdown");
}); });
QUnit.test( QUnit.test(
@@ -584,7 +584,11 @@ QUnit.module("Fields", (hooks) => {
arch: '<tree editable="top"><field name="foo"/></tree>', arch: '<tree editable="top"><field name="foo"/></tree>',
}); });
await click(target.querySelector(".o_list_button_add")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_add"
)
);
assert.strictEqual( assert.strictEqual(
target.querySelector("textarea"), target.querySelector("textarea"),
@@ -226,7 +226,11 @@ QUnit.module("Fields", (hooks) => {
await editInput(cell, "input", "brolo"); await editInput(cell, "input", "brolo");
// save // save
await click(target.querySelector(".o_list_button_save")); await click(
target.querySelector(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_list_button_save"
)
);
cell = target.querySelector("tbody td:not(.o_list_record_selector)"); cell = target.querySelector("tbody td:not(.o_list_record_selector)");
assert.doesNotHaveClass( assert.doesNotHaveClass(
cell.parentElement, cell.parentElement,
@@ -184,7 +184,7 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ ` const expected = /*xml*/ `
<t> <t>
<div class="o_form_renderer o_form_nosheet" t-att-class="__comp__.props.class" t-attf-class="{{__comp__.props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ __comp__.props.record.isDirty ? 'o_form_dirty' : !__comp__.props.record.isNew ? 'o_form_saved' : '' }}" t-ref="compiled_view_root"> <div class="o_form_renderer o_form_nosheet" t-att-class="__comp__.props.class" t-attf-class="{{__comp__.props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ __comp__.props.record.isDirty ? 'o_form_dirty' : !__comp__.props.record.isNew ? 'o_form_saved' : '' }}" t-ref="compiled_view_root">
<div class="o_form_statusbar position-relative d-flex justify-content-between pb-3 px-3"><StatusBarButtons/></div> <div class="o_form_statusbar position-relative d-flex justify-content-between mb-2 px-3 pb-2 pb-md-0 px-md-0"><StatusBarButtons/></div>
<div>someDiv</div> <div>someDiv</div>
</div> </div>
</t>`; </t>`;
@@ -206,10 +206,10 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ ` const expected = /*xml*/ `
<t> <t>
<div class="o_form_renderer" t-att-class="__comp__.props.class" t-attf-class="{{__comp__.props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-flex {{ __comp__.uiService.size &lt; 6 ? &quot;flex-column&quot; : &quot;flex-nowrap h-100&quot; }} {{ __comp__.props.record.isDirty ? 'o_form_dirty' : !__comp__.props.record.isNew ? 'o_form_saved' : '' }}" t-ref="compiled_view_root"> <div class="o_form_renderer" t-att-class="__comp__.props.class" t-attf-class="{{__comp__.props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-flex {{ __comp__.uiService.size &lt; 6 ? &quot;flex-column&quot; : &quot;flex-nowrap h-100&quot; }} {{ __comp__.props.record.isDirty ? 'o_form_dirty' : !__comp__.props.record.isNew ? 'o_form_saved' : '' }}" t-ref="compiled_view_root">
<div class="o_form_sheet_bg pt-2"> <div class="o_form_sheet_bg">
<div class="o_form_statusbar position-relative d-flex justify-content-between pb-3 px-3"><StatusBarButtons/></div> <div class="o_form_statusbar position-relative d-flex justify-content-between mb-2 px-3 pb-2 pb-md-0 px-md-0"><StatusBarButtons/></div>
<div>someDiv</div> <div>someDiv</div>
<div class="o_form_sheet position-relative clearfix px-3"> <div class="o_form_sheet position-relative">
<div>inside sheet</div> <div>inside sheet</div>
</div> </div>
</div> </div>
@@ -267,7 +267,7 @@ QUnit.module("Form Compiler", (hooks) => {
</form>`; </form>`;
const expected = /*xml*/ ` const expected = /*xml*/ `
<div class="o_form_statusbar position-relative d-flex justify-content-between pb-3 px-3"> <div class="o_form_statusbar position-relative d-flex justify-content-between mb-2 px-3 pb-2 pb-md-0 px-md-0">
<StatusBarButtons> <StatusBarButtons>
<t t-set-slot="button_0" isVisible="true"> <t t-set-slot="button_0" isVisible="true">
<div>someDiv</div> <div>someDiv</div>
@@ -285,7 +285,7 @@ QUnit.module("Form Compiler", (hooks) => {
</form>`; </form>`;
const expected = /*xml*/ ` const expected = /*xml*/ `
<div class="o_form_statusbar position-relative d-flex justify-content-between pb-3 px-3"> <div class="o_form_statusbar position-relative d-flex justify-content-between mb-2 px-3 pb-2 pb-md-0 px-md-0">
<StatusBarButtons/> <StatusBarButtons/>
</div>`; </div>`;
@@ -21,7 +21,11 @@ import {
triggerEvent, triggerEvent,
triggerHotkey, triggerHotkey,
} from "@web/../tests/helpers/utils"; } from "@web/../tests/helpers/utils";
import { toggleActionMenu, toggleGroupByMenu, toggleMenuItem } from "@web/../tests/search/helpers"; import {
toggleActionMenu,
toggleSearchBarMenu,
toggleMenuItem,
} from "@web/../tests/search/helpers";
import { makeView, makeViewInDialog, setupViewRegistries } from "@web/../tests/views/helpers"; import { makeView, makeViewInDialog, setupViewRegistries } from "@web/../tests/views/helpers";
import { createWebClient, doAction } from "@web/../tests/webclient/helpers"; import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
import { browser } from "@web/core/browser/browser"; import { browser } from "@web/core/browser/browser";
@@ -46,6 +50,11 @@ const widgetRegistry = registry.category("view_widgets");
let target; let target;
let serverData; let serverData;
// Record
async function createRecord() {
await click(target, ".o_control_panel_main_buttons .d-none button.o_form_button_create");
}
QUnit.module("Views", (hooks) => { QUnit.module("Views", (hooks) => {
hooks.beforeEach(() => { hooks.beforeEach(() => {
target = getFixture(); target = getFixture();
@@ -384,15 +393,15 @@ QUnit.module("Views", (hooks) => {
type: "form", type: "form",
resModel: "partner", resModel: "partner",
serverData, serverData,
arch: `<form><sheet><div name="button_box"><button id="btn1">MyButton</button><button id="btn2">MyButton2</button><button id="btn3">MyButton3</button></div></sheet></form>`, arch: `<form><sheet><div name="button_box"><button id="btn1">MyButton</button><button id="btn2">MyButton2</button><button id="btn3">MyButton3</button><button id="btn4">MyButton4</button></div></sheet></form>`,
resId: 2, resId: 2,
}); });
assert.containsN(target, ".o-form-buttonbox > button", 2); assert.containsN(target, ".o-form-buttonbox > button", 3);
assert.containsOnce(target, ".o-dropdown.oe_stat_button .o_button_more"); assert.containsOnce(target, ".o-dropdown.oe_stat_button .o_button_more");
await click(target, ".o-dropdown.oe_stat_button .o_button_more");
assert.containsOnce(target, ".o-dropdown--menu #btn3"); await click(target, ".o-dropdown.oe_stat_button .o_button_more");
assert.containsOnce(target, ".o-dropdown--menu #btn4");
}); });
QUnit.test("button box rendering on big screen", async (assert) => { QUnit.test("button box rendering on big screen", async (assert) => {
@@ -1708,7 +1717,7 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target.querySelector(".o_list_button_add")); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
// sanity check: notebook active page is first page // sanity check: notebook active page is first page
assert.hasClass(target.querySelector(".o_notebook .nav-link"), "active"); assert.hasClass(target.querySelector(".o_notebook .nav-link"), "active");
@@ -1720,7 +1729,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(".o_control_panel .o_form_button_cancel")); await click(target.querySelector(".o_control_panel .o_form_button_cancel"));
assert.containsNone(target, ".o_form_view"); assert.containsNone(target, ".o_form_view");
await click(target.querySelector(".o_list_button_add")); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
// check notebook active page is first page again // check notebook active page is first page again
assert.hasClass(target.querySelector(".o_notebook .nav-link"), "active"); assert.hasClass(target.querySelector(".o_notebook .nav-link"), "active");
@@ -3187,16 +3196,10 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps(["read1", "willStart"]); assert.verifySteps(["read1", "willStart"]);
await click(target.querySelector(".o_form_statusbar button.p")); await click(target.querySelector(".o_form_statusbar button.p"));
assert.verifySteps(["willUpdateProps", "read2", "willUpdateProps", "willUpdateProps"]); assert.verifySteps(["willUpdateProps", "read2", "willUpdateProps"]);
await click(target.querySelector(".o_form_statusbar button.p")); await click(target.querySelector(".o_form_statusbar button.p"));
assert.verifySteps([ assert.verifySteps(["willUpdateProps", "read3", "willUpdateProps"]);
"willUpdateProps",
"willUpdateProps",
"read3",
"willUpdateProps",
"willUpdateProps",
]);
}); });
QUnit.test("buttons in form view, new record", async function (assert) { QUnit.test("buttons in form view, new record", async function (assert) {
@@ -3636,7 +3639,7 @@ QUnit.module("Views", (hooks) => {
const n = serverData.models.partner.records.length; const n = serverData.models.partner.records.length;
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsOnce(target, ".o_form_editable"); assert.containsOnce(target, ".o_form_editable");
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_char input").value, target.querySelector(".o_field_char input").value,
@@ -3784,7 +3787,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_cp_action_menus"); assert.containsOnce(target, ".o_cp_action_menus");
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsOnce(target, ".o_cp_action_menus"); assert.containsOnce(target, ".o_cp_action_menus");
@@ -3897,13 +3900,13 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1); await doAction(webClient, 1);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"first record", "first record",
"should have the display name of the record as title" "should have the display name of the record as title"
); );
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"New", "New",
"should have the display name of the record as title" "should have the display name of the record as title"
); );
@@ -4186,16 +4189,16 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"first record", "first record",
"should have the display name of the record as title" "should have the display name of the record as title"
); );
await toggleActionMenu(target); await toggleActionMenu(target);
await toggleMenuItem(target, "Duplicate"); await toggleMenuItem(target, "Duplicate");
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"first record (copy)", "first record (copy)",
"should have duplicated the record" "should have duplicated the record"
); );
@@ -4236,9 +4239,9 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"first record", "first record",
"should have the display name of the record as title" "should have the display name of the record as title"
); );
assert.containsOnce(target, ".o_cp_action_menus"); assert.containsOnce(target, ".o_cp_action_menus");
await toggleActionMenu(target); await toggleActionMenu(target);
@@ -4342,15 +4345,14 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"second record", "second record",
"should have correct display_name" "should have correct display_name"
); );
await editInput(target, ".o_field_widget[name=name] input", "some other name"); await editInput(target, ".o_field_widget[name=name] input", "some other name");
await click(target.querySelector(".oe_stat_button")); await click(target.querySelector(".oe_stat_button"));
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent, target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"GOLDORAK", "GOLDORAK",
"should have correct display_name" "should have correct display_name"
); );
@@ -5041,20 +5043,17 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record"); assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier"); assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
await editInput(target, ".o_field_widget[name=foo] input", ""); await editInput(target, ".o_field_widget[name=foo] input", "");
await click(target.querySelector(".o_pager_next")); await click(target.querySelector(".o_pager_next"));
assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.strictEqual( assert.strictEqual(
target.querySelector(".breadcrumb-item > span").innerText, target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"first record" "Unable to save. Correct the issue or discard changes"
);
assert.strictEqual(
target.querySelector(".breadcrumb-item > .o_form_status_indicator").innerText.trim(),
"Unable to save"
); );
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
@@ -5077,7 +5076,7 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record"); assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier"); assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
@@ -5085,13 +5084,10 @@ QUnit.module("Views", (hooks) => {
await editInput(target, ".o_field_widget[name=foo] input", ""); await editInput(target, ".o_field_widget[name=foo] input", "");
triggerHotkey("alt+n"); triggerHotkey("alt+n");
await nextTick(); await nextTick();
assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.strictEqual( assert.strictEqual(
target.querySelector(".breadcrumb-item > span").innerText, target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"first record" "Unable to save. Correct the issue or discard changes"
);
assert.strictEqual(
target.querySelector(".breadcrumb-item > .o_form_status_indicator").innerText.trim(),
"Unable to save"
); );
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
@@ -5116,17 +5112,17 @@ QUnit.module("Views", (hooks) => {
resId: 1, resId: 1,
}); });
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record"); assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier"); assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
await click(target.querySelector(".o_pager_next")); await click(target.querySelector(".o_pager_next"));
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "second record"); assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "second record");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "2");
await click(target.querySelector(".o_pager_previous")); await click(target.querySelector(".o_pager_previous"));
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record"); assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier"); assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
}); });
@@ -5480,7 +5476,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".o_back_button"); await click(target, ".o_back_button");
// Create a new record // Create a new record
await click(target, ".o_list_button_add"); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
notebooks = target.querySelectorAll(".o_notebook"); notebooks = target.querySelectorAll(".o_notebook");
assert.hasClass(notebooks[0].querySelector(".nav-link"), "active"); assert.hasClass(notebooks[0].querySelector(".nav-link"), "active");
assert.doesNotHaveClass(notebooks[0].querySelectorAll(".nav-link")[1], "active"); assert.doesNotHaveClass(notebooks[0].querySelectorAll(".nav-link")[1], "active");
@@ -5505,7 +5501,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1"); assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2"); assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsNone(target, ".o_pager"); assert.containsNone(target, ".o_pager");
@@ -5557,7 +5553,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsNone(target, ".foo_field"); assert.containsNone(target, ".foo_field");
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsOnce(target, ".foo_field"); assert.containsOnce(target, ".foo_field");
}); });
@@ -5582,7 +5578,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsOnce(target, ".o_field_empty"); assert.containsOnce(target, ".o_field_empty");
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsNone(target, ".o_field_empty"); assert.containsNone(target, ".o_field_empty");
}); });
@@ -5883,7 +5879,7 @@ QUnit.module("Views", (hooks) => {
// create mode (leave edition first!) // create mode (leave edition first!)
await clickDiscard(target); await clickDiscard(target);
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsOnce( assert.containsOnce(
target, target,
".oe_stat_button", ".oe_stat_button",
@@ -7026,7 +7022,7 @@ QUnit.module("Views", (hooks) => {
); );
}); });
QUnit.test("diplay something else than a button in a buttonbox", async function (assert) { QUnit.test("display something else than a button in a buttonbox", async function (assert) {
await makeView({ await makeView({
type: "form", type: "form",
resModel: "partner", resModel: "partner",
@@ -7044,18 +7040,18 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".oe_button_box").children.length, target.querySelector(".o-form-buttonbox").children.length,
2, 2,
"button box should contain two children" "button box should contain two children"
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box > .oe_stat_button", ".o-form-buttonbox > .oe_stat_button",
"button box should only contain one button" "button box should only contain one button"
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box > label", ".o-form-buttonbox > label",
"button box should only contain one label" "button box should only contain one label"
); );
}); });
@@ -7085,12 +7081,12 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".oe_button_box").children.length, target.querySelector(".o-form-buttonbox").children.length,
1, 1,
"button box should contain only one child" "button box should contain only one child"
); );
assert.hasClass( assert.hasClass(
target.querySelector(".oe_button_box"), target.querySelector(".o-form-buttonbox"),
"o_not_full", "o_not_full",
"the buttonbox should not be full" "the buttonbox should not be full"
); );
@@ -7135,7 +7131,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".oe_button_box").children.length, target.querySelector(".o-form-buttonbox").children.length,
2, 2,
"button box should contain two children" "button box should contain two children"
); );
@@ -7557,7 +7553,7 @@ QUnit.module("Views", (hooks) => {
function getVisibleButtonTexts() { function getVisibleButtonTexts() {
return [...target.querySelectorAll(".modal-footer button:not(.d-none)")].map((x) => return [...target.querySelectorAll(".modal-footer button:not(.d-none)")].map((x) =>
x.innerHTML.trim() x.textContent.trim()
); );
} }
}); });
@@ -7624,7 +7620,7 @@ QUnit.module("Views", (hooks) => {
); );
await clickDiscard(target); await clickDiscard(target);
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value, target.querySelector(".o_field_widget[name=foo] input").value,
"", "",
@@ -7647,11 +7643,9 @@ QUnit.module("Views", (hooks) => {
</sheet> </sheet>
</form>`, </form>`,
}); });
var $button = target.querySelector( const button = target.querySelector(".o_form_view .o-form-buttonbox .oe_stat_button");
".o_form_view .o_form_sheet .oe_button_box .oe_stat_button"
);
assert.strictEqual( assert.strictEqual(
$button.textContent, button.textContent,
"Inventory Moves", "Inventory Moves",
"the stat button should contain a span with the string attribute value" "the stat button should contain a span with the string attribute value"
); );
@@ -7916,7 +7910,6 @@ QUnit.module("Views", (hooks) => {
<field name="bar"/> <field name="bar"/>
</button>`); </button>`);
// legacySelector = ".oe_stat_button:not(.dropdown-item, .dropdown-toggle)";
const statButtonSelector = ".o-form-buttonbox .oe_stat_button:not(.o-dropdown)"; const statButtonSelector = ".o-form-buttonbox .oe_stat_button:not(.o-dropdown)";
const formView = await makeView({ const formView = await makeView({
@@ -7944,12 +7937,12 @@ QUnit.module("Views", (hooks) => {
); );
}; };
await assertFormContainsNButtonsWithSizeClass(0, 2); await assertFormContainsNButtonsWithSizeClass(0, 3);
await assertFormContainsNButtonsWithSizeClass(1, 2); await assertFormContainsNButtonsWithSizeClass(1, 3);
await assertFormContainsNButtonsWithSizeClass(2, 2); await assertFormContainsNButtonsWithSizeClass(2, 3);
await assertFormContainsNButtonsWithSizeClass(3, 4); await assertFormContainsNButtonsWithSizeClass(3, 7);
await assertFormContainsNButtonsWithSizeClass(4, 7); await assertFormContainsNButtonsWithSizeClass(4, 3);
await assertFormContainsNButtonsWithSizeClass(5, 7); await assertFormContainsNButtonsWithSizeClass(5, 4);
await assertFormContainsNButtonsWithSizeClass(6, 7); await assertFormContainsNButtonsWithSizeClass(6, 7);
}); });
@@ -8100,10 +8093,9 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
assert.containsNone(target, ".o_cp_action_menus .dropdown-toggle:contains(Print)");
assert.containsOnce(target, ".o_cp_action_menus .dropdown-toggle:contains(Action)");
await toggleActionMenu(target); await toggleActionMenu(target);
assert.containsNone(target, ".o_cp_action_menus .dropdown-menu_group:contains(Print)");
assert.containsOnce(target, ".o_cp_action_menus .dropdown-menu_group:contains(Action)");
assert.containsN( assert.containsN(
target, target,
".o_cp_action_menus .dropdown-item", ".o_cp_action_menus .dropdown-item",
@@ -8152,7 +8144,7 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
assert.containsOnce(target, ".o_cp_action_menus .dropdown-toggle:contains(Action)"); assert.containsOnce(target, ".o_cp_action_menus .dropdown-toggle");
await toggleActionMenu(target); await toggleActionMenu(target);
await toggleMenuItem(target, "Action Partner"); await toggleMenuItem(target, "Action Partner");
@@ -8203,7 +8195,7 @@ QUnit.module("Views", (hooks) => {
"My little Foo Value" "My little Foo Value"
); );
await editInput(target, ".o_field_widget[name='foo'] input", "test"); await editInput(target, ".o_field_widget[name='foo'] input", "test");
assert.containsOnce(target, ".o_cp_action_menus .dropdown-toggle:contains(Action)"); assert.containsOnce(target, ".o_cp_action_menus .dropdown-toggle");
await toggleActionMenu(target); await toggleActionMenu(target);
await toggleMenuItem(target, "Action Partner"); await toggleMenuItem(target, "Action Partner");
@@ -9206,11 +9198,11 @@ QUnit.module("Views", (hooks) => {
</form>`, </form>`,
resId: 1, resId: 1,
}); });
// Contains invisible buttons that are only displayed under xl screens
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):not(:disabled)", ".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
3, 5,
"control panel buttons should be enabled" "control panel buttons should be enabled"
); );
assert.containsN( assert.containsN(
@@ -9221,17 +9213,18 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:not(:disabled)", ".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled" "stat buttons should be enabled"
); );
await click(target.querySelector(".o_form_statusbar button")); await click(target.querySelector(".o_form_statusbar button"));
await nextTick();
// The unresolved promise lets us check the state of the buttons // The unresolved promise lets us check the state of the buttons
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):disabled", ".o_control_panel_breadcrumbs button:not(.fa):disabled",
3, 5,
"control panel buttons should be disabled" "control panel buttons should be disabled"
); );
assert.containsN( assert.containsN(
@@ -9242,7 +9235,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:disabled", ".o-form-buttonbox button:disabled",
"stat buttons should be disabled" "stat buttons should be disabled"
); );
@@ -9250,8 +9243,8 @@ QUnit.module("Views", (hooks) => {
await nextTick(); await nextTick();
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):not(:disabled)", ".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
3, 5,
"control panel buttons should be enabled" "control panel buttons should be enabled"
); );
assert.containsN( assert.containsN(
@@ -9262,7 +9255,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:not(:disabled)", ".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled" "stat buttons should be enabled"
); );
}); });
@@ -9306,8 +9299,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):not(:disabled)", ".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
3, 5,
"control panel buttons should be enabled" "control panel buttons should be enabled"
); );
assert.containsN( assert.containsN(
@@ -9318,17 +9311,17 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:not(:disabled)", ".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled" "stat buttons should be enabled"
); );
await click(target.querySelector(".oe_button_box button")); await click(target.querySelector(".o-form-buttonbox button"));
// The unresolved promise lets us check the state of the buttons // The unresolved promise lets us check the state of the buttons
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):disabled", ".o_control_panel_breadcrumbs button:not(.fa):disabled",
3, 5,
"control panel buttons should be disabled" "control panel buttons should be disabled"
); );
assert.containsN( assert.containsN(
@@ -9339,16 +9332,16 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:disabled", ".o-form-buttonbox button:disabled",
"stat buttons should be disabled" "stat buttons should be disabled"
); );
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsN( assert.containsN(
target, target,
".o_control_panel button:not(.fa):not(:disabled)", ".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
3, 5,
"control panel buttons should be enabled" "control panel buttons should be enabled"
); );
assert.containsN( assert.containsN(
@@ -9359,7 +9352,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce( assert.containsOnce(
target, target,
".oe_button_box button:not(:disabled)", ".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled" "stat buttons should be enabled"
); );
}); });
@@ -9538,14 +9531,14 @@ QUnit.module("Views", (hooks) => {
}); });
await click(target.querySelector(".o_external_button")); await click(target.querySelector(".o_external_button"));
assert.notOk(target.querySelector(".modal .oe_button_box button").disabled); assert.notOk(target.querySelector(".modal .o-form-buttonbox button").disabled);
await click(target.querySelector(".modal .oe_button_box button")); await click(target.querySelector(".modal .o-form-buttonbox button"));
assert.ok(target.querySelector(".modal .oe_button_box button").disabled); assert.ok(target.querySelector(".modal .o-form-buttonbox button").disabled);
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.notOk(target.querySelector(".modal .oe_button_box button").disabled); assert.notOk(target.querySelector(".modal .o-form-buttonbox button").disabled);
} }
); );
@@ -10379,7 +10372,7 @@ QUnit.module("Views", (hooks) => {
"yop", "yop",
]); ]);
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "bar"); await toggleMenuItem(target, "bar");
assert.containsN(target, ".o_group_header", 2); assert.containsN(target, ".o_group_header", 2);
assert.containsNone(target, ".o_data_row"); assert.containsNone(target, ".o_data_row");
@@ -10659,7 +10652,7 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC }); const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target, ".o_list_button_add"); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
// edit foo to trigger a delayed onchange // edit foo to trigger a delayed onchange
onchangeDef = makeDeferred(); onchangeDef = makeDeferred();
@@ -10796,7 +10789,9 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target.querySelector(".o_control_panel .o-kanban-button-new")); await click(
target.querySelector(".o_control_panel_main_buttons .d-none button.o-kanban-button-new")
);
//cannot save because there is a required field //cannot save because there is a required field
await click(target.querySelector(".o_control_panel .o_form_button_save")); await click(target.querySelector(".o_control_panel .o_form_button_save"));
@@ -10832,7 +10827,7 @@ QUnit.module("Views", (hooks) => {
resId: 1, resId: 1,
}); });
await click(target.querySelector(".o_form_button_create")); await createRecord();
await click(target.querySelector(".o-kanban-button-new")); await click(target.querySelector(".o-kanban-button-new"));
assert.containsOnce(target, ".modal"); assert.containsOnce(target, ".modal");
@@ -11335,29 +11330,29 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
await editInput(target, ".o_field_widget[name='name'] input", "aaa"); await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await click(target.querySelector(`.o_pager button.o_pager_next`)); await click(target.querySelector(`.o_pager button.o_pager_next`));
assert.containsOnce(target, ".o_form_editable"); assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"second record", "Partnersecond record"
]); );
assert.strictEqual( assert.strictEqual(
target.querySelector('.o_field_widget[name="name"] input').value, target.querySelector('.o_field_widget[name="name"] input').value,
"name" "name"
); );
await clickDiscard(target); await clickDiscard(target);
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"second record", "Partnersecond record"
]); );
assert.strictEqual( assert.strictEqual(
target.querySelector('.o_field_widget[name="name"] input').value, target.querySelector('.o_field_widget[name="name"] input').value,
"name" "name"
@@ -11365,10 +11360,10 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(`.o_pager button.o_pager_previous`)); await click(target.querySelector(`.o_pager button.o_pager_previous`));
assert.containsOnce(target, ".o_form_saved"); assert.containsOnce(target, ".o_form_saved");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa"); assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
}); });
@@ -11411,24 +11406,24 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
await editInput(target, ".o_field_widget[name='name'] input", "aaa"); await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await click(target.querySelector(".breadcrumb-item.o_back_button")); await click(target.querySelector(".breadcrumb-item.o_back_button"));
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partner"); assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partner");
assert.strictEqual(target.querySelector(".o_field_cell").textContent, "aaa"); assert.strictEqual(target.querySelector(".o_field_cell").textContent, "aaa");
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.containsOnce(target, ".o_form_editable"); assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa"); assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
}); });
@@ -11545,25 +11540,25 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1); await doAction(webClient, 1);
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
await editInput(target, ".o_field_widget[name='name'] input", "aaa"); await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await doAction(webClient, 2, { clearBreadcrumbs: true }); await doAction(webClient, 2, { clearBreadcrumbs: true });
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Other action"); assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Other action");
await doAction(webClient, 1, { clearBreadcrumbs: true }); await doAction(webClient, 1, { clearBreadcrumbs: true });
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.containsOnce(target, ".o_form_editable"); assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa"); assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
}); });
@@ -11764,14 +11759,14 @@ QUnit.module("Views", (hooks) => {
// Click on a row to open a record // Click on a row to open a record
await click(target.querySelector(".o_data_row td.o_data_cell")); await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [ assert.strictEqual(
"Partner", target.querySelector(".o_breadcrumb").textContent,
"first record", "Partnerfirst record"
]); );
// Return in the list view to detach the form view // Return in the list view to detach the form view
await click(target.querySelector(".o_back_button")); await click(target.querySelector(".o_back_button"));
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partner"); assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partner");
// Simulate tab/browser close in the list // Simulate tab/browser close in the list
window.dispatchEvent(new Event("beforeunload")); window.dispatchEvent(new Event("beforeunload"));
@@ -12103,13 +12098,16 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_field_widget[name='foo'] input").value, "yop"); assert.strictEqual(target.querySelector(".o_field_widget[name='foo'] input").value, "yop");
await editInput(target, ".o_field_widget[name='foo'] input", "test"); await editInput(target, ".o_field_widget[name='foo'] input", "test");
await click(target, ".o_form_button_create"); await click(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_form_button_create"
);
assert.verifySteps(["write"]); assert.verifySteps(["write"]);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_field_widget[name='foo'] input").value, target.querySelector(".o_field_widget[name='foo'] input").value,
"My little Foo Value" "My little Foo Value"
); );
assert.strictEqual(target.querySelector(".breadcrumb-item.active").textContent, "New"); assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "New");
}); });
QUnit.test("Auto save: error on save when create button clicked", async function (assert) { QUnit.test("Auto save: error on save when create button clicked", async function (assert) {
@@ -12141,7 +12139,7 @@ QUnit.module("Views", (hooks) => {
}); });
await editInput(target, ".o_field_widget[name='foo'] input", "test"); await editInput(target, ".o_field_widget[name='foo'] input", "test");
await click(target, ".o_form_button_create"); await createRecord();
assert.verifySteps(["write"]); assert.verifySteps(["write"]);
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_error_dialog"); assert.containsOnce(target, ".o_error_dialog");
@@ -12410,7 +12408,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsOnce(target, ".o_form_readonly"); assert.containsOnce(target, ".o_form_readonly");
await click(target.querySelector(".o_form_button_create")); await createRecord();
assert.containsOnce(target, ".o_form_editable"); assert.containsOnce(target, ".o_form_editable");
}); });
@@ -12576,7 +12574,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data"); assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data");
await click(target.querySelector(".o_list_view .o_list_button_add")); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
await click(target.querySelector(".o_form_view .breadcrumb-item a")); await click(target.querySelector(".o_form_view .breadcrumb-item a"));
assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data"); assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data");
@@ -12612,7 +12610,7 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data"); assert.containsOnce(target, ".o_list_view .o_content.o_view_sample_data");
await click(target.querySelector(".o_list_view .o_list_button_add")); await click(target, ".o_control_panel_main_buttons .d-none button.o_list_button_add");
assert.containsOnce(target, ".o_form_view .o_field_x2many .o_kanban_renderer"); assert.containsOnce(target, ".o_form_view .o_field_x2many .o_kanban_renderer");
assert.containsNone(target, ".o_view_nocontent"); assert.containsNone(target, ".o_view_nocontent");
}); });
@@ -12756,8 +12754,8 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_form_status_indicator").textContent, ""); assert.strictEqual(target.querySelector(".o_form_status_indicator").textContent, "");
await clickSave(target); await clickSave(target);
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_form_status_indicator").textContent.trim(), target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"Unable to save" "Unable to save. Correct the issue or discard changes"
); );
}); });
@@ -13045,7 +13043,7 @@ QUnit.module("Views", (hooks) => {
assert.isVisible(target.querySelector(".o_form_status_indicator_buttons")); assert.isVisible(target.querySelector(".o_form_status_indicator_buttons"));
await click(target, ".o_cp_action_menus .dropdown-toggle"); await click(target, ".o_cp_action_menus .dropdown-toggle");
await click(target.querySelectorAll(".o_cp_action_menus .dropdown-item")[1]); await click(target.querySelectorAll(".o_cp_action_menus .dropdown-item")[2]);
assert.containsOnce(target, ".modal"); assert.containsOnce(target, ".modal");
await click(target, ".modal-footer button.btn-primary"); await click(target, ".modal-footer button.btn-primary");
@@ -13,14 +13,11 @@ import {
editFavoriteName, editFavoriteName,
saveFavorite, saveFavorite,
switchView, switchView,
toggleComparisonMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleMenu, toggleMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
toggleSaveFavorite, toggleSaveFavorite,
toggleSearchBarMenu,
validateSearch, validateSearch,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
@@ -2292,7 +2289,7 @@ QUnit.module("Views", (hooks) => {
await toggleMenuItem(target, "Revenue"); await toggleMenuItem(target, "Revenue");
assert.strictEqual(getYAxeLabel(graph), "Revenue"); assert.strictEqual(getYAxeLabel(graph), "Revenue");
assert.ok(true, "Message"); assert.ok(true, "Message");
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color"); await toggleMenuItem(target, "Color");
checkModeIs(assert, graph, "line"); checkModeIs(assert, graph, "line");
assert.strictEqual(getXAxeLabel(graph), "Color"); assert.strictEqual(getXAxeLabel(graph), "Color");
@@ -2459,7 +2456,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "div.o_graph_canvas_container canvas"); assert.containsOnce(target, "div.o_graph_canvas_container canvas");
assert.containsNone(target, "div.o_view_nocontent"); assert.containsNone(target, "div.o_view_nocontent");
assert.containsNone(target, ".abc"); assert.containsNone(target, ".abc");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain"); await toggleMenuItem(target, "False Domain");
assert.containsOnce(target, "div.o_graph_canvas_container canvas"); assert.containsOnce(target, "div.o_graph_canvas_container canvas");
assert.containsNone(target, "div.o_view_nocontent"); assert.containsNone(target, "div.o_view_nocontent");
@@ -2484,7 +2481,7 @@ QUnit.module("Views", (hooks) => {
`, `,
}); });
checkLabels(assert, graph, ["xphone", "xpad"]); checkLabels(assert, graph, ["xphone", "xpad"]);
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color"); await toggleMenuItem(target, "Color");
checkLabels(assert, graph, ["Undefined", "red"]); checkLabels(assert, graph, ["Undefined", "red"]);
}); });
@@ -2560,7 +2557,7 @@ QUnit.module("Views", (hooks) => {
`, `,
}); });
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "First Favorite"); await editFavoriteName(target, "First Favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -2568,23 +2565,21 @@ QUnit.module("Views", (hooks) => {
await toggleMenu(target, "Measures"); await toggleMenu(target, "Measures");
await toggleMenuItem(target, "Foo"); await toggleMenuItem(target, "Foo");
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Second Favorite"); await editFavoriteName(target, "Second Favorite");
await saveFavorite(target); await saveFavorite(target);
await selectMode(target, "line"); await selectMode(target, "line");
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Third Favorite"); await editFavoriteName(target, "Third Favorite");
await saveFavorite(target); await saveFavorite(target);
await toggleGroupByMenu(target);
await toggleMenuItem(target, "Product"); await toggleMenuItem(target, "Product");
await toggleMenuItem(target, "Color"); await toggleMenuItem(target, "Color");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Fourth Favorite"); await editFavoriteName(target, "Fourth Favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -2751,7 +2746,7 @@ QUnit.module("Views", (hooks) => {
checkLegend(assert, graph, "Count"); checkLegend(assert, graph, "Count");
assert.strictEqual(getYAxeLabel(graph), "Count"); assert.strictEqual(getYAxeLabel(graph), "Count");
checkModeIs(assert, graph, "bar"); checkModeIs(assert, graph, "bar");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Context"); await toggleMenuItem(target, "Context");
checkLegend(assert, graph, "Foo"); checkLegend(assert, graph, "Foo");
assert.strictEqual(getYAxeLabel(graph), "Foo"); assert.strictEqual(getYAxeLabel(graph), "Foo");
@@ -2780,7 +2775,7 @@ QUnit.module("Views", (hooks) => {
</search> </search>
`, `,
}); });
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain"); await toggleMenuItem(target, "False Domain");
}); });
@@ -2812,7 +2807,7 @@ QUnit.module("Views", (hooks) => {
checkDatasets(assert, graph, "data", { data: [82, 157] }); checkDatasets(assert, graph, "data", { data: [82, 157] });
assert.strictEqual(getXAxeLabel(graph), "Product"); assert.strictEqual(getXAxeLabel(graph), "Product");
assert.strictEqual(getYAxeLabel(graph), "Foo"); assert.strictEqual(getYAxeLabel(graph), "Foo");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain"); await toggleMenuItem(target, "False Domain");
checkLabels(assert, graph, []); checkLabels(assert, graph, []);
checkLegend(assert, graph, []); checkLegend(assert, graph, []);
@@ -2908,9 +2903,7 @@ QUnit.module("Views", (hooks) => {
}); });
await toggleMenu(target, "Measures"); await toggleMenu(target, "Measures");
assert.deepEqual( assert.deepEqual(
[...target.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map( [...target.querySelectorAll(".o-dropdown .o_menu_item")].map((el) => el.innerText),
(el) => el.innerText
),
["Foo", "Revenue", "Count"] ["Foo", "Revenue", "Count"]
); );
}); });
@@ -2953,9 +2946,7 @@ QUnit.module("Views", (hooks) => {
}); });
await toggleMenu(target, "Measures"); await toggleMenu(target, "Measures");
assert.deepEqual( assert.deepEqual(
[...target.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map( [...target.querySelectorAll(".o-dropdown .o_menu_item")].map((el) => el.innerText),
(el) => el.innerText
),
["Bouh", "Foo", "Revenue", "Count"] ["Bouh", "Foo", "Revenue", "Count"]
); );
} }
@@ -3122,7 +3113,7 @@ QUnit.module("Views", (hooks) => {
views: [[false, "graph"]], views: [[false, "graph"]],
}); });
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").innerText, target.querySelector(".o_control_panel .o_breadcrumb .active:first-child").innerText,
"Glou glou" "Glou glou"
); );
}); });
@@ -3619,7 +3610,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_view_nocontent"); assert.containsOnce(target, ".o_view_nocontent");
assert.containsOnce(target, ".o_graph_canvas_container canvas"); assert.containsOnce(target, ".o_graph_canvas_container canvas");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain"); await toggleMenuItem(target, "False Domain");
assert.doesNotHaveClass( assert.doesNotHaveClass(
@@ -3652,7 +3643,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent"); assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, ".o_graph_canvas_container canvas"); assert.containsOnce(target, ".o_graph_canvas_container canvas");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain"); await toggleMenuItem(target, "False Domain");
assert.doesNotHaveClass(target, "o_view_sample_data"); assert.doesNotHaveClass(target, "o_view_sample_data");
@@ -3704,7 +3695,7 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
checkLabels(assert, graph, ["2", "3", "4", "24", "42", "48", "53", "63"]); checkLabels(assert, graph, ["2", "3", "4", "24", "42", "48", "53", "63"]);
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Foo"); await toggleMenuItem(target, "Foo");
checkLabels(assert, graph, ["xphone", "xpad"]); checkLabels(assert, graph, ["xphone", "xpad"]);
} }
@@ -3786,7 +3777,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
checkDatasets(assert, graph, ["data", "label"], { checkDatasets(assert, graph, ["data", "label"], {
@@ -3842,7 +3833,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
checkDatasets(assert, graph, ["data", "label"], { checkDatasets(assert, graph, ["data", "label"], {
@@ -3899,7 +3890,7 @@ QUnit.module("Views", (hooks) => {
checkDatasets(assert, graph, "data", { data: [82, 157] }); checkDatasets(assert, graph, "data", { data: [82, 157] });
def = makeDeferred(); def = makeDeferred();
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color"); await toggleMenuItem(target, "Color");
await toggleMenuItem(target, "Color"); await toggleMenuItem(target, "Color");
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
@@ -3984,7 +3975,7 @@ QUnit.module("Views", (hooks) => {
`, `,
}); });
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
checkLabels(assert, graph, ["", ""]); checkLabels(assert, graph, ["", ""]);
@@ -4018,7 +4009,7 @@ QUnit.module("Views", (hooks) => {
`, `,
}); });
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
checkDatasets(assert, graph, "backgroundColor", { checkDatasets(assert, graph, "backgroundColor", {
@@ -4075,7 +4066,7 @@ QUnit.module("Views", (hooks) => {
checkLabels(assert, graph, ["Q1 2016", "Q2 2016", "Undefined"]); checkLabels(assert, graph, ["Q1 2016", "Q2 2016", "Undefined"]);
checkLegend(assert, graph, "Count"); checkLegend(assert, graph, "Count");
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite"); await toggleMenuItem(target, "Favorite");
checkModeIs(assert, graph, "bar"); checkModeIs(assert, graph, "bar");
@@ -19,12 +19,12 @@ import {
triggerHotkey, triggerHotkey,
} from "@web/../tests/helpers/utils"; } from "@web/../tests/helpers/utils";
import { import {
getButtons, getVisibleButtons,
getFacetTexts, getFacetTexts,
getPagerLimit, getPagerLimit,
getPagerValue, getPagerValue,
pagerNext, pagerNext,
toggleFilterMenu, toggleSearchBarMenu,
validateSearch, validateSearch,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
@@ -104,7 +104,7 @@ function getTooltips(groupIndex) {
// Record // Record
async function createRecord() { async function createRecord() {
await click(target, "button.o-kanban-button-new"); await click(target, ".o_control_panel_main_buttons .d-none button.o-kanban-button-new");
} }
async function quickCreateRecord(groupIndex) { async function quickCreateRecord(groupIndex) {
@@ -432,7 +432,7 @@ QUnit.module("Views", (hooks) => {
}); });
QUnit.test("basic grouped rendering", async (assert) => { QUnit.test("basic grouped rendering", async (assert) => {
assert.expect(14); assert.expect(13);
await makeView({ await makeView({
type: "kanban", type: "kanban",
@@ -458,12 +458,6 @@ QUnit.module("Views", (hooks) => {
} }
}, },
}); });
assert.hasClass(
target.querySelector(".o_kanban_group"),
"bg-200",
"o_kanban_group should have a background"
);
assert.hasClass(target.querySelector(".o_kanban_view"), "o_kanban_test"); assert.hasClass(target.querySelector(".o_kanban_view"), "o_kanban_test");
assert.hasClass(target.querySelector(".o_kanban_renderer"), "o_kanban_grouped"); assert.hasClass(target.querySelector(".o_kanban_renderer"), "o_kanban_grouped");
assert.containsN(target, ".o_kanban_group", 2); assert.containsN(target, ".o_kanban_group", 2);
@@ -712,7 +706,7 @@ QUnit.module("Views", (hooks) => {
[...target.querySelectorAll(".o_kanban_group")].map((el) => [...target.querySelectorAll(".o_kanban_group")].map((el) =>
el.innerText.replace(/\s/g, " ") el.innerText.replace(/\s/g, " ")
), ),
["None (1)", "gold yop blip", "silver yop gnap"] ["None 1", "gold yop blip", "silver yop gnap"]
); );
await click(getColumn(0)); await click(getColumn(0));
@@ -1600,7 +1594,7 @@ QUnit.module("Views", (hooks) => {
assert.containsN(target, ".o_kanban_group", 2); assert.containsN(target, ".o_kanban_group", 2);
assert.containsNone(target, ".o_kanban_quick_add"); assert.containsNone(target, ".o_kanban_quick_add");
await click(target.querySelector(".o-kanban-button-new")); await createRecord();
assert.containsNone(target, ".o_kanban_quick_create"); assert.containsNone(target, ".o_kanban_quick_create");
assert.verifySteps(["create record"]); assert.verifySteps(["create record"]);
@@ -1622,7 +1616,10 @@ QUnit.module("Views", (hooks) => {
}); });
assert.containsN(target, ".o_kanban_group.o_group_draggable", 2); assert.containsN(target, ".o_kanban_group.o_group_draggable", 2);
assert.containsOnce(target, ".btn-primary.o-kanban-button-new"); assert.containsOnce(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex button.o-kanban-button-new"
);
assert.containsOnce(target, ".o_column_quick_create"); assert.containsOnce(target, ".o_column_quick_create");
await createRecord(); await createRecord();
@@ -1996,7 +1993,7 @@ QUnit.module("Views", (hooks) => {
groupBy: ["bar"], groupBy: ["bar"],
}); });
await click(target, ".o-kanban-button-new"); await createRecord();
assert.strictEqual( assert.strictEqual(
document.activeElement, document.activeElement,
target.querySelector(".o_field_widget[name=int_field] input") target.querySelector(".o_field_widget[name=int_field] input")
@@ -2027,7 +2024,7 @@ QUnit.module("Views", (hooks) => {
groupBy: ["bar"], groupBy: ["bar"],
}); });
await click(target, ".o-kanban-button-new"); await createRecord();
assert.strictEqual( assert.strictEqual(
document.activeElement, document.activeElement,
target.querySelector(".o_field_widget[name=foo] input") target.querySelector(".o_field_widget[name=foo] input")
@@ -5482,7 +5479,7 @@ QUnit.module("Views", (hooks) => {
assert.deepEqual(getFacetTexts(target), []); assert.deepEqual(getFacetTexts(target), []);
// validate presence of the search arch info // validate presence of the search arch info
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
assert.containsOnce(target, ".o_filter_menu .o_menu_item"); assert.containsOnce(target, ".o_filter_menu .o_menu_item");
}); });
@@ -5941,7 +5938,7 @@ QUnit.module("Views", (hooks) => {
assert.containsN(target, ".o_kanban_group", 2, "should still have two columns"); assert.containsN(target, ".o_kanban_group", 2, "should still have two columns");
assert.strictEqual( assert.strictEqual(
getColumn(0).querySelector(".o_column_title").innerText, getColumn(0).querySelector(".o_column_title").innerText,
"None (2)", "None\n2",
"first column should have no id (Undefined column)" "first column should have no id (Undefined column)"
); );
@@ -6503,7 +6500,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_kanban_group.o_column_folded"); assert.containsOnce(target, ".o_kanban_group.o_column_folded");
assert.deepEqual( assert.deepEqual(
[...target.querySelectorAll(".o_kanban_group")].map((e) => e.textContent), [...target.querySelectorAll(".o_kanban_group")].map((e) => e.textContent),
["not folded", "folded (0)"] ["not folded", "folded0"]
); );
}); });
@@ -8645,7 +8642,10 @@ QUnit.module("Views", (hooks) => {
await editColumnName("new column"); await editColumnName("new column");
await validateColumn(); await validateColumn();
assert.containsOnce(target, ".o-kanban-button-new"); assert.containsOnce(
target,
".o_control_panel_main_buttons .d-none.d-xl-inline-flex button.o-kanban-button-new"
);
}); });
QUnit.test("group_by_tooltip option when grouping on a many2one", async (assert) => { QUnit.test("group_by_tooltip option when grouping on a many2one", async (assert) => {
@@ -11373,7 +11373,7 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps([]); assert.verifySteps([]);
await click(target, ".o-kanban-button-new"); await createRecord();
assert.verifySteps(["create record"]); assert.verifySteps(["create record"]);
assert.containsNone(target, ".o_kanban_quick_create"); assert.containsNone(target, ".o_kanban_quick_create");
@@ -11457,7 +11457,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.verifySteps([]); assert.verifySteps([]);
await click(target, ".o-kanban-button-new"); await createRecord();
assert.verifySteps(["create record"]); assert.verifySteps(["create record"]);
assert.containsNone(target, ".o_kanban_quick_create"); assert.containsNone(target, ".o_kanban_quick_create");
@@ -11517,11 +11517,11 @@ QUnit.module("Views", (hooks) => {
`, `,
}); });
assert.containsNone(target, ".dropdown-menu"); assert.containsNone(target, ".o_content .dropdown-menu");
await click(target, ".o_kanban_renderer .dropdown-toggle"); await click(target, ".o_kanban_renderer .dropdown-toggle");
assert.containsOnce(target, ".dropdown-menu"); assert.containsOnce(target, ".o_content .dropdown-menu");
await click(target, ".o_kanban_renderer .dropdown-menu .dropdown-item"); await click(target, ".o_kanban_renderer .dropdown-menu .dropdown-item");
assert.containsNone(target, ".dropdown-menu"); assert.containsNone(target, ".o_content .dropdown-menu");
}); });
QUnit.test("can use JSON in kanban template", async (assert) => { QUnit.test("can use JSON in kanban template", async (assert) => {
@@ -12276,13 +12276,13 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2); assert.containsN(getColumn(0), ".o_kanban_record", 2);
assert.hasClass(getColumn(1), "o_column_folded"); assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "xmo (2)"); assert.strictEqual(getColumn(1).innerText, "xmo\n2");
await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded"); await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded");
assert.containsN(getColumn(0), ".o_kanban_record", 1); assert.containsN(getColumn(0), ".o_kanban_record", 1);
assert.hasClass(getColumn(1), "o_column_folded"); assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "xmo (3)"); assert.strictEqual(getColumn(1).innerText, "xmo\n3");
}); });
QUnit.test("drag record on initially folded column should not unfold it", async (assert) => { QUnit.test("drag record on initially folded column should not unfold it", async (assert) => {
@@ -12310,13 +12310,13 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2); assert.containsN(getColumn(0), ".o_kanban_record", 2);
assert.hasClass(getColumn(1), "o_column_folded"); assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "xmo (2)"); assert.strictEqual(getColumn(1).innerText, "xmo\n2");
await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded"); await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded");
assert.containsN(getColumn(0), ".o_kanban_record", 1); assert.containsN(getColumn(0), ".o_kanban_record", 1);
assert.hasClass(getColumn(1), "o_column_folded"); assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "xmo (3)"); assert.strictEqual(getColumn(1).innerText, "xmo\n3");
}); });
QUnit.test("drag record to folded column, with progressbars", async (assert) => { QUnit.test("drag record to folded column, with progressbars", async (assert) => {
@@ -12356,7 +12356,7 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2); assert.containsN(getColumn(0), ".o_kanban_record", 2);
assert.hasClass(getColumn(1), "o_column_folded"); assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "Yes (2)"); assert.strictEqual(getColumn(1).innerText, "Yes\n2");
await dragAndDrop( await dragAndDrop(
".o_kanban_group:first-child .o_kanban_record", ".o_kanban_group:first-child .o_kanban_record",
@@ -12364,7 +12364,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.containsOnce(getColumn(0), ".o_kanban_record"); assert.containsOnce(getColumn(0), ".o_kanban_record");
assert.strictEqual(getColumn(1).innerText, "Yes (3)"); assert.strictEqual(getColumn(1).innerText, "Yes\n3");
assert.deepEqual( assert.deepEqual(
getProgressBars(0).map((pb) => pb.style.width), getProgressBars(0).map((pb) => pb.style.width),
["100%"] ["100%"]
@@ -12575,8 +12575,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN(target, ".o_column_folded", 2); assert.containsN(target, ".o_column_folded", 2);
assert.strictEqual( assert.strictEqual(
getNodesTextContent(target.querySelectorAll("span.o_column_title")).join(" "), getNodesTextContent(target.querySelectorAll(".o_column_title")).join(" "),
"hello (2) xmo (2)" "hello2 xmo2"
); );
assert.containsNone(target, ".o_nocontent_help"); assert.containsNone(target, ".o_nocontent_help");
@@ -13084,10 +13084,10 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
const cpButtons = getButtons(target); const cpButtons = getVisibleButtons(target);
assert.deepEqual( assert.deepEqual(
[...cpButtons].map((button) => button.textContent.trim()), [...cpButtons].map((button) => button.textContent.trim()),
["New", "display"] ["New", "display", ""]
); );
assert.hasClass(cpButtons[1], "display"); assert.hasClass(cpButtons[1], "display");
+12 -12
View File
@@ -70,7 +70,7 @@ QUnit.module("Views", (hooks) => {
class ToyComponent extends Component {} class ToyComponent extends Component {}
ToyComponent.template = xml` ToyComponent.template = xml`
<Layout display="props.display"> <Layout display="props.display">
<t t-set-slot="control-panel-top-right"> <t t-set-slot="layout-actions">
<div class="toy_search_bar" /> <div class="toy_search_bar" />
</t> </t>
<div class="toy_content" /> <div class="toy_content" />
@@ -84,7 +84,7 @@ QUnit.module("Views", (hooks) => {
searchViewId: false, searchViewId: false,
}); });
assert.containsOnce(target, ".o_control_panel .o_cp_top_right .toy_search_bar"); assert.containsOnce(target, ".o_control_panel .o_control_panel_actions .toy_search_bar");
assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel"); assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel");
assert.containsNone(target, ".o_cp_searchview"); assert.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content"); assert.containsOnce(target, ".o_content > .toy_content");
@@ -106,7 +106,7 @@ QUnit.module("Views", (hooks) => {
} }
ToyComponent.template = xml` ToyComponent.template = xml`
<Layout className="'o_view_sample_data'" display="{ <Layout className="'o_view_sample_data'" display="{
controlPanel: { 'top-right': false, 'bottom-right': false, 'bottom-left': false }, controlPanel: {},
searchPanel: true, searchPanel: true,
}"> }">
<div class="toy_content" /> <div class="toy_content" />
@@ -122,7 +122,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_search_panel"); assert.containsOnce(target, ".o_search_panel");
assert.containsOnce(target, ".o_control_panel"); assert.containsOnce(target, ".o_control_panel");
assert.containsOnce(target, ".breadcrumb"); assert.containsOnce(target, ".o_breadcrumb");
assert.containsOnce(target, ".o_component_with_search_panel"); assert.containsOnce(target, ".o_component_with_search_panel");
assert.containsOnce(target, ".o_content > .toy_content"); assert.containsOnce(target, ".o_content > .toy_content");
}); });
@@ -159,7 +159,7 @@ QUnit.module("Views", (hooks) => {
} }
ToyB.template = xml` ToyB.template = xml`
<Layout className="'toy_b'" display="props.display"> <Layout className="'toy_b'" display="props.display">
<t t-set-slot="control-panel-top-right"> <t t-set-slot="layout-actions">
<div class="toy_b_breadcrumbs" /> <div class="toy_b_breadcrumbs" />
</t> </t>
<ToyC/> <ToyC/>
@@ -170,7 +170,7 @@ QUnit.module("Views", (hooks) => {
class ToyA extends Component {} class ToyA extends Component {}
ToyA.template = xml` ToyA.template = xml`
<Layout className="'toy_a'" display="props.display"> <Layout className="'toy_a'" display="props.display">
<t t-set-slot="control-panel-top-right"> <t t-set-slot="layout-actions">
<div class="toy_a_search" /> <div class="toy_a_search" />
</t> </t>
<ToyB display="props.display"/> <ToyB display="props.display"/>
@@ -291,21 +291,21 @@ QUnit.module("Views", (hooks) => {
}); });
QUnit.test("Simple rendering: with dynamically displayed search", async (assert) => { QUnit.test("Simple rendering: with dynamically displayed search", async (assert) => {
let displayControlPanelTopRight = true; let displayLayoutActions = true;
class ToyComponent extends Component { class ToyComponent extends Component {
get display() { get display() {
return { return {
...this.props.display, ...this.props.display,
controlPanel: { controlPanel: {
...this.props.display.controlPanel, ...this.props.display.controlPanel,
"top-right": displayControlPanelTopRight, layoutActions: displayLayoutActions,
}, },
}; };
} }
} }
ToyComponent.template = xml` ToyComponent.template = xml`
<Layout display="display"> <Layout display="display">
<t t-set-slot="control-panel-top-right"> <t t-set-slot="layout-actions">
<div class="toy_search_bar" /> <div class="toy_search_bar" />
</t> </t>
<div class="toy_content" /> <div class="toy_content" />
@@ -319,16 +319,16 @@ QUnit.module("Views", (hooks) => {
searchViewId: false, searchViewId: false,
}); });
assert.containsOnce(target, ".o_control_panel .o_cp_top_right .toy_search_bar"); assert.containsOnce(target, ".o_control_panel .o_control_panel_actions .toy_search_bar");
assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel"); assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel");
assert.containsNone(target, ".o_cp_searchview"); assert.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content"); assert.containsOnce(target, ".o_content > .toy_content");
displayControlPanelTopRight = false; displayLayoutActions = false;
comp.render(); comp.render();
await nextTick(); await nextTick();
assert.containsNone(target, ".o_control_panel .o_cp_top_right .toy_search_bar"); assert.containsNone(target, ".o_control_panel .o_control_panel_actions .toy_search_bar");
assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel"); assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel");
assert.containsNone(target, ".o_cp_searchview"); assert.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content"); assert.containsOnce(target, ".o_content > .toy_content");
File diff suppressed because it is too large Load Diff
+120 -133
View File
@@ -26,10 +26,7 @@ import {
setupControlPanelFavoriteMenuRegistry, setupControlPanelFavoriteMenuRegistry,
setupControlPanelServiceRegistry, setupControlPanelServiceRegistry,
toggleAddCustomGroup, toggleAddCustomGroup,
toggleComparisonMenu, toggleSearchBarMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleMenu, toggleMenu,
toggleMenuItem, toggleMenuItem,
toggleMenuItemOption, toggleMenuItemOption,
@@ -265,9 +262,9 @@ QUnit.module("Views", (hooks) => {
</pivot>`, </pivot>`,
}); });
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item").innerText, target.querySelector(".o_pivot_buttons .dropdown-menu .dropdown-item").innerText,
"BAR" "BAR"
); );
assert.strictEqual( assert.strictEqual(
@@ -366,9 +363,9 @@ QUnit.module("Views", (hooks) => {
// there should be only one displayed measure as the other one is invisible // there should be only one displayed measure as the other one is invisible
assert.containsOnce(target, ".o_pivot_measure_row"); assert.containsOnce(target, ".o_pivot_measure_row");
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
// there should be only one measure besides count, as the other one is invisible // there should be only one measure besides count, as the other one is invisible
assert.containsN(target, ".o_cp_bottom_left .dropdown-menu .dropdown-item", 2); assert.containsN(target, ".o_pivot_buttons .dropdown-menu .dropdown-item", 2);
// the invisible field souldn't be in the groupable fields neither // the invisible field souldn't be in the groupable fields neither
await click(target.querySelector(".o_pivot_header_cell_closed")); await click(target.querySelector(".o_pivot_header_cell_closed"));
assert.containsNone(target, '.dropdown-menu a[data-field="foo2"]'); assert.containsNone(target, '.dropdown-menu a[data-field="foo2"]');
@@ -432,10 +429,10 @@ QUnit.module("Views", (hooks) => {
</pivot>`, </pivot>`,
}); });
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.containsOnce( assert.containsOnce(
target, target,
".o_cp_bottom_left .dropdown-menu .dropdown-item:contains(Computed and not stored)" ".o_pivot_buttons .dropdown-menu .dropdown-item:contains(Computed and not stored)"
); );
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_pivot_measure_row").innerText, target.querySelector(".o_pivot_measure_row").innerText,
@@ -580,7 +577,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true }, context: { search_default_date_filter: true },
}); });
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
// hover Count in first group // hover Count in first group
@@ -648,7 +645,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true }, context: { search_default_date_filter: true },
}); });
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
// hover the second origin in second group // hover the second origin in second group
@@ -773,7 +770,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true }, context: { search_default_date_filter: true },
}); });
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
assert.hasClass(target.querySelector("table"), "o_enable_linking"); assert.hasClass(target.querySelector("table"), "o_enable_linking");
@@ -829,9 +826,9 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
await click(target.querySelector(".o_cp_bottom_left .dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons .dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu .dropdown-item"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu .dropdown-item");
const measure = target.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item"); const measure = target.querySelector(".o_pivot_buttons .dropdown-menu .dropdown-item");
assert.strictEqual(measure.innerText, "Count"); assert.strictEqual(measure.innerText, "Count");
assert.hasClass(measure, "selected", "The count measure should be selected"); assert.hasClass(measure, "selected", "The count measure should be selected");
}); });
@@ -861,7 +858,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.strictEqual(readGroupCount, 1, "should have done 1 rpc"); assert.strictEqual(readGroupCount, 1, "should have done 1 rpc");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter"); await toggleMenuItem(target, "Some Filter");
assert.containsOnce( assert.containsOnce(
target, target,
@@ -1064,16 +1061,16 @@ QUnit.module("Views", (hooks) => {
}); });
// open group by dropdown // open group by dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
3, 3,
"should have 3 dropdown items in searchview groupby" "should have 3 dropdown items in searchview groupby"
); );
assert.containsOnce( assert.containsOnce(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", ".o_control_panel .o_cp_searchview .dropdown-menu .o_add_custom_group_menu",
"should have custom group generator in searchview groupby" "should have custom group generator in searchview groupby"
); );
@@ -1129,10 +1126,10 @@ QUnit.module("Views", (hooks) => {
}); });
// open group by dropdown // open group by dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
2, 2,
"should have 2 dropdown items in searchview groupby" "should have 2 dropdown items in searchview groupby"
); );
@@ -1147,12 +1144,12 @@ QUnit.module("Views", (hooks) => {
); );
// add a custom group in searchview groupby // add a custom group in searchview groupby
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
await applyGroup(target); await applyGroup(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
3, 3,
"should have 3 dropdown items in searchview groupby now" "should have 3 dropdown items in searchview groupby now"
); );
@@ -1179,10 +1176,10 @@ QUnit.module("Views", (hooks) => {
); );
// applying custom groupby in pivot groupby dropdown will not update search dropdown // applying custom groupby in pivot groupby dropdown will not update search dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
3, 3,
"should still have 3 dropdown items in searchview groupby dropdown" "should still have 3 dropdown items in searchview groupby dropdown"
); );
@@ -1208,10 +1205,10 @@ QUnit.module("Views", (hooks) => {
}); });
// open group by dropdown // open group by dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
2, 2,
"should have 2 dropdown items in searchview groupby" "should have 2 dropdown items in searchview groupby"
); );
@@ -1219,7 +1216,7 @@ QUnit.module("Views", (hooks) => {
await applyGroup(target); await applyGroup(target);
assert.containsN( assert.containsN(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
3, 3,
"should have 3 dropdown items in searchview groupby now" "should have 3 dropdown items in searchview groupby now"
); );
@@ -1333,15 +1330,15 @@ QUnit.module("Views", (hooks) => {
}); });
// open group by dropdown // open group by dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsNone( assert.containsNone(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
"should not have any dropdown item in searchview groupby" "should not have any dropdown item in searchview groupby"
); );
assert.containsOnce( assert.containsOnce(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", ".o_control_panel .o_cp_searchview .dropdown-menu .o_add_custom_group_menu",
"should have add custom group item in searchview groupby" "should have add custom group item in searchview groupby"
); );
// click on closed header to open dropdown // click on closed header to open dropdown
@@ -1403,15 +1400,15 @@ QUnit.module("Views", (hooks) => {
}); });
// open group by dropdown // open group by dropdown
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
assert.containsOnce( assert.containsOnce(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", ".o_control_panel .o_cp_searchview .dropdown-menu .o_menu_item",
"should have 1 dropdown item in searchview groupby" "should have 1 dropdown item in searchview groupby"
); );
assert.containsNone( assert.containsNone(
target, target,
".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", ".o_control_panel .o_cp_searchview .dropdown-menu .o_add_custom_group_menu",
"should not have custom group generator in searchview groupby" "should not have custom group generator in searchview groupby"
); );
@@ -1497,16 +1494,16 @@ QUnit.module("Views", (hooks) => {
"should have 3 cells: 1 for the open header, and 2 for data" "should have 3 cells: 1 for the open header, and 2 for data"
); );
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.doesNotHaveClass( assert.doesNotHaveClass(
$(target).find(".dropdown-item:contains(Count)"), $(target).find(".dropdown-item:contains(Count)"),
"selected", "selected",
"the __count measure should not be selected" "the __count measure should not be selected"
); );
await click($(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); await click($(target).find(".o_pivot_buttons .dropdown-item:contains(Count)")[0]);
assert.hasClass( assert.hasClass(
$(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)"), $(target).find(".o_pivot_buttons .dropdown-item:contains(Count)"),
"selected", "selected",
"the __count measure should be selected" "the __count measure should be selected"
); );
@@ -1518,7 +1515,7 @@ QUnit.module("Views", (hooks) => {
); );
assert.strictEqual(rpcCount, 2, "should have done 2 rpcs to reload data"); assert.strictEqual(rpcCount, 2, "should have done 2 rpcs to reload data");
await click($(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); await click($(target).find(".o_pivot_buttons .dropdown-item:contains(Count)")[0]);
assert.doesNotHaveClass( assert.doesNotHaveClass(
$(target).find(".dropdown-item:contains(Count)")[0], $(target).find(".dropdown-item:contains(Count)")[0],
@@ -1545,8 +1542,8 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent"); assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
await click($(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); await click($(target).find(".o_pivot_buttons .dropdown-item:contains(Count)")[0]);
assert.containsOnce(target, ".o_view_nocontent"); assert.containsOnce(target, ".o_view_nocontent");
assert.containsNone(target, "table"); assert.containsNone(target, "table");
@@ -1567,7 +1564,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent"); assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter"); await toggleMenuItem(target, "Some Filter");
assert.containsOnce(target, ".o_view_nocontent"); assert.containsOnce(target, ".o_view_nocontent");
@@ -1606,7 +1603,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_searchview .o_searchview_facet"); assert.containsOnce(target, ".o_searchview .o_searchview_facet");
assert.containsOnce(target, ".o_view_nocontent"); assert.containsOnce(target, ".o_view_nocontent");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter"); await toggleMenuItem(target, "Some Filter");
assert.containsN(target, ".o_searchview .o_searchview_facet", 2); assert.containsN(target, ".o_searchview .o_searchview_facet", 2);
assert.containsOnce(target, ".o_view_nocontent"); assert.containsOnce(target, ".o_view_nocontent");
@@ -1659,7 +1656,7 @@ QUnit.module("Views", (hooks) => {
"should have 1 row for measure Foo" "should have 1 row for measure Foo"
); );
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.containsNone(target, "table"); assert.containsNone(target, "table");
@@ -1701,7 +1698,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_pivot_cell_value", "should have only 1 cell"); assert.containsOnce(target, ".o_pivot_cell_value", "should have only 1 cell");
assert.containsOnce(target, "tbody tr", "should have 1 rows"); assert.containsOnce(target, "tbody tr", "should have 1 rows");
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product"); await toggleMenuItem(target, "Product");
assert.containsN(target, ".o_pivot_cell_value", 3, "should have 3 cells"); assert.containsN(target, ".o_pivot_cell_value", 3, "should have 3 cells");
@@ -1781,7 +1778,7 @@ QUnit.module("Views", (hooks) => {
); );
// expand on date:days, product // expand on date:days, product
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Month"); await toggleMenuItemOption(target, "Date", "Month");
nbReadGroups = 0; nbReadGroups = 0;
@@ -1835,7 +1832,7 @@ QUnit.module("Views", (hooks) => {
}); });
// expand on date:days, product // expand on date:days, product
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Month"); await toggleMenuItemOption(target, "Date", "Month");
await toggleMenuItem(target, "Product"); await toggleMenuItem(target, "Product");
@@ -1963,7 +1960,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav1"); await editFavoriteName(target, "Fav1");
await saveFavorite(target); await saveFavorite(target);
@@ -1977,7 +1974,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav2"); await editFavoriteName(target, "Fav2");
await saveFavorite(target); await saveFavorite(target);
@@ -1991,7 +1988,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"], pivot_row_groupby: ["product_id"],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav3"); await editFavoriteName(target, "Fav3");
await saveFavorite(target); await saveFavorite(target);
@@ -2051,7 +2048,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"], pivot_row_groupby: ["product_id"],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "1"); await editFavoriteName(target, "1");
await saveFavorite(target); await saveFavorite(target);
@@ -2064,7 +2061,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "2"); await editFavoriteName(target, "2");
await saveFavorite(target); await saveFavorite(target);
@@ -2078,7 +2075,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "3"); await editFavoriteName(target, "3");
await saveFavorite(target); await saveFavorite(target);
@@ -2092,7 +2089,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"], pivot_row_groupby: ["product_id"],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "4"); await editFavoriteName(target, "4");
await saveFavorite(target); await saveFavorite(target);
@@ -2106,7 +2103,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"], pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"], pivot_row_groupby: ["product_id"],
}; };
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "5"); await editFavoriteName(target, "5");
await saveFavorite(target); await saveFavorite(target);
@@ -2139,7 +2136,7 @@ QUnit.module("Views", (hooks) => {
); );
// Apply both groupbys // Apply both groupbys
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product"); await toggleMenuItem(target, "Product");
assert.strictEqual( assert.strictEqual(
target.querySelector("tbody .o_pivot_header_cell_closed").textContent, target.querySelector("tbody .o_pivot_header_cell_closed").textContent,
@@ -2198,7 +2195,7 @@ QUnit.module("Views", (hooks) => {
); );
// Apply BAR groupbys // Apply BAR groupbys
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bar"); await toggleMenuItem(target, "Bar");
assert.strictEqual( assert.strictEqual(
target.querySelector("tbody .o_pivot_header_cell_closed").textContent, target.querySelector("tbody .o_pivot_header_cell_closed").textContent,
@@ -2317,7 +2314,7 @@ QUnit.module("Views", (hooks) => {
); );
// activate the unique existing favorite // activate the unique existing favorite
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0); await toggleMenuItem(target, 0);
assert.strictEqual( assert.strictEqual(
@@ -2358,7 +2355,7 @@ QUnit.module("Views", (hooks) => {
); );
// activate AGAIN the unique existing favorite // activate AGAIN the unique existing favorite
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0); await toggleMenuItem(target, 0);
assert.strictEqual( assert.strictEqual(
@@ -2446,7 +2443,7 @@ QUnit.module("Views", (hooks) => {
); );
// Equivalent to unload the filter // Equivalent to unload the filter
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite"); await toggleMenuItem(target, "My fake favorite");
// collapse all headers // collapse all headers
await click(target, ".o_pivot_header_cell_opened:first-child"); await click(target, ".o_pivot_header_cell_opened:first-child");
@@ -2488,7 +2485,7 @@ QUnit.module("Views", (hooks) => {
// Equivalent to load another filter // Equivalent to load another filter
await removeFacet(target); // remove previously saved favorite await removeFacet(target); // remove previously saved favorite
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite 2"); await toggleMenuItem(target, "My fake favorite 2");
// Check Columns // Check Columns
@@ -2553,7 +2550,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("thead .dropdown-item")[1]); await click(target.querySelectorAll("thead .dropdown-item")[1]);
// Set a domain // Set a domain
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 1"); await toggleMenuItem(target, "My Filter 1");
// Save to favorites and check that column groupbys were not lost // Save to favorites and check that column groupbys were not lost
@@ -2563,7 +2560,6 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["__count"], pivot_measures: ["__count"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 1"); await editFavoriteName(target, "My favorite 1");
await saveFavorite(target); await saveFavorite(target);
@@ -2574,7 +2570,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]);
// Set a domain // Set a domain
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 2"); await toggleMenuItem(target, "My Filter 2");
expectedContext = { expectedContext = {
@@ -2583,7 +2579,6 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["__count"], pivot_measures: ["__count"],
pivot_row_groupby: [], pivot_row_groupby: [],
}; };
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 2"); await editFavoriteName(target, "My favorite 2");
await saveFavorite(target); await saveFavorite(target);
@@ -2626,7 +2621,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(getCurrentValues(target), values.join(",")); assert.strictEqual(getCurrentValues(target), values.join(","));
// reload (should keep folded groups folded as col/row groupbys didn't change) // reload (should keep folded groups folded as col/row groupbys didn't change)
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Dummy Filter"); await toggleMenuItem(target, "Dummy Filter");
assert.strictEqual(getCurrentValues(target), values.join(",")); assert.strictEqual(getCurrentValues(target), values.join(","));
@@ -2692,11 +2687,10 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
// Set a domain for empty results // Set a domain for empty results
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 1"); await toggleMenuItem(target, "My Filter 1");
assert.containsNone(target, "table"); assert.containsNone(target, "table");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 1"); await editFavoriteName(target, "My favorite 1");
await saveFavorite(target); await saveFavorite(target);
@@ -2705,11 +2699,10 @@ QUnit.module("Views", (hooks) => {
await removeFacet(target); // remove previously saved favorite await removeFacet(target); // remove previously saved favorite
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 2"); await toggleMenuItem(target, "My Filter 2");
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 2"); await editFavoriteName(target, "My favorite 2");
await saveFavorite(target); await saveFavorite(target);
@@ -2807,7 +2800,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelectorAll(".o_pivot_cell_value")[4].innerText, ""); // xphone December 2016 assert.strictEqual(target.querySelectorAll(".o_pivot_cell_value")[4].innerText, ""); // xphone December 2016
// invert axis, and reopen column groupings // invert axis, and reopen column groupings
await click(target.querySelector(".o_cp_bottom_left .o_pivot_flip_button")); await click(target.querySelector(".o_pivot_buttons .o_pivot_flip_button"));
await click(target.querySelector("thead .o_pivot_header_cell_opened")); await click(target.querySelector("thead .o_pivot_header_cell_opened"));
await click(target.querySelector("thead .o_pivot_header_cell_closed")); await click(target.querySelector("thead .o_pivot_header_cell_closed"));
await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]);
@@ -2847,7 +2840,7 @@ QUnit.module("Views", (hooks) => {
); );
// select filter "Bayou" in control panel // select filter "Bayou" in control panel
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou"); await toggleMenuItem(target, "Bayou");
assert.deepEqual( assert.deepEqual(
@@ -2889,7 +2882,7 @@ QUnit.module("Views", (hooks) => {
); );
// select filter "Bayou" in control panel // select filter "Bayou" in control panel
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou"); await toggleMenuItem(target, "Bayou");
assert.deepEqual( assert.deepEqual(
@@ -2906,7 +2899,7 @@ QUnit.module("Views", (hooks) => {
); );
// unselect filter "Bayou" in control panel // unselect filter "Bayou" in control panel
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou"); await toggleMenuItem(target, "Bayou");
assert.deepEqual( assert.deepEqual(
@@ -2964,7 +2957,7 @@ QUnit.module("Views", (hooks) => {
"the active measure should be amount" "the active measure should be amount"
); );
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite"); await toggleMenuItem(target, "My fake favorite");
assert.containsOnce( assert.containsOnce(
@@ -3145,13 +3138,13 @@ QUnit.module("Views", (hooks) => {
}, },
}); });
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-item"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-item");
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-item").innerText, target.querySelector(".o_pivot_buttons .dropdown-item").innerText,
"Count" "Count"
); );
assert.hasClass(target.querySelector(".o_cp_bottom_left .dropdown-item"), "selected"); assert.hasClass(target.querySelector(".o_pivot_buttons .dropdown-item"), "selected");
}); });
QUnit.test("not use a many2one as a measure by default", async function (assert) { QUnit.test("not use a many2one as a measure by default", async function (assert) {
@@ -3167,13 +3160,13 @@ QUnit.module("Views", (hooks) => {
<field name="date" interval="month" type="col"/> <field name="date" interval="month" type="col"/>
</pivot>`, </pivot>`,
}); });
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-item"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-item");
assert.strictEqual( assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-item").innerText, target.querySelector(".o_pivot_buttons .dropdown-item").innerText,
"Count" "Count"
); );
assert.hasClass(target.querySelector(".o_cp_bottom_left .dropdown-item"), "selected"); assert.hasClass(target.querySelector(".o_pivot_buttons .dropdown-item"), "selected");
}); });
QUnit.test("pivot view with many2one field as a measure", async function (assert) { QUnit.test("pivot view with many2one field as a measure", async function (assert) {
@@ -3261,7 +3254,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("tbody .dropdown-item")[4]); await click(target.querySelectorAll("tbody .dropdown-item")[4]);
// Add a filter // Add a filter
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter"); await toggleMenuItem(target, "Some Filter");
assert.containsOnce( assert.containsOnce(
@@ -3276,7 +3269,6 @@ QUnit.module("Views", (hooks) => {
); );
// Save current search to favorite // Save current search to favorite
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite"); await editFavoriteName(target, "My favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -3312,7 +3304,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "tbody tr", "should have 1 row initially"); assert.containsOnce(target, "tbody tr", "should have 1 row initially");
def = makeDeferred(); def = makeDeferred();
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product"); await toggleMenuItem(target, "Product");
await toggleMenuItem(target, "Customer"); await toggleMenuItem(target, "Customer");
@@ -3361,9 +3353,9 @@ QUnit.module("Views", (hooks) => {
</pivot>`, </pivot>`,
}); });
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.strictEqual( assert.strictEqual(
[...target.querySelectorAll(".o_cp_bottom_left .dropdown-item")] [...target.querySelectorAll(".o_pivot_buttons .dropdown-item")]
.map((i) => i.innerText) .map((i) => i.innerText)
.join(""), .join(""),
"bouhFoomoddZipCount" "bouhFoomoddZipCount"
@@ -3479,12 +3471,11 @@ QUnit.module("Views", (hooks) => {
}); });
// with no data // with no data
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
assert.containsOnce(target, "p.o_view_nocontent_empty_folder"); assert.containsOnce(target, "p.o_view_nocontent_empty_folder");
await toggleFilterMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "December"); await toggleMenuItemOption(target, "Date", "December");
await toggleMenuItemOption(target, "Date", "2016"); await toggleMenuItemOption(target, "Date", "2016");
@@ -3530,10 +3521,10 @@ QUnit.module("Views", (hooks) => {
]; ];
assert.strictEqual(getCurrentValues(target), values.join()); assert.strictEqual(getCurrentValues(target), values.join());
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
await click(target.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[0]); await click(target.querySelectorAll(".o_pivot_buttons .dropdown-menu .dropdown-item")[0]);
await click(target.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[1]); await click(target.querySelectorAll(".o_pivot_buttons .dropdown-menu .dropdown-item")[1]);
values = ["2,0,-100%,0,2,100%,2,2,0%,2,0,-100%,0,1,100%,2,1,-50%,0,1,100%,0,1,100%"]; values = ["2,0,-100%,0,2,100%,2,2,0%,2,0,-100%,0,1,100%,2,1,-50%,0,1,100%,0,1,100%"];
assert.strictEqual(getCurrentValues(target), values.join()); assert.strictEqual(getCurrentValues(target), values.join());
@@ -3541,7 +3532,7 @@ QUnit.module("Views", (hooks) => {
values = ["2", "2", "0%", "2", "1", "-50%", "0", "1", "100%"]; values = ["2", "2", "0%", "2", "1", "-50%", "0", "1", "100%"];
assert.strictEqual(getCurrentValues(target), values.join()); assert.strictEqual(getCurrentValues(target), values.join());
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav"); await editFavoriteName(target, "Fav");
await saveFavorite(target); await saveFavorite(target);
@@ -3596,7 +3587,7 @@ QUnit.module("Views", (hooks) => {
}); });
// open comparison menu // open comparison menu
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
// compare October 2016 to September 2016 // compare October 2016 to September 2016
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
@@ -3604,17 +3595,16 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "p.o_view_nocontent_empty_folder", "there should be no data"); assert.containsOnce(target, "p.o_view_nocontent_empty_folder", "there should be no data");
// export data should be impossible since the pivot buttons // export data should be impossible since the pivot buttons
// are deactivated (exception: the 'Measures' button). // are deactivated (exception: the 'Measures' button).
assert.ok(target.querySelector(".o_control_panel button.o_pivot_download").disabled); assert.ok(target.querySelector(".o_pivot_buttons button.o_pivot_download").disabled);
await toggleFilterMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "December"); await toggleMenuItemOption(target, "Date", "December");
await toggleMenuItemOption(target, "Date", "October"); await toggleMenuItemOption(target, "Date", "October");
assert.notOk(target.querySelector(".o_control_panel button.o_pivot_download").disabled); assert.notOk(target.querySelector(".o_pivot_buttons button.o_pivot_download").disabled);
// With the data above, the time ranges contain some records. // With the data above, the time ranges contain some records.
// export data. Should execute 'get_file' // export data. Should execute 'get_file'
await click(target.querySelector(".o_control_panel button.o_pivot_download")); await click(target.querySelector(".o_pivot_buttons button.o_pivot_download"));
assert.verifySteps([ assert.verifySteps([
// col group headers // col group headers
@@ -3673,7 +3663,7 @@ QUnit.module("Views", (hooks) => {
mockMock = true; mockMock = true;
// compare December 2016 to November 2016 // compare December 2016 to November 2016
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
const values = ["0", "4", "100%", "0", "2", "100%", "0", "2", "100%"]; const values = ["0", "4", "100%", "0", "2", "100%", "0", "2", "100%"];
@@ -3715,7 +3705,7 @@ QUnit.module("Views", (hooks) => {
}); });
// compare December 2016 to November 2016 // compare December 2016 to November 2016
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
// initial sanity check // initial sanity check
@@ -3968,21 +3958,21 @@ QUnit.module("Views", (hooks) => {
arch: `<pivot><field name="foo" type="measure"/></pivot>`, arch: `<pivot><field name="foo" type="measure"/></pivot>`,
}); });
assert.containsNone(target, ".o_cp_bottom_left .dropdown-menu"); assert.containsNone(target, ".o_pivot_buttons .dropdown-menu");
// open the "Measures" menu // open the "Measures" menu
await click(target.querySelector(".o_cp_bottom_left .dropdown-toggle")); await click(target.querySelector(".o_pivot_buttons .dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu");
// click on the divider in the "Measures" menu does not crash // click on the divider in the "Measures" menu does not crash
await click(target.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-divider")); await click(target.querySelector(".o_pivot_buttons .dropdown-menu .dropdown-divider"));
// the menu should still be open // the menu should still be open
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu");
// click on the measure list but not on a menu item or the separator // click on the measure list but not on a menu item or the separator
await click(target.querySelector(".o_cp_bottom_left .dropdown-menu")); await click(target.querySelector(".o_pivot_buttons .dropdown-menu"));
// the menu should still be open // the menu should still be open
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu"); assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu");
}); });
QUnit.test( QUnit.test(
@@ -4038,7 +4028,7 @@ QUnit.module("Views", (hooks) => {
views: [[false, "pivot"]], views: [[false, "pivot"]],
}); });
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0); await toggleMenuItem(target, 0);
await nextTick(); await nextTick();
@@ -4090,7 +4080,7 @@ QUnit.module("Views", (hooks) => {
}); });
// compare December 2016 to November 2016 // compare December 2016 to November 2016
await toggleComparisonMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
// initial sanity check // initial sanity check
@@ -4237,12 +4227,11 @@ QUnit.module("Views", (hooks) => {
); );
// Filter on December 2016 // Filter on December 2016
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "December"); await toggleMenuItemOption(target, "Date", "December");
// compare December 2016 to November 2016 // compare December 2016 to November 2016
await toggleComparisonMenu(target);
await toggleMenuItem(target, "Date: Previous period"); await toggleMenuItem(target, "Date: Previous period");
assert.deepEqual( assert.deepEqual(
@@ -4384,7 +4373,7 @@ QUnit.module("Views", (hooks) => {
); );
// open group by menu and add new groupby // open group by menu and add new groupby
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
await applyGroup(target); await applyGroup(target);
@@ -4415,7 +4404,7 @@ QUnit.module("Views", (hooks) => {
); );
// open groupby menu generator and add a new groupby // open groupby menu generator and add a new groupby
await toggleGroupByMenu(target); await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target); await toggleAddCustomGroup(target);
await selectGroup(target, "bar"); await selectGroup(target, "bar");
await applyGroup(target); await applyGroup(target);
@@ -4648,7 +4637,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent .abc"); assert.containsNone(target, ".o_view_nocontent .abc");
assert.containsOnce(target, "table"); assert.containsOnce(target, "table");
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Small Than 0"); await toggleMenuItem(target, "Small Than 0");
assert.doesNotHaveClass(target, "o_view_sample_data"); assert.doesNotHaveClass(target, "o_view_sample_data");
@@ -4911,7 +4900,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), values.join(",")); assert.strictEqual(getCurrentValues(target), values.join(","));
@@ -4951,7 +4940,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(",")); assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -4992,7 +4981,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(",")); assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5033,7 +5022,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(",")); assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5079,7 +5068,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "12", "20"].join(",")); assert.strictEqual(getCurrentValues(target), ["32", "12", "12", "20"].join(","));
@@ -5122,7 +5111,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed) // Set a domain (this reload is delayed)
def = makeDeferred(); def = makeDeferred();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter"); await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(",")); assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5215,13 +5204,13 @@ QUnit.module("Views", (hooks) => {
// "Count" is the only measure available // "Count" is the only measure available
assert.deepEqual( assert.deepEqual(
[...target.querySelectorAll(".o_cp_bottom_left .dropdown-menu .o_menu_item")].map( [...target.querySelectorAll(".o_pivot_buttons .dropdown-menu .o_menu_item")].map(
(e) => e.innerText (e) => e.innerText
), ),
["Count"] ["Count"]
); );
// No separator should be displayed in the menu "Measures" // No separator should be displayed in the menu "Measures"
assert.containsNone(target, ".o_cp_bottom_left .dropdown-menu div.dropdown-divider"); assert.containsNone(target, ".o_pivot_buttons .dropdown-menu div.dropdown-divider");
}); });
QUnit.test( QUnit.test(
@@ -5257,11 +5246,10 @@ QUnit.module("Views", (hooks) => {
}); });
// compare 2021 to 2020 // compare 2021 to 2020
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date"); await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "2021"); await toggleMenuItemOption(target, "Date", "2021");
await toggleComparisonMenu(target); await toggleMenuItem(target.querySelector(".o_comparison_menu"), 0);
await toggleMenuItem(target, 0);
assert.deepEqual( assert.deepEqual(
[...target.querySelectorAll("th")].slice(0, 6).map((el) => el.innerText), [...target.querySelectorAll("th")].slice(0, 6).map((el) => el.innerText),
@@ -5333,7 +5321,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected" "The row headers should be as expected"
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite"); await editFavoriteName(target, "Favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -5352,7 +5340,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected" "The row headers should be as expected"
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite"); await toggleMenuItem(target, "Favorite");
assert.deepEqual( assert.deepEqual(
@@ -5361,7 +5349,6 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected" "The row headers should be as expected"
); );
await toggleGroupByMenu(target);
await toggleMenuItem(target, "Customer"); await toggleMenuItem(target, "Customer");
assert.deepEqual( assert.deepEqual(
@@ -5380,7 +5367,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected" "The row headers should be as expected"
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite 2"); await editFavoriteName(target, "Favorite 2");
await saveFavorite(target); await saveFavorite(target);
@@ -5429,7 +5416,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected" "The row headers should be as expected"
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite"); await toggleMenuItem(target, "Favorite");
assert.deepEqual( assert.deepEqual(
@@ -5492,7 +5479,7 @@ QUnit.module("Views", (hooks) => {
["Total", "", "No", "Yes", "Computed and not stored"] ["Total", "", "No", "Yes", "Computed and not stored"]
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My favorite 2"); await toggleMenuItem(target, "My favorite 2");
assert.deepEqual( assert.deepEqual(
@@ -5554,7 +5541,7 @@ QUnit.module("Views", (hooks) => {
["Total", "Computed and not stored"] ["Total", "Computed and not stored"]
); );
await toggleFavoriteMenu(target); await toggleSearchBarMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite"); await editFavoriteName(target, "Favorite");
await saveFavorite(target); await saveFavorite(target);
@@ -19,6 +19,11 @@ import { makeFakeUserService } from "../../helpers/mock_services";
const serviceRegistry = registry.category("services"); const serviceRegistry = registry.category("services");
async function exportAllAction(target) {
await click(target, ".o_cp_action_menus .dropdown-toggle");
await click(target, ".o_cp_action_menus .dropdown-item");
}
QUnit.module("ViewDialogs", (hooks) => { QUnit.module("ViewDialogs", (hooks) => {
let serverData; let serverData;
let target; let target;
@@ -947,7 +952,7 @@ QUnit.module("ViewDialogs", (hooks) => {
domain: [["bar", "!=", "glou"]], domain: [["bar", "!=", "glou"]],
}); });
await click(target.querySelector(".o_list_export_xlsx")); await exportAllAction(target);
}); });
QUnit.test("Direct export grouped list ", async function (assert) { QUnit.test("Direct export grouped list ", async function (assert) {
@@ -999,7 +1004,7 @@ QUnit.module("ViewDialogs", (hooks) => {
domain: [["bar", "!=", "glou"]], domain: [["bar", "!=", "glou"]],
}); });
await click(target.querySelector(".o_list_export_xlsx")); await exportAllAction(target);
}); });
QUnit.test("Export dialog with duplicated fields", async function (assert) { QUnit.test("Export dialog with duplicated fields", async function (assert) {
@@ -19,8 +19,7 @@ import {
editFavoriteName, editFavoriteName,
removeFacet, removeFacet,
saveFavorite, saveFavorite,
toggleFavoriteMenu, toggleSearchBarMenu,
toggleFilterMenu,
toggleMenuItem, toggleMenuItem,
toggleSaveFavorite, toggleSaveFavorite,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
@@ -401,13 +400,12 @@ QUnit.module("ViewDialogs", (hooks) => {
assert.containsN(target, ".o_data_row", 3, "should contain 3 records"); assert.containsN(target, ".o_data_row", 3, "should contain 3 records");
// filter on bar // filter on bar
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bar"); await toggleMenuItem(target, "Bar");
assert.containsN(target, ".o_data_row", 2, "should contain 2 records"); assert.containsN(target, ".o_data_row", 2, "should contain 2 records");
// save filter // save filter
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target); await toggleSaveFavorite(target);
await editFavoriteName(target, "some name"); await editFavoriteName(target, "some name");
await saveFavorite(target); await saveFavorite(target);
@@ -430,7 +430,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target, ".my_owl_action"); await click(target, ".my_owl_action");
await doAction(webClient, 3); await doAction(webClient, 3);
assert.strictEqual( assert.strictEqual(
target.querySelector(".breadcrumb").textContent, target.querySelector(".o_breadcrumb").textContent,
"Favorite PoniesnewOwlTitlePartners" "Favorite PoniesnewOwlTitlePartners"
); );
}); });
@@ -3,14 +3,16 @@
import { import {
click, click,
getFixture, getFixture,
getNodesTextContent,
legacyExtraNextTick, legacyExtraNextTick,
makeDeferred, makeDeferred,
nextTick, nextTick,
} from "@web/../tests/helpers/utils"; } from "@web/../tests/helpers/utils";
import { ControlPanel } from "@web/search/control_panel/control_panel"; import { ControlPanel } from "@web/search/control_panel/control_panel";
import { SearchBar } from "@web/search/search_bar/search_bar";
import { import {
isItemSelected, isItemSelected,
toggleFilterMenu, toggleSearchBarMenu,
toggleMenuItem, toggleMenuItem,
switchView, switchView,
} from "@web/../tests/search/helpers"; } from "@web/../tests/search/helpers";
@@ -26,6 +28,10 @@ import {
import { Component, xml } from "@odoo/owl"; import { Component, xml } from "@odoo/owl";
const actionRegistry = registry.category("actions"); const actionRegistry = registry.category("actions");
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData; let serverData;
let target; let target;
@@ -109,12 +115,7 @@ QUnit.module("ActionManager", (hooks) => {
doAction(webClient, 4); doAction(webClient, 4);
def.resolve(); def.resolve();
await nextTick(); await nextTick();
await legacyExtraNextTick(); assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded"
);
}); });
QUnit.test("clicking quickly on breadcrumbs...", async function (assert) { QUnit.test("clicking quickly on breadcrumbs...", async function (assert) {
@@ -140,11 +141,7 @@ QUnit.module("ActionManager", (hooks) => {
// resolve the form view read // resolve the form view read
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded and visible"
);
}); });
QUnit.test( QUnit.test(
@@ -335,11 +332,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4"); 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.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
"/web/action/load", "/web/action/load",
@@ -370,11 +363,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4"); 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.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
"/web/action/load", "/web/action/load",
@@ -398,12 +387,12 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3); await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_view"); assert.containsOnce(target, ".o_list_view");
assert.containsN(target, ".o_list_view .o_data_row", 5); 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) // reload (the search_read RPC will be blocked)
def = makeDeferred(); def = makeDeferred();
await switchView(target, "list"); await switchView(target, "list");
assert.containsN(target, ".o_list_view .o_data_row", 5); 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 // open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell")); await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
@@ -468,10 +457,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_list_view"); assert.containsOnce(target, ".o_list_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.containsNone(target, ".o_form_view"); assert.containsNone(target, ".o_form_view");
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
@@ -505,10 +491,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_kanban_view"); assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.containsNone(target, ".o_list_view"); assert.containsNone(target, ".o_list_view");
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
@@ -540,10 +523,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_kanban_view"); assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.containsNone(target, ".o_list_view"); assert.containsNone(target, ".o_list_view");
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
@@ -575,10 +555,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_kanban_view"); assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.containsNone(target, ".o_list_view"); assert.containsNone(target, ".o_list_view");
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
@@ -616,18 +593,12 @@ QUnit.module("ActionManager", (hooks) => {
await click(row1.querySelector(".o_data_cell")); await click(row1.querySelector(".o_data_cell"));
await click(row2.querySelector(".o_data_cell")); await click(row2.querySelector(".o_data_cell"));
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
def.resolve(); def.resolve();
await nextTick(); await nextTick();
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
}); });
QUnit.test("local state, global state, and race conditions", async function (assert) { QUnit.test("local state, global state, and race conditions", async function (assert) {
@@ -659,15 +630,15 @@ QUnit.module("ActionManager", (hooks) => {
ToyController.template = xml` ToyController.template = xml`
<div class="o_toy_view"> <div class="o_toy_view">
<ControlPanel /> <ControlPanel />
<SearchBar />
</div>`; </div>`;
ToyController.components = { ControlPanel }; ToyController.components = { ControlPanel, SearchBar };
registry.category("views").add("toy", { registry.category("views").add("toy", {
type: "toy", type: "toy",
display_name: "Toy", display_name: "Toy",
icon: "fab fa-android", icon: "fab fa-android",
multiRecord: true, multiRecord: true,
searchMenuTypes: ["filter"],
Controller: ToyController, Controller: ToyController,
}); });
@@ -683,7 +654,7 @@ QUnit.module("ActionManager", (hooks) => {
], ],
}); });
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Foo"); await toggleMenuItem(target, "Foo");
assert.ok(isItemSelected(target, "Foo")); assert.ok(isItemSelected(target, "Foo"));
@@ -695,7 +666,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve(); def.resolve();
await nextTick(); await nextTick();
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
assert.ok(isItemSelected(target, "Foo")); assert.ok(isItemSelected(target, "Foo"));
// this test is not able to detect that getGlobalState is put on the right place: // 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 // currentController.action.globalState contains in any case the search state
@@ -33,7 +33,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC }); const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, "1"); await doAction(webClient, "1");
assert.containsOnce(target, ".o_kanban_view"); 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( assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent), [...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"] ["yop", "blip", "gnap", "plop", "zoup"]
@@ -46,7 +46,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.ok(e.cause instanceof TypeError); assert.ok(e.cause instanceof TypeError);
} }
assert.containsOnce(target, ".o_kanban_view"); 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( assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent), [...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"] ["yop", "blip", "gnap", "plop", "zoup"]
@@ -17,8 +17,9 @@ import {
nextTick, nextTick,
makeDeferred, makeDeferred,
editInput, editInput,
getNodesTextContent,
} from "../../helpers/utils"; } 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 { session } from "@web/session";
import { import {
createWebClient, createWebClient,
@@ -31,6 +32,10 @@ import { errorService } from "@web/core/errors/error_service";
import { Component, xml } from "@odoo/owl"; import { Component, xml } from "@odoo/owl";
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData; let serverData;
let target; let target;
@@ -233,13 +238,8 @@ QUnit.module("ActionManager", (hooks) => {
model: "partner", model: "partner",
}); });
await testUtils.nextTick(); await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]); assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
}); });
@@ -261,11 +261,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.nextTick(); await testUtils.nextTick();
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.containsNone(target, ".o_menu_brand"); assert.containsNone(target, ".o_menu_brand");
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]); assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
}); });
@@ -318,7 +314,7 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test( QUnit.test(
"lazy load multi record view if mono record one is requested", "lazy load multi record view if mono record one is requested",
async function (assert) { async function (assert) {
assert.expect(12); assert.expect(11);
const mockRPC = async function (route, args) { const mockRPC = async function (route, args) {
assert.step((args && args.method) || route); assert.step((args && args.method) || route);
}; };
@@ -332,15 +328,9 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsNone(target, ".o_list_view"); assert.containsNone(target, ".o_list_view");
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".o_control_panel .breadcrumb-item", 2); assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Second record",
"breadcrumbs should contain the display_name of the opened record"
);
// go back to List // go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a")); await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view"); assert.containsOnce(target, ".o_list_view");
assert.containsNone(target, ".o_form_view"); assert.containsNone(target, ".o_form_view");
assert.verifySteps([ assert.verifySteps([
@@ -354,48 +344,21 @@ QUnit.module("ActionManager", (hooks) => {
); );
QUnit.test("lazy load multi record view with previous action", async function (assert) { QUnit.test("lazy load multi record view with previous action", async function (assert) {
assert.expect(6);
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await doAction(webClient, 4); await doAction(webClient, 4);
assert.containsOnce( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
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"
);
await doAction(webClient, 3, { await doAction(webClient, 3, {
props: { resId: 2 }, props: { resId: 2 },
viewType: "form", viewType: "form",
}); });
assert.containsN( assert.deepEqual(getBreadCrumbTexts(target), [
target, "Partners Action 4",
".o_control_panel .breadcrumb li", "Partners",
3, "Second record",
"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"
);
// go back to List // go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:last")); await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:last"));
await legacyExtraNextTick(); assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4", "Partners"]);
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"
);
}); });
QUnit.test( QUnit.test(
@@ -421,7 +384,7 @@ QUnit.module("ActionManager", (hooks) => {
); );
QUnit.test("change the viewType of the current action", async function (assert) { QUnit.test("change the viewType of the current action", async function (assert) {
assert.expect(14); assert.expect(13);
const mockRPC = async function (route, args) { const mockRPC = async function (route, args) {
assert.step((args && args.method) || route); assert.step((args && args.method) || route);
}; };
@@ -447,17 +410,7 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsNone(target, ".o_kanban_view"); assert.containsNone(target, ".o_kanban_view");
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.containsN( assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
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"
);
// verify steps to ensure that the whole action hasn't been re-executed // 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 // (if it would have been, /web/action/load and get_views would appear
// several times) // several times)
@@ -472,7 +425,7 @@ QUnit.module("ActionManager", (hooks) => {
}); });
QUnit.test("change the id of the current action", async function (assert) { QUnit.test("change the id of the current action", async function (assert) {
assert.expect(12); assert.expect(11);
const mockRPC = async function (route, args) { const mockRPC = async function (route, args) {
assert.step((args && args.method) || route); 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 // execute action 3 and open the first record in a form view
await doAction(webClient, 3); await doAction(webClient, 3);
await testUtils.dom.click($(target).find(".o_list_view .o_data_cell:first")); await testUtils.dom.click($(target).find(".o_list_view .o_data_cell:first"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"should have opened the first record"
);
// switch to record 4 // switch to record 4
webClient.env.bus.trigger("test:hashchange", { webClient.env.bus.trigger("test:hashchange", {
action: 3, action: 3,
@@ -494,19 +442,8 @@ QUnit.module("ActionManager", (hooks) => {
view_type: "form", view_type: "form",
}); });
await testUtils.nextTick(); await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.containsN( assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
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"
);
// verify steps to ensure that the whole action hasn't been re-executed // 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 // (if it would have been, /web/action/load and get_views would appear
// twice) // twice)
@@ -699,20 +636,12 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC }); const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 4); await doAction(webClient, 4);
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view"); assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"breadcrumbs should display the display_name of the action"
);
await loadState(webClient, { await loadState(webClient, {
model: "partner", model: "partner",
view_type: "list", view_type: "list",
}); });
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"should still be in the same action"
);
assert.containsNone(target, ".o_kanban_view", "should no longer display a kanban view"); 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.containsOnce(target, ".o_list_view", "should display a list view");
assert.verifySteps([ assert.verifySteps([
@@ -742,11 +671,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC }); const webClient = await createWebClient({ serverData, mockRPC });
await loadState(webClient, { menu_id: 666 }); await loadState(webClient, { menu_id: 666 });
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view"); assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1",
"breadcrumbs should display the display_name of the action"
);
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
"/web/action/load", "/web/action/load",
@@ -762,21 +687,14 @@ QUnit.module("ActionManager", (hooks) => {
1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1 }, 1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1 },
}; };
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app) assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
await loadState(webClient, { action: 3 }); await loadState(webClient, { action: 3 });
assert.containsOnce(target, ".o_list_view"); // 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 }); await loadState(webClient, { home: 1 });
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app) assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
}); });
QUnit.test("load state supports #home as initial state", async function (assert) { 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 createWebClient({ serverData, mockRPC });
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view"); assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual( assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
"/web/action/load", "/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) { 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] = { serverData.actions[999] = {
id: 999, id: 999,
name: "Partner", name: "Partner",
@@ -823,11 +738,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC }); const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999, { viewType: "form", props: { resId: 2 } }); await doAction(webClient, 999, { viewType: "form", props: { resId: 2 } });
assert.containsOnce(target, ".o_form_view"); assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2); assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "Second record"]);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Second record"
);
assert.verifySteps([ assert.verifySteps([
"/web/webclient/load_menus", "/web/webclient/load_menus",
"/web/action/load", "/web/action/load",
@@ -841,11 +752,7 @@ QUnit.module("ActionManager", (hooks) => {
}); });
assert.verifySteps(["/web/dataset/call_kw/partner/onchange"]); assert.verifySteps(["/web/dataset/call_kw/partner/onchange"]);
assert.containsOnce(target, ".o_form_view .o_form_editable"); assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.containsN(target, ".breadcrumb-item", 2); assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "New"]);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"New"
);
}); });
QUnit.test("hashchange does not trigger canberemoved right away", async function (assert) { 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 click(target.querySelector(".o_control_panel .breadcrumb-item"));
await legacyExtraNextTick();
assert.containsN(target, ".o_list_view .o_data_row", 5); assert.containsN(target, ".o_list_view .o_data_row", 5);
await toggleFilterMenu(target); await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter"); await toggleMenuItem(target, "Filter");
assert.containsN(target, ".o_list_view .o_data_row", 1); assert.containsN(target, ".o_list_view .o_data_row", 1);
@@ -982,18 +888,18 @@ QUnit.module("ActionManager", (hooks) => {
}, },
{ props: { resIds: [1, 2] } } { props: { resIds: [1, 2] } }
); );
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "First record"); assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
await pagerNext(target); 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"); await editInput(target, "[name=display_name] input", "new name");
// without saving we now make a loadState which should commit changes // without saving we now make a loadState which should commit changes
await loadState(webClient, { action: 1337, id: 1, model: "partner", view_type: "form" }); 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 // loadState again just to check if changes were commited
await loadState(webClient, { action: 1337, id: 2, model: "partner", view_type: "form" }); 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) => { QUnit.test("initial action crashes", async (assert) => {
@@ -5,7 +5,6 @@ import { registry } from "@web/core/registry";
import { session } from "@web/session"; import { session } from "@web/session";
import AbstractAction from "web.AbstractAction"; import AbstractAction from "web.AbstractAction";
import core from "web.core"; import core from "web.core";
import testUtils from "web.test_utils";
import { makeTestEnv } from "../../helpers/mock_env"; import { makeTestEnv } from "../../helpers/mock_env";
import { import {
click, click,
@@ -207,10 +206,10 @@ QUnit.module("ActionManager", (hooks) => {
serverData.actions[4].context = { no_breadcrumbs: true }; serverData.actions[4].context = { no_breadcrumbs: true };
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await doAction(webClient, 3); 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' // push another action flagged with 'no_breadcrumbs=true'
await doAction(webClient, 4); 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) { 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 }); const webClient = await createWebClient({ serverData });
await doAction(webClient, "ClientAction"); await doAction(webClient, "ClientAction");
assert.containsOnce(target, ".my_button"); assert.containsOnce(target, ".my_button");
await testUtils.dom.click(target.querySelector(".my_button")); await click(target.querySelector(".my_button"));
await legacyExtraNextTick(); await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view"); 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(); await legacyExtraNextTick();
assert.containsOnce(target, ".my_button"); assert.containsOnce(target, ".my_button");
assert.verifySteps(["on_reverse_breadcrumb"]); assert.verifySteps(["on_reverse_breadcrumb"]);
@@ -284,7 +283,7 @@ QUnit.module("ActionManager", (hooks) => {
); );
QUnit.test('handles "history_back" event', async function (assert) { QUnit.test('handles "history_back" event', async function (assert) {
assert.expect(3); assert.expect(4);
let list; let list;
patchWithCleanup(listView.Controller.prototype, { patchWithCleanup(listView.Controller.prototype, {
setup() { setup() {
@@ -295,13 +294,13 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData }); const webClient = await createWebClient({ serverData });
await doAction(webClient, 4); await doAction(webClient, 4);
await doAction(webClient, 3); 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(); list.env.config.historyBack();
await testUtils.nextTick(); await nextTick();
await legacyExtraNextTick(); assert.containsOnce(target, ".o_breadcrumb span");
assert.containsOnce(target, ".o_control_panel .breadcrumb-item");
assert.strictEqual( assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(), target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partners Action 4", "Partners Action 4",
"breadcrumbs should display the display_name of the action" "breadcrumbs should display the display_name of the action"
); );

Some files were not shown because too many files have changed in this diff Show More