[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',
}, {
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',
content: 'Primary color is correct',
@@ -341,10 +341,11 @@ QUnit.module("Base Import Tests", (hooks) => {
"button has the right download url"
);
assert.verifySteps(["partner/get_import_templates", "base_import.import/create"]);
// Contains invisible mobile buttons
assert.containsN(
target,
".o_control_panel button",
2,
5,
"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
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([
"partner/get_import_templates",
"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
const file = new File(["fake_file"], "fake_file.xls", { type: "text/plain" });
await editInput(target, "input[type='file']", file);
await click(target.querySelector(".o_control_panel button:first-child"));
await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:first-child")
);
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
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(
target,
".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
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();
assert.containsOnce(
@@ -604,7 +607,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
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(
target.querySelector(".o_import_data_sidepanel input[type=checkbox]").checked,
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"
);
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(
target,
".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 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([
"base_import.import/execute_import",
"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
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
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(
target.querySelector(".o_import_data_content .alert-danger").textContent,
"The file contains blocking errors (see below)",
@@ -730,7 +743,9 @@ QUnit.module("Base Import Tests", (hooks) => {
"prevent option is selected by default"
);
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(
target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.",
@@ -774,10 +789,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
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
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(
target.querySelector(".o_import_data_content .alert-danger").textContent,
"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'"
);
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(
target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.",
@@ -837,10 +856,12 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
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
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(
target.querySelector(".o_import_data_content .alert-danger").textContent,
"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'"
);
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(
target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.",
"import is now successful"
);
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(
target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.",
@@ -914,8 +939,10 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
const file = new File(["fake_file"], "fake_file.xlsx", { type: "text/plain" });
await editInput(target, "input[type='file']", file);
await click(target.querySelector(".o_control_panel button:nth-child(1)"));
await editInput(target, ".o_control_panel_main_buttons .d-none input[type='file']", file);
await click(
target.querySelector(".o_control_panel_main_buttons .d-none button:nth-child(1)")
);
assert.strictEqual(
target.querySelector(".o_import_data_content .alert-danger").textContent,
"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
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(
target.querySelector("input#o_import_batch_limit").value,
"2000",
@@ -1004,7 +1031,9 @@ QUnit.module("Base Import Tests", (hooks) => {
);
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(
target.querySelector(".o_import_data_content .alert-info").textContent,
"Everything seems valid.",
@@ -1068,9 +1097,11 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
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 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
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"
);
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",
"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
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 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
await nextTick();
await nextTick();
@@ -1169,7 +1203,8 @@ QUnit.module("Base Import Tests", (hooks) => {
"Everything seems valid."
);
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",
"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
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(
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."
);
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
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
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(
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
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");
// Parse the file again with the updated date format to check that
// the format is correctly formatted in the UI
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.strictEqual(
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
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");
assert.containsN(
target,
@@ -1444,7 +1491,7 @@ QUnit.module("Base Import Tests", (hooks) => {
// Set and trigger the change of a file for the input
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(
target.querySelector(".o_import_date_format").list.id,
"list-3",
@@ -5,10 +5,9 @@ import { importRecordsItem } from "@base_import/import_records/import_records";
import { registry } from "@web/core/registry";
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";
const favoriteMenuRegistry = registry.category("favoriteMenu");
import { clearRegistryWithCleanup } from "@web/../tests/helpers/mock_env";
let serverData;
let target;
@@ -27,12 +26,14 @@ QUnit.module("Base Import Tests", (hooks) => {
},
};
setupViewRegistries();
favoriteMenuRegistry.add("import-menu", importRecordsItem);
const cogMenuRegistry = registry.category("cogMenu");
clearRegistryWithCleanup(cogMenuRegistry);
cogMenuRegistry.add("import-menu", importRecordsItem);
});
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);
const actionService = {
@@ -56,14 +57,14 @@ QUnit.module("Base Import Tests", (hooks) => {
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
await toggleActionMenu(target);
assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsOnce(target, ".o_import_menu");
await click(target.querySelector(".o_import_menu"));
});
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) {
await makeView({
type: "list",
@@ -75,14 +76,14 @@ QUnit.module("Base Import Tests", (hooks) => {
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
await toggleActionMenu(target);
assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
}
);
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) {
await makeView({
type: "list",
@@ -94,13 +95,13 @@ QUnit.module("Base Import Tests", (hooks) => {
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
await toggleActionMenu(target);
assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--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);
const actionService = {
@@ -131,14 +132,14 @@ QUnit.module("Base Import Tests", (hooks) => {
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
await toggleActionMenu(target);
assert.containsOnce(target, ".o_cp_action_menus .o-dropdown--menu");
assert.containsOnce(target, ".o_import_menu");
await click(target.querySelector(".o_import_menu"));
});
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) {
await makeView({
type: "kanban",
@@ -156,15 +157,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window",
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
// Cog menu will not show when empty
assert.containsNone(target, ".o_cp_action_menus");
}
);
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) {
await makeView({
type: "kanban",
@@ -182,15 +181,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window",
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
// Cog menu will not show when empty
assert.containsNone(target, ".o_cp_action_menus");
}
);
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) {
serverData.models.foo.fields.foobar = {
string: "Fubar",
@@ -207,15 +204,13 @@ QUnit.module("Base Import Tests", (hooks) => {
actionType: "ir.actions.act_window",
},
});
await toggleFavoriteMenu(target);
assert.containsOnce(target, ".o_favorite_menu .o-dropdown--menu");
assert.containsNone(target, ".o_import_menu");
// Cog menu will not show when empty
assert.containsNone(target, ".o_cp_action_menus");
}
);
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) {
serverData.models.bar = {
fields: {
@@ -244,8 +239,8 @@ QUnit.module("Base Import Tests", (hooks) => {
await selectDropdownItem(target, "m2o", "Search More...");
const dialog = target.querySelector(".modal");
await toggleFavoriteMenu(dialog);
assert.containsOnce(dialog, ".o_favorite_menu .o-dropdown--menu");
await toggleActionMenu(dialog);
assert.containsOnce(dialog, ".o_cp_action_menus .o-dropdown--menu");
assert.containsNone(dialog, ".o_import_menu");
}
);
@@ -12,10 +12,7 @@ import {
applyGroup,
removeFacet,
toggleAddCustomGroup,
toggleComparisonMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleSearchBarMenu,
toggleMenuItem,
toggleMenuItemOption,
} from "@web/../tests/search/helpers";
@@ -142,13 +139,11 @@ QUnit.module("Board", (hooks) => {
await click(document.querySelector(".o_column_sortable"));
// Group It
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
await applyGroup(target);
// add this action to dashboard
await toggleFavoriteMenu(target);
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.dom.click($(".o_add_to_board .dropdown-menu button"));
@@ -202,11 +197,10 @@ QUnit.module("Board", (hooks) => {
var filter_count = 0;
// Add a first filter
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter on a");
// Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter");
await testUtils.dom.click($(".o_add_to_board .dropdown-menu button"));
@@ -214,11 +208,10 @@ QUnit.module("Board", (hooks) => {
await removeFacet(target);
// Add the second filter
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter on b");
// Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent(
target.querySelector(".o_add_to_board button.dropdown-toggle"),
"mouseenter"
@@ -263,11 +256,10 @@ QUnit.module("Board", (hooks) => {
});
// Add a filter
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter");
// Add it to dashboard
await toggleFavoriteMenu(target);
await testUtils.dom.triggerEvent(
target.querySelector(".o_add_to_board button.dropdown-toggle"),
"mouseenter"
@@ -292,7 +284,7 @@ QUnit.module("Board", (hooks) => {
type: "ir.actions.act_window",
views: [[false, "pivot"]],
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
assert.containsNone(target, ".o_add_to_board");
// Sanity check
@@ -302,7 +294,7 @@ QUnit.module("Board", (hooks) => {
type: "ir.actions.act_window",
views: [[false, "pivot"]],
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
assert.containsOnce(target, ".o_add_to_board");
});
@@ -357,16 +349,14 @@ QUnit.module("Board", (hooks) => {
});
// filter on July 2020
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "July");
// compare July 2020 to June 2020
await toggleComparisonMenu(target);
await toggleMenuItem(target, 0);
await toggleMenuItem(target.querySelector(".o_comparison_menu"), 0);
// add the view to the dashboard
await toggleFavoriteMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input");
@@ -403,7 +393,7 @@ QUnit.module("Board", (hooks) => {
views: [[false, "pivot"]],
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input");
await testUtils.fields.editInput(input, "Pipeline");
@@ -445,7 +435,7 @@ QUnit.module("Board", (hooks) => {
context: { search_default_filter: 1 },
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await mouseEnter(target.querySelector(".o_add_to_board .dropdown-toggle"));
const input = target.querySelector(".o_add_to_board .dropdown-menu input");
await testUtils.fields.editInput(input, "Pipeline");
+4 -1
View File
@@ -131,7 +131,10 @@ QUnit.module("Board", (hooks) => {
return Promise.resolve(true);
}
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 { menuService } from "@web/webclient/menus/menu_service";
import {
toggleFilterMenu,
toggleGroupByMenu,
toggleSearchBarMenu,
toggleMenuItem,
toggleMenuItemOption,
} 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, "Date Field");
@@ -123,7 +122,6 @@ QUnit.module("Views", (hooks) => {
await toggleMenuItemOption(target, "Date Field", "Year");
await toggleFilterMenu(target);
await toggleMenuItem(target, "Forecast Filter");
unpatchDate();
@@ -98,7 +98,7 @@ QUnit.module('Google Calendar', {
}, function () {
QUnit.test('sync google calendar', async function (assert) {
assert.expect(11);
assert.expect(13);
let id = 7;
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
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('.o_calendar_button_prev'));
await click(target.querySelector('.ui-datepicker-next'));
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([
'/google_calendar/sync_data',
@@ -148,8 +151,10 @@ QUnit.module('Google Calendar', {
'/web/dataset/call_kw/calendar.event/search_read',
'/google_calendar/sync_data',
'/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');
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(
document.body,
".o_field_many2many_avatar_employee .badge",
".o_field_many2many_avatar_employee .o_tag",
2,
"should have 2 records"
);
assert.strictEqual(
document
.querySelector(".o_field_many2many_avatar_employee .badge img")
.querySelector(".o_field_many2many_avatar_employee .o_tag img")
.getAttribute("data-src"),
`/web/image/hr.employee.public/${employeeId_1}/avatar_128`
);
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(
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([
`read m2x.avatar.employee ${avatarId_1}`,
@@ -413,19 +413,19 @@ QUnit.test(
res_id: avatarId,
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(
document
.querySelector(".o_field_many2many_avatar_employee .badge img")
.querySelector(".o_field_many2many_avatar_employee .o_tag img")
.getAttribute("data-src"),
`/web/image/hr.employee.public/${employeeId_1}/avatar_128`
);
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(
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([
`read m2x.avatar.employee ${employeeId_1}`,
@@ -82,10 +82,5 @@ registry.category("web_tour.tours").add('hr_holidays_tour', {
trigger: 'button[name="action_approve"]',
content: _t("Let's approve it"),
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: () => {},
},
...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,
hasParentReloadOnMessagePosted,
isAttachmentBoxVisibleInitially,
threadId: "__comp__.props.record.model.root.resId or undefined",
threadModel: "__comp__.props.record.model.root.resModel",
webRecord: "__comp__.props.record.model.root",
threadId: "__comp__.props.record.resId or undefined",
threadModel: "__comp__.props.record.resModel",
webRecord: "__comp__.props.record",
saveRecord: "() => __comp__.saveButtonClicked and __comp__.saveButtonClicked()",
});
const chatterContainerHookXml = createElement("div");
@@ -63,8 +63,8 @@ function compileAttachmentPreview(node, params) {
const webClientViewAttachmentViewContainerXml = createElement("t");
setAttributes(webClientViewAttachmentViewContainerXml, {
"t-component": "__comp__.mailComponents.AttachmentView",
threadId: "__comp__.props.record.model.root.resId or undefined",
threadModel: "__comp__.props.record.model.root.resModel",
threadId: "__comp__.props.record.resId or undefined",
threadModel: "__comp__.props.record.resModel",
});
append(webClientViewAttachmentViewContainerHookXml, webClientViewAttachmentViewContainerXml);
return webClientViewAttachmentViewContainerHookXml;
@@ -1994,6 +1994,6 @@ QUnit.test(
await click(".o-mail-NotificationItem:contains(General)");
await click(".o-mail-ChatWindow [title='Open in Discuss']");
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(
$("button:contains(Log note)"),
"btn-odoo",
"btn-primary",
"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) => {
@@ -54,5 +54,8 @@ QUnit.test("Manage Messages", async (assert) => {
await click(dropdownItems[0]);
await legacyExtraNextTick();
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"]],
});
assert.strictEqual(
$(".o_field_many2many_avatar_user.o_field_widget .badge img")[0].getAttribute(
"data-src"
),
document.body
.querySelector(".o_field_many2many_avatar_user.o_field_widget .o_avatar img")
.getAttribute("data-src"),
`/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,
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.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] }
);
assert.strictEqual($(".breadcrumb-item.active").text(), "Partner 1");
assert.strictEqual($(".o_breadcrumb .active").text(), "Partner 1");
assert.strictEqual($(".o_content")[0].scrollTop, 0);
$(".o_content")[0].scrollTop = 150;
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);
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
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")
@@ -38,7 +38,7 @@ registry.category("web_tour.tours").add('project_tour', {
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>.")),
position: 'bottom',
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",
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',
content: Markup(_t("Add columns to organize your tasks into <b>stages</b> <i>e.g. New - In Progress - Done</i>.")),
position: 'bottom',
@@ -2,7 +2,7 @@
import { browser } from "@web/core/browser/browser";
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 { registry } from "@web/core/registry";
import { makeFakeNotificationService, fakeCookieService } from "@web/../tests/helpers/mock_services";
@@ -133,7 +133,7 @@ QUnit.module("Project", {}, () => {
}
async function openGroupByMainMenu(target) {
await toggleGroupByMenu(target);
await toggleSearchBarMenu(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) {
const stepsTriggeringNotification = async () => {
const removeFilterXpath = `//div[contains(@class, 'o_searchview_facet')]
[.//span[@class='o_facet_value']
[contains(., 'Date: Month')]]
/i[contains(@class, 'o_facet_remove')]`;
const removeFilterElement = getFirstElementForXpath(target, removeFilterXpath);
await click(removeFilterElement);
// There's only one possibility here
await click(target, ".o_facet_remove");
};
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
});
@@ -216,7 +212,7 @@ QUnit.module("Project", {}, () => {
function checkGroupByOrder(assert) {
const dateSearchFacetXpath = `//div[contains(@class, 'o_searchview_facet')]
[.//span[@class='o_facet_value']
[.//small[@class='o_facet_value']
[contains(., 'Date: Month')]]`;
const dateSearchFacetElement = getFirstElementForXpath(target, dateSearchFacetXpath);
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")',
}, {
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',
}, {
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"',
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',
trigger: '.o_group_by_menu button',
content: 'Open the search panel menu',
trigger: '.o_control_panel .o_searchview_dropdown_toggler',
}, {
content: 'The Stage group menu item is invisible',
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"',
trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date") button.o_notification_close',
}, {
content: 'Open the filter menu',
trigger: '.o_filter_menu button',
content: 'Open the search panel menu',
trigger: '.o_control_panel .o_searchview_dropdown_toggler',
}, {
content: 'Open the Date filter sub menu',
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',
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',
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)',
content: 'Go back to the kanban view',
}, {
trigger: 'iframe .o_filter_menu > button',
content: 'click on filter menu in the search view',
trigger: 'iframe .o_searchview_dropdown_toggler',
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',
}, {
trigger: 'iframe .o_group_by_menu > button',
content: 'click on group by menu in the search view',
}, {
trigger: 'iframe .o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
trigger: 'iframe .o_group_by_menu .dropdown-item:first-child',
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',
content: 'click to "save current search" button in favorite menu',
}, {
trigger: 'iframe .o_filter_menu > button',
content: 'click on filter menu in the search view',
}, {
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',
}, {
trigger: 'iframe .o_group_by_menu > button',
content: 'click on group by menu in the search view',
}, {
trigger: 'iframe .o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
trigger: 'iframe .o_group_by_menu .dropdown-item:first-child',
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',
content: 'click to "save current search" button in favorite menu',
@@ -14,8 +14,8 @@ PurchaseAdditionalTourSteps.include({
_get_purchase_stock_steps: function () {
this._super.apply(this, arguments);
return [{
trigger: ".oe_button_box button[name='action_view_picking']",
extra_trigger: ".oe_button_box button[name='action_view_picking']",
trigger: ".o-form-buttonbox button[name='action_view_picking']",
extra_trigger: ".o-form-buttonbox button[name='action_view_picking']",
content: _t("Receive the ordered products."),
position: "bottom",
run: 'click',
@@ -185,7 +185,7 @@ registry.category("web_tour.tours").add('sale_timesheet_tour', {
content: 'Set Project name',
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',
}, {
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,
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',
isCheck: true,
}, {
@@ -174,7 +174,7 @@ QUnit.test(
const serverData = getServerData(spreadsheetData);
const fixture = getFixture();
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;
assert.equal(year.value, String(this_year));
const input = fixture.querySelector("input.o_datetime_input");
@@ -183,10 +183,10 @@ QUnit.test(
await nextTick();
assert.equal(year.value, String(this_year - 1));
assert.containsOnce(fixture, ".o_cp_top_right .fa-times");
await click(fixture.querySelector(".o_cp_top_right .fa-times"));
assert.containsOnce(fixture, ".o_control_panel_actions .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...");
}
);
@@ -88,10 +88,10 @@ QUnit.module(
assert.containsN(target, '.o_data_row', 3, "should have 3 records");
// 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=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
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...
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=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...
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 editInput(target, "[name=name] input", name);
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...
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 editInput(target, "[name=name] input", name);
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...
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=age] input", age);
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...
assert.containsN(target, '.o_data_row', 3, "should have 3 records");
@@ -7,7 +7,7 @@
steps: [
{
trigger: '.o_kanban_record',
extra_trigger:'.breadcrumb',
extra_trigger: '.o_breadcrumb',
},
{
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
}, {
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",
trigger: ".o-kanban-button-new",
@@ -14,6 +14,7 @@ import {
} from "@web/../tests/helpers/utils";
import { doAction } from "@web/../tests/webclient/helpers";
import { session } from "@web/session";
import { toggleSearchBarMenu } from "@web/../tests/search/helpers";
let serverData;
let pyEnv;
@@ -511,19 +512,19 @@ QUnit.module("test_mail", {}, function () {
const { webClient } = await start({ serverData, mockRPC });
await doAction(webClient, 1);
await toggleSearchBarMenu(document);
assert.containsN(
document.body,
".o_search_options .dropdown button:visible",
".o_cp_searchview .o_dropdown_container",
2,
"only two elements should be available in view search"
);
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"
);
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"
);
});
@@ -15,7 +15,7 @@ QUnit.test(
const o_view_controller = document.querySelector(".o_view_controller");
const o_content = o_view_controller.querySelector(".o_content");
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 o_header_cell = o_content.querySelector(".o_activity_type_cell");
@@ -34,7 +34,8 @@ export class Popover extends Component {
}
// reset all arrow classes
const arrowEl = el.getElementsByClassName('popover-arrow')[0];
const arrowEl = el.querySelector(".popover-arrow");
arrowEl.className = "popover-arrow";
switch (position) {
case "tm": // top-middle
case "bm": // bottom-middle
@@ -23,7 +23,7 @@ export class CogMenu extends Component {
static template = "web.CogMenu";
static components = {
Dropdown,
}
};
static props = {
slots: { type: Object, optional: true },
};
@@ -75,14 +75,18 @@ export class ControlPanel extends Component {
useEffect(() => {
// 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) {
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"));
this.mainButtons.el
.querySelectorAll(".o_control_panel_collapsed_create.btn-group")
.forEach((el) => el.classList.remove("btn-group"));
.querySelectorAll(".o_control_panel_collapsed_create.btn-group")
.forEach((el) => el.classList.remove("btn-group"));
return;
}
for (const button of dropdownButtons) {
@@ -190,7 +194,7 @@ export class ControlPanel extends Component {
/**
* @param {KeyboardEvent} ev
*/
onBottomLeftKeydown(ev) {
onMainButtonsKeydown(ev) {
const hotkey = getActiveHotkey(ev);
if (hotkey === "arrowdown") {
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_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_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">
<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">
@@ -79,7 +79,7 @@
<t t-set="collapsedBreadcrumbs" t-value="breadcrumbs.slice(0, -3).reverse()"/>
<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-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)">
@@ -101,22 +101,22 @@
</Dropdown>
</li>
<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>
</li>
</t>
</ol>
</t>
<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"/>
</div>
<t t-call="web.Breadcrumb.Actions"/>
</div>
</div>
<div t-else="" class="d-flex gap-1">
<div class="active d-flex fs-4 min-w-0 align-items-center">
<div t-else="" class="o_breadcrumb d-flex gap-1">
<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"/>
</div>
<t t-call="web.Breadcrumb.Actions"/>
@@ -97,7 +97,7 @@
</div>
<SearchBarMenu/>
</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">
<i class="fa fa-fw fa-search"/>
</button>
@@ -1,9 +1,8 @@
/** @odoo-module **/
import { AdvancedSearchDialog } from "@web/search/filter_menu/advanced_search_dialog";
import { Component } from "@odoo/owl";
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 { DropdownItem } from "@web/core/dropdown/dropdown_item";
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 { SearchDropdownItem } from "@web/search/search_dropdown_item/search_dropdown_item";
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");
@@ -29,7 +30,7 @@ export class SearchBarMenu extends Component {
this.facet_icons = FACET_ICONS;
// Filter
this.dialogService = useService("dialog");
this.notification = useService("notification");
this.getDefaultLeafDomain = useGetDefaultLeafDomain();
// GroupBy
const fields = [];
for (const [fieldName, field] of Object.entries(this.env.searchModel.searchViewFields)) {
@@ -51,33 +52,23 @@ export class SearchBarMenu extends Component {
);
}
onAdvancedSearchClick() {
const domains = [this.env.searchModel._getDomain({ withGlobal: false })];
if (this.env.searchModel.comparison && !this.env.searchModel.globalComparison) {
const { range } = this.env.searchModel.getFullComparison();
domains.push(range);
}
const domain = Domain.and(domains).toString();
this.dialogService.add(AdvancedSearchDialog, {
async onAddCustomFilterClick() {
const { domainEvalContext: context, resModel } = this.env.searchModel;
const domain = await this.getDefaultLeafDomain(resModel);
this.dialogService.add(DomainSelectorDialog, {
resModel,
defaultConnector: "|",
domain,
onConfirm: (domain) => this.onConfirm(domain),
resModel: this.env.searchModel.resModel,
context,
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,
});
}
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 {number} param0.itemId
@@ -54,7 +54,7 @@
<t t-if="filterItems.length">
<div role="separator" class="dropdown-divider"/>
</t>
<DropdownItem onSelected.bind="onAdvancedSearchClick">Advanced Search</DropdownItem>
<DropdownItem onSelected.bind="onAddCustomFilterClick">Add Custom Filter</DropdownItem>
</div>
</t>
<!-- GroupBy -->
@@ -65,6 +65,7 @@ export class CalendarController extends Component {
createRecord: this.createRecord.bind(this),
deleteRecord: this.deleteRecord.bind(this),
editRecord: this.editRecord.bind(this),
setDate: this.setDate.bind(this),
displayName: this.displayName,
};
}
@@ -62,4 +62,7 @@
padding-bottom: 0.25rem;
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">
<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>
</t>
@@ -170,10 +170,7 @@ export class FormCompiler extends ViewCompiler {
}
compileButton(el, params) {
const compiled = super.compileButton(el, params);
compiled.setAttribute("disable", "__comp__.props.disableViewButtons");
compiled.setAttribute("enable", "__comp__.props.enableViewButtons");
return compiled;
return super.compileButton(el, params);
}
/**
@@ -648,9 +645,12 @@ export class FormCompiler extends ViewCompiler {
append(sheetBG, sheetFG);
for (const child of el.childNodes) {
const compiled = this.compileNode(child, params);
if (!compiled || compiled.nodeName === "ButtonBox") {
if (!compiled) {
continue;
}
if (compiled.nodeName === "ButtonBox") {
compiled.setAttribute("t-if", "__comp__.env.inDialog");
}
if (getTag(child, true) === "field") {
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 { 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 { FormCompiler } from "./form_compiler";
import { evalDomain } from "../utils";
@@ -108,9 +108,6 @@ export class FormController extends Component {
this.user = useService("user");
this.viewService = useService("view");
this.ui = useService("ui");
this.state = useState({
isDisabled: false,
});
useBus(this.ui.bus, "resize", this.render);
this.archInfo = this.props.archInfo;
@@ -120,6 +117,8 @@ export class FormController extends Component {
this.canCreate = create && !this.props.preventCreate;
this.canEdit = edit && !this.props.preventEdit;
this.disabledButtons = null;
let mode = this.props.mode || "edit";
if (!this.canEdit) {
mode = "readonly";
@@ -198,8 +197,8 @@ export class FormController extends Component {
this.buttonBoxTemplate = buttonBoxTemplates.ButtonBox;
}
const rootRef = useRef("root");
useViewButtons(this.model, rootRef, {
this.rootRef = useRef("root");
useViewButtons(this.model, this.rootRef, {
beforeExecuteAction: this.beforeExecuteActionButton.bind(this),
afterExecuteAction: this.afterExecuteActionButton.bind(this),
});
@@ -213,7 +212,7 @@ export class FormController extends Component {
};
useSetupView({
rootRef,
rootRef: this.rootRef,
beforeLeave: () => this.beforeLeave(),
beforeUnload: (ev) => this.beforeUnload(ev),
getLocalState: () => {
@@ -248,9 +247,11 @@ export class FormController extends Component {
(isInEdition) => {
if (
!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"
);
if (elementToFocus) {
@@ -398,11 +399,18 @@ export class FormController extends Component {
}
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() {
this.state.isDisabled = false;
for (const btn of this.disabledButtons) {
btn.removeAttribute("disabled");
}
this.disabledButtons = null;
}
async beforeExecuteActionButton(clickParams) {
@@ -7,14 +7,14 @@
<Layout className="model.useSampleModel ? 'o_view_sample_data' : ''" display="display">
<t t-set-slot="control-panel-create-button">
<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-set-slot="layout-buttons">
<t t-if="env.inDialog">
<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-else="">
<t t-call="{{ props.buttonTemplate }}"/>
@@ -47,15 +47,15 @@
<t t-set-slot="control-panel-status-indicator">
<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-set-slot="control-panel-create-button">
<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-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>
</div>
</div>
@@ -114,8 +114,6 @@ FormRenderer.props = {
// Template props : added by the FormCompiler
class: { type: String, optional: 1 },
translateAlert: { type: [Object, { value: null }], optional: true },
enableViewButtons: { type: Function, optional: true },
disableViewButtons: { type: Function, optional: true },
onNotebookPageChange: { type: Function, optional: true },
activeNotebookPages: { type: Object, optional: true },
setFieldAsDirty: { type: Function, optional: true },
@@ -123,6 +121,4 @@ FormRenderer.props = {
FormRenderer.defaultProps = {
activeNotebookPages: {},
onNotebookPageChange: () => {},
enableViewButtons: () => {},
disableViewButtons: () => {},
};
@@ -1,6 +1,6 @@
/** @odoo-module **/
import { Component, useState } from "@odoo/owl";
import { Component, useEffect, useRef, useState } from "@odoo/owl";
import { useBus } from "@web/core/utils/hooks";
export class FormStatusIndicator extends Component {
@@ -13,6 +13,18 @@ export class FormStatusIndicator extends Component {
"FIELD_IS_DIRTY",
(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() {
@@ -43,5 +55,4 @@ FormStatusIndicator.props = {
model: Object,
save: Function,
discard: Function,
isDisabled: Boolean,
};
@@ -7,17 +7,16 @@
<button
type="button"
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"
t-on-click.stop="save"
data-tooltip="Save manually"
aria-label="Save manually">
aria-label="Save manually"
t-ref="save">
<i class="fa fa-cloud-upload fa-fw" />
</button>
<button
type="button"
class="o_form_button_cancel btn btn-light px-1 py-0 lh-sm"
t-att-disabled="props.isDisabled"
data-hotkey="j"
t-on-click.stop="discard"
data-tooltip="Discard changes"
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<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">
<t t-call="web.ReportViewMeasures">
<t t-set="measures" t-value="model.metaData.measures"/>
@@ -39,9 +39,7 @@
</t>
<t t-else="" t-call="web.NoContentHelper"/>
</t>
<t t-if="model.hasData() and model.metaData.activeMeasures.length">
<t t-component="props.Renderer" model="model"/>
</t>
<t t-component="props.Renderer" model="model"/>
</Layout>
</div>
</t>
@@ -3,8 +3,7 @@
<t t-name="web.PivotRenderer" owl="1">
<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
class="table-hover table table-sm table-bordered table-borderless bg-view"
t-att-class="{ o_enable_linking: !model.metaData.disableLinking }"
@@ -100,8 +100,6 @@ export class ViewButton extends Component {
this.env[DROPDOWN].close();
}
},
disableAction: this.props.disable,
enableAction: this.props.enable,
});
}
@@ -143,9 +141,7 @@ ViewButton.props = [
"clickParams?",
"icon?",
"defaultRank?",
"disable?",
"disabled?",
"enable?",
"size?",
"tabindex?",
"title?",
@@ -158,6 +154,4 @@ ViewButton.defaultProps = {
tag: "button",
className: "",
clickParams: {},
disable: () => {},
enable: () => {},
};
@@ -7,7 +7,6 @@ import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_d
import { status, useEnv, useSubEnv } from "@odoo/owl";
function disableButtons(el) {
// WOWL: can we do this non-imperatively?
const btns = [...el.querySelectorAll("button:not([disabled])")];
for (const btn of btns) {
btn.setAttribute("disabled", "1");
@@ -15,15 +14,12 @@ function disableButtons(el) {
return btns;
}
function enableButtons(el, manuallyDisabledButtons, enableAction) {
function enableButtons(el, manuallyDisabledButtons) {
if (el) {
for (const btn of manuallyDisabledButtons) {
btn.removeAttribute("disabled");
}
}
if (enableAction) {
enableAction();
}
}
function undefinedAsTrue(val) {
@@ -41,17 +37,8 @@ export function useViewButtons(model, ref, options = {}) {
});
const afterExecuteAction = options.afterExecuteAction || (() => {});
useSubEnv({
async onClickViewButton({
clickParams,
getResParams,
beforeExecute,
disableAction,
enableAction,
}) {
async onClickViewButton({ clickParams, getResParams, beforeExecute }) {
const manuallyDisabledButtons = disableButtons(getEl());
if (disableAction) {
disableAction();
}
async function execute() {
let _continue = true;
@@ -61,7 +48,7 @@ export function useViewButtons(model, ref, options = {}) {
_continue = _continue && undefinedAsTrue(await beforeExecuteAction(clickParams));
if (!_continue) {
enableButtons(getEl(), manuallyDisabledButtons, enableAction);
enableButtons(getEl(), manuallyDisabledButtons);
return;
}
const closeDialog = clickParams.close && env.closeDialog;
@@ -103,7 +90,7 @@ export function useViewButtons(model, ref, options = {}) {
if (closeDialog) {
closeDialog();
}
enableButtons(getEl(), manuallyDisabledButtons, enableAction);
enableButtons(getEl(), manuallyDisabledButtons);
if (error) {
return Promise.reject(error);
}
@@ -124,7 +111,7 @@ export function useViewButtons(model, ref, options = {}) {
};
dialog.add(ConfirmationDialog, dialogProps, { onClose: resolve });
});
enableButtons(getEl(), manuallyDisabledButtons, enableAction);
enableButtons(getEl(), manuallyDisabledButtons);
} else {
return execute();
}
@@ -514,7 +514,8 @@ function makeActionManager(env) {
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;
return {
props: viewProps,
@@ -379,17 +379,15 @@ QUnit.module("DebugMenu", (hooks) => {
await doAction(webClient, 1234);
await click(target.querySelector(".o_debug_manager button"));
await click(target.querySelector(".o_debug_manager .dropdown-item"));
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").textContent,
"Edit view"
);
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb .active");
assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
assert.strictEqual(target.querySelector(".o_field_widget[name=id] input").value, "18");
await click(target, ".breadcrumb .o_back_button");
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb .active");
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").textContent,
target.querySelector(".o_breadcrumb .active").textContent,
"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 .dropdown-item"));
await legacyExtraNextTick();
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").textContent,
"Edit view"
);
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb .active");
assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
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 .dropdown-item"));
await legacyExtraNextTick();
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").textContent,
"Edit view"
);
assert.containsOnce(target, ".breadcrumb-item");
assert.containsOnce(target, ".o_breadcrumb .active");
assert.strictEqual(target.querySelector(".o_breadcrumb .active").textContent, "Edit view");
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) {
if (htmlElement.querySelectorAll(".o_form_button_create").length) {
return click(htmlElement, ".o_form_button_create");
} else if (htmlElement.querySelectorAll(".o_list_button_create").length) {
return click(htmlElement, ".o_list_button_create");
if (
htmlElement.querySelectorAll(
".o_control_panel_main_buttons .d-none.d-xl-inline-flex .o_form_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 {
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) {
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 {
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) {
return click(htmlElement, ".o_form_button_cancel");
} else if (htmlElement.querySelectorAll(".o_list_button_discard").length) {
return click(htmlElement, ".o_list_button_discard");
} else if ($(htmlElement).find(".o_list_button_discard:visible").length) {
return click($(htmlElement).find(".o_list_button_discard:visible").get(0));
} else {
throw new Error("No discard button found to be clicked.");
}
@@ -1,12 +1,8 @@
/** @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 {
editSearch,
makeWithSearch,
setupControlPanelServiceRegistry,
} from "@web/../tests/search/helpers";
import { makeWithSearch, setupControlPanelServiceRegistry } from "@web/../tests/search/helpers";
import { registry } from "@web/core/registry";
import { uiService } from "@web/core/ui/ui_service";
@@ -42,86 +38,6 @@ QUnit.module("Search", (hooks) => {
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) => {
await makeWithSearch({
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_next", "next button should be hidden");
await click(target, ".o_calendar_container .o_other_calendar_panel");
assert.isVisible(
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
// displays month mode by default
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridWeek-view",
"should display the current week"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (Dec 11 – 17, 2016)"
target.querySelector(
".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Week",
"should display the current week"
);
// switch to day mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_scale_button_day");
await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_calendar_sidebar_container .o_scale_button_day");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridDay-view",
"should display the current day"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (December 12, 2016)"
target.querySelector(
".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Day",
"should display the current day"
);
// switch to month mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_scale_button_month");
await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_calendar_sidebar_container .o_scale_button_month");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-dayGridMonth-view",
"should display the current month"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (December 2016)"
target.querySelector(
".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"Month",
"should display the current month"
);
// switch to year mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_scale_button_year");
await click(target, ".o_calendar_sidebar_container .dropdown-toggle");
await click(target, ".o_calendar_sidebar_container .o_scale_button_year");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-dayGridYear-view",
assert.equal(
target.querySelector(
".o_calendar_container .o_calendar_sidebar_container .dropdown-toggle"
).textContent,
"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) {
@@ -186,7 +182,9 @@ QUnit.module("Views", ({ beforeEach }) => {
await swipeRight(target, ".o_calendar_widget");
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_other_calendar_panel");
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
assert.containsOnce(target, ".fc-dayGridYear-view");
assert.containsN(target, ".fc-month-container", 12);
assert.equal(target.querySelector(".breadcrumb-item").textContent, "undefined (2016)");
// Tap on a date
await tap(target, ".fc-day-top[data-date='2016-02-05']");
@@ -368,19 +365,14 @@ QUnit.module("Views", ({ beforeEach }) => {
// Should display day view
assert.containsNone(target, ".fc-dayGridYear-view");
assert.containsOnce(target, ".fc-timeGridDay-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 5, 2016)"
);
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-02-05");
// Change scale to month
await click(target, ".o_calendar_container .o_other_calendar_panel");
await changeScale(target, "month");
await click(target, ".o_calendar_container .o_other_calendar_panel");
assert.containsNone(target, ".fc-timeGridDay-view");
assert.containsOnce(target, ".fc-dayGridMonth-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 2016)"
);
// Tap on a date
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.containsOnce(target, ".fc-timeGridDay-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 10, 2016)"
);
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-02-10");
});
});
@@ -29,7 +29,7 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
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({
type: "form",
resModel: "partner",
@@ -75,20 +75,20 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
);
assert.containsN(
fixture,
".o_statusbar_status .dropdown-menu .btn",
".o_statusbar_status .dropdown-menu .dropdown-item",
3,
"should have 3 status"
);
assert.containsN(
fixture,
".o_statusbar_status .btn.disabled",
".o_statusbar_status .dropdown-item.disabled",
3,
"all status should be disabled"
);
assert.hasClass(
fixture.querySelector(".o_statusbar_status .btn:nth-child(3)"),
"btn-primary",
"active status should be btn-primary"
fixture.querySelector(".o_statusbar_status .dropdown-item:nth-child(3)"),
"active",
"active status should be set"
);
});
@@ -131,30 +131,30 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
);
assert.containsN(
fixture,
".o_statusbar_status .dropdown-menu .btn",
".o_statusbar_status .dropdown-menu .dropdown-item",
3,
"statusbar widget dropdown menu should have 3 buttons"
"statusbar widget dropdown menu should have 3 items"
);
assert.strictEqual(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[0]
.querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[0]
.textContent.trim(),
"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(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[1]
.querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[1]
.textContent.trim(),
"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(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[2]
.querySelectorAll(".o_statusbar_status .dropdown-menu .dropdown-item")[2]
.textContent.trim(),
"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");
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(3)"),
"btn-primary"
fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(3)"),
"active"
);
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"
);
assert.containsN(
fixture,
".o_statusbar_status .btn-secondary:not(.dropdown-toggle):not(.disabled)",
".o_statusbar_status .dropdown-item:not(.dropdown-toggle):not(.disabled):not(.active)",
2,
"other status should be btn-secondary and not disabled"
"other status should be active and not disabled"
);
await click(
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");
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(1)"),
"btn-primary"
fixture.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item:nth-child(1)"),
"active"
);
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"
);
});
@@ -61,13 +61,13 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
assert.containsN(fixture, ".o_data_row", 4);
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
await triggerEvents(fixture, ".o_data_row:nth-child(1)", ["touchstart", "touchend"]);
assert.containsOnce(fixture, ".o_list_selection_box");
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(
fixture.querySelector(".o_list_selection_box").textContent.includes("1 selected")
);
@@ -94,7 +94,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
// unselect all
await click(fixture, ".o_list_unselect_all");
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) {
@@ -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,
"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");
assert.doesNotHaveClass(
@@ -81,7 +81,7 @@ QUnit.test("Burger Menu on an App", async (assert) => {
);
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) => {
@@ -2,7 +2,6 @@
import { getFixture, patchDate, patchWithCleanup } from "@web/../tests/helpers/utils";
import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import {
getFacetTexts,
makeWithSearch,
@@ -12,6 +11,7 @@ import {
toggleFilterMenu,
toggleMenuItem,
toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers";
let target;
@@ -51,12 +51,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "comparison"],
searchViewId: false,
});
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 toggleMenuItem(target, "Birthday");
await toggleMenuItemOption(target, "Birthday", "January");
@@ -65,7 +65,7 @@ QUnit.module("Search", (hooks) => {
target
.querySelector("div.o_comparison_menu > button span")
.innerText.trim()
.toUpperCase() /** @todo why do I need to upperCase */,
.toUpperCase(),
"COMPARISON"
);
await toggleComparisonMenu(target);
@@ -87,7 +87,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "comparison"],
searchViewId: false,
});
@@ -106,7 +106,7 @@ QUnit.module("Search", (hooks) => {
await toggleComparisonMenu(target);
await toggleMenuItem(target, "Date: Previous Year");
assert.deepEqual(getFacetTexts(target), [
["Birthday: January 1997", "Date: December 1996"].join("or"),
["Birthday: January 1997", "Date: December 1996"].join("\nor\n"),
"Date: Previous Year",
]);
await toggleFilterMenu(target);
+14 -32
View File
@@ -1,10 +1,8 @@
/** @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 { makeWithSearch, setupControlPanelServiceRegistry } from "./helpers";
import { Component, xml } from "@odoo/owl";
import { makeTestEnv } from "../helpers/mock_env";
let target;
let serverData;
@@ -39,16 +37,15 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: [],
});
assert.containsOnce(target, ".o_cp_top");
assert.containsOnce(target, ".o_cp_top_left");
assert.strictEqual(target.querySelector(".o_cp_top_right").innerHTML, "");
assert.containsOnce(target, ".o_cp_bottom");
assert.containsOnce(target, ".o_cp_bottom_left");
assert.containsOnce(target, ".o_cp_bottom_right");
assert.containsOnce(target, ".o_control_panel_breadcrumbs");
assert.containsOnce(target, ".o_control_panel_actions");
assert.strictEqual(target.querySelector(".o_control_panel_actions").innerHTML, "");
assert.containsOnce(target, ".o_control_panel_navigation");
assert.strictEqual(target.querySelector(".o_control_panel_navigation").innerHTML, "");
assert.containsNone(target, ".o_cp_switch_buttons");
assert.containsOnce(target, ".breadcrumb");
assert.containsOnce(target, ".o_breadcrumb");
});
QUnit.test("breadcrumbs", async (assert) => {
@@ -65,8 +62,9 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: [],
});
assert.containsN(target, ".breadcrumb li.breadcrumb-item", 2);
const breadcrumbItems = target.querySelectorAll("li.breadcrumb-item");
const breadcrumbsSelector = ".o_breadcrumb li.breadcrumb-item, .o_breadcrumb .active";
assert.containsN(target, breadcrumbsSelector, 2);
const breadcrumbItems = target.querySelectorAll(breadcrumbsSelector);
assert.strictEqual(breadcrumbItems[0].innerText, "Previous");
assert.hasClass(breadcrumbItems[1], "active");
assert.strictEqual(breadcrumbItems[1].innerText, "Current");
@@ -93,7 +91,10 @@ QUnit.module("Search", (hooks) => {
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);
const views = target.querySelectorAll(".o_switch_view");
@@ -134,23 +135,4 @@ QUnit.module("Search", (hooks) => {
await nextTick();
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 { browser } from "@web/core/browser/browser";
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 { useSetupAction } from "@web/webclient/actions/action_hook";
import {
@@ -16,10 +15,12 @@ import {
setupControlPanelServiceRegistry,
toggleFavoriteMenu,
toggleSaveFavorite,
toggleSearchBarMenu,
validateSearch,
} from "./helpers";
import { Component, xml } from "@odoo/owl";
import { SearchBar } from "@web/search/search_bar/search_bar";
const serviceRegistry = registry.category("services");
/**
@@ -79,7 +80,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["favorite"],
searchViewId: false,
config: {
@@ -87,7 +88,7 @@ QUnit.module("Search", (hooks) => {
},
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
assert.strictEqual(
target.querySelector('.o_add_favorite input[type="text"]').value,
@@ -107,12 +108,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["favorite"],
searchViewId: false,
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
const checkboxes = target.querySelectorAll('input[type="checkbox"]');
@@ -211,8 +212,8 @@ QUnit.module("Search", (hooks) => {
}
},
resModel: "foo",
Component: ControlPanel,
searchMenuTypes: ["favorite"],
Component: SearchBar,
searchMenuTypes: ["filter", "favorite"],
searchViewId: false,
searchViewArch: `
<search>
@@ -224,7 +225,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Filter"]);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite");
await saveFavorite(target);
@@ -245,7 +246,7 @@ QUnit.module("Search", (hooks) => {
}
},
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["favorite"],
searchViewId: false,
searchViewArch: `
@@ -262,7 +263,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo\na"]);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite");
await saveFavorite(target);
@@ -312,7 +313,7 @@ QUnit.module("Search", (hooks) => {
}
},
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["favorite"],
searchViewId: false,
irFilters: [
@@ -328,7 +329,7 @@ QUnit.module("Search", (hooks) => {
],
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
// 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) {
assert.expect(2);
QUnit.test(
"undefined name for filter shows notification and not error",
async function (assert) {
assert.expect(2);
serviceRegistry.add(
"notification",
{
start() {
return {
add(message, options) {
assert.strictEqual(
message,
"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" });
},
};
serviceRegistry.add(
"notification",
{
start() {
return {
add(message, options) {
assert.strictEqual(
message,
"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" });
},
};
},
},
},
{ force: true }
);
{ force: true }
);
await makeWithSearch({
serverData,
mockRPC: (_, args) => {
if (args.model === "ir.filters" && args.method === "create_or_replace") {
return 7; // fake serverSideId
}
},
resModel: "foo",
Component: FavoriteMenu,
searchViewId: false,
});
await makeWithSearch({
serverData,
mockRPC: (_, args) => {
if (args.model === "ir.filters" && args.method === "create_or_replace") {
return 7; // fake serverSideId
}
},
resModel: "foo",
Component: FavoriteMenu,
searchViewId: false,
});
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await saveFavorite(target);
});
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await saveFavorite(target);
}
);
QUnit.skip("save search filter in modal", async function (assert) {
/** @todo I don't know yet how to convert this test */
@@ -1,7 +1,6 @@
/** @odoo-module **/
import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { getFixture, patchWithCleanup } from "../helpers/utils";
import {
applyGroup,
@@ -11,9 +10,10 @@ import {
makeWithSearch,
setupControlPanelServiceRegistry,
toggleAddCustomGroup,
toggleGroupByMenu,
toggleMenuItem,
toggleSearchBarMenu,
} from "./helpers";
import { SearchBar } from "@web/search/search_bar/search_bar";
let target;
let serverData;
@@ -52,12 +52,12 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
});
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
const customGroupByItem = target.querySelector(".o_add_custom_group_menu");
assert.strictEqual(customGroupByItem.innerText.trim(), "Add Custom Group");
@@ -85,7 +85,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewFields: {
@@ -94,7 +94,7 @@ QUnit.module("Search", (hooks) => {
},
});
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
assert.deepEqual(
@@ -116,7 +116,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewFields: {
@@ -130,7 +130,7 @@ QUnit.module("Search", (hooks) => {
},
});
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
assert.deepEqual(
@@ -152,7 +152,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewFields: {
@@ -160,7 +160,7 @@ QUnit.module("Search", (hooks) => {
id: { sortable: true, string: "ID", type: "integer" },
},
});
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.deepEqual(controlPanel.env.searchModel.groupBy, []);
assert.containsNone(target, ".o_menu_item");
@@ -184,14 +184,14 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewFields: {
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");
@@ -220,7 +220,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewFields: {
candle_light: {
@@ -231,7 +231,7 @@ QUnit.module("Search", (hooks) => {
},
});
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
await applyGroup(target);
@@ -3,7 +3,6 @@
import { click, getFixture, patchDate } from "@web/../tests/helpers/utils";
import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
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 { SearchBar } from "@web/search/search_bar/search_bar";
import {
@@ -16,6 +15,7 @@ import {
toggleComparisonMenu,
toggleFavoriteMenu,
toggleMenuItem,
DropDownMenusTestComponent,
} from "@web/../tests/search/helpers";
import { Component, onWillUpdateProps, xml } from "@odoo/owl";
@@ -28,6 +28,7 @@ function getDomain(comp) {
let serverData;
let target;
QUnit.module("Search", (hooks) => {
hooks.beforeEach(async () => {
target = getFixture();
@@ -64,7 +65,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"],
searchViewId: false,
config: {
@@ -97,7 +98,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"],
searchViewId: false,
config: {
@@ -208,7 +209,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["favorite"],
searchViewId: false,
irFilters: [
@@ -241,7 +242,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"],
searchViewId: false,
irFilters: [
@@ -9,7 +9,6 @@ import {
patchWithCleanup,
} from "@web/../tests/helpers/utils";
import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import {
getFacetTexts,
isItemSelected,
@@ -20,6 +19,7 @@ import {
toggleFilterMenu,
toggleMenuItem,
toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers";
function getDomain(controlPanel) {
@@ -68,7 +68,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
});
@@ -83,7 +83,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -109,7 +109,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -132,7 +132,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo"]);
assert.containsOnce(
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.deepEqual(getDomain(controlPanel), [["foo", "=", "qsdf"]]);
@@ -152,7 +152,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -382,7 +382,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -416,7 +416,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -443,7 +443,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -469,7 +469,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -493,7 +493,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -519,7 +519,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -547,7 +547,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), [
"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({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewArch: `
@@ -600,7 +600,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
});
@@ -628,7 +628,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
});
await toggleFilterMenu(target);
@@ -652,7 +652,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
});
await toggleFilterMenu(target);
@@ -670,7 +670,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
});
await toggleFilterMenu(target);
@@ -696,7 +696,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `
@@ -756,7 +756,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
@@ -781,7 +781,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
@@ -1,7 +1,6 @@
/** @odoo-module **/
import { browser } from "@web/core/browser/browser";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { getFixture, patchWithCleanup } from "../helpers/utils";
import {
getFacetTexts,
@@ -13,6 +12,7 @@ import {
toggleGroupByMenu,
toggleMenuItem,
toggleMenuItemOption,
DropDownMenusTestComponent,
} from "./helpers";
let target;
@@ -54,7 +54,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewFields: {},
@@ -74,7 +74,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
});
@@ -90,7 +90,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -115,7 +115,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -141,7 +141,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getFacetTexts(target), ["Foo"]);
assert.containsOnce(
target.querySelector(".o_searchview .o_searchview_facet"),
"span.oi.oi-group.o_searchview_facet_label"
".o_searchview_facet_label"
);
assert.ok(isItemSelected(target, "Foo"));
@@ -158,7 +158,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -184,7 +184,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -218,7 +218,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -245,19 +245,19 @@ QUnit.module("Search", (hooks) => {
const steps = [
{
description: "Year",
facetTexts: ["Date: Year>Date: Week"],
facetTexts: ["Date: Year\n>\nDate: Week"],
selectedoptions: ["Year", "Week"],
groupBy: ["date_field:year", "date_field:week"],
},
{
description: "Month",
facetTexts: ["Date: Year>Date: Month>Date: Week"],
facetTexts: ["Date: Year\n>\nDate: Month\n>\nDate: Week"],
selectedoptions: ["Year", "Month", "Week"],
groupBy: ["date_field:year", "date_field:month", "date_field:week"],
},
{
description: "Week",
facetTexts: ["Date: Year>Date: Month"],
facetTexts: ["Date: Year\n>\nDate: Month"],
selectedoptions: ["Year", "Month"],
groupBy: ["date_field:year", "date_field:month"],
},
@@ -286,7 +286,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -309,43 +309,49 @@ QUnit.module("Search", (hooks) => {
// select option 'week'
await toggleMenuItemOption(target, "Date", "Week");
assert.deepEqual(getFacetTexts(target), ["Bar>Date: Week"]);
assert.deepEqual(getFacetTexts(target), ["Bar\n>\nDate: Week"]);
// select option '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'
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'
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'
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Quarter");
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'
await toggleMenuItem(target, "Bar");
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'
await toggleMenuItem(target, "Date");
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) {
@@ -354,7 +360,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -371,7 +377,7 @@ QUnit.module("Search", (hooks) => {
"date_field:week",
"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) {
@@ -380,7 +386,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -407,7 +413,7 @@ QUnit.module("Search", (hooks) => {
assert.ok(isItemSelected(target, "Date"));
assert.ok(isItemSelected(target, "Bar"));
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");
@@ -415,7 +421,7 @@ QUnit.module("Search", (hooks) => {
assert.ok(isItemSelected(target, "Bar"));
assert.ok(isOptionSelected(target, "Date", "Quarter"), "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, "Date");
@@ -424,7 +430,7 @@ QUnit.module("Search", (hooks) => {
assert.notOk(isItemSelected(target, "Bar"));
assert.ok(isOptionSelected(target, "Date", "Quarter"), "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);
@@ -445,7 +451,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchMenuTypes: ["groupBy"],
searchViewId: false,
searchViewArch: `
@@ -467,7 +473,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchViewArch: `
<search>
@@ -490,7 +496,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchViewArch: `
<search>
@@ -514,7 +520,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
Component: DropDownMenusTestComponent,
searchViewId: false,
searchViewArch: `
<search>
+49 -6
View File
@@ -21,6 +21,11 @@ import { popoverService } from "@web/core/popover/popover_service";
import { registry } from "@web/core/registry";
import { CustomFavoriteItem } from "@web/search/favorite_menu/custom_favorite_item";
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 { viewService } from "@web/views/view_service";
import { actionService } from "@web/webclient/actions/action_service";
@@ -196,7 +201,18 @@ export function getMenuItemTexts(target) {
}
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 */
@@ -280,7 +296,7 @@ export async function applyGroup(el) {
}
export async function groupByMenu(el, fieldName) {
await toggleGroupByMenu(el);
await toggleSearchBarMenu(el);
await toggleAddCustomGroup(el);
await selectGroup(el, fieldName);
await applyGroup(el);
@@ -331,7 +347,7 @@ export function getFacetTexts(target) {
export async function removeFacet(el, facetFinder = 0) {
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) {
@@ -384,7 +400,34 @@ export async function editPager(el, value) {
* @param {string} [menuFinder="Action"]
* @returns {Promise}
*/
export async function toggleActionMenu(el, menuFinder = "Action") {
const dropdown = findItem(el, `.o_cp_action_menus button`, menuFinder);
await click(dropdown);
export async function toggleActionMenu(el) {
await click(el.querySelector(".o_cp_action_menus .dropdown-toggle"));
}
/** 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 **/
import { ControlPanel } from "@web/search/control_panel/control_panel";
import {
click,
getFixture,
@@ -9,7 +8,6 @@ import {
nextTick,
patchDate,
patchTimeZone,
patchWithCleanup,
triggerEvent,
} from "../helpers/utils";
import {
@@ -18,9 +16,8 @@ import {
makeWithSearch,
removeFacet,
setupControlPanelServiceRegistry,
toggleComparisonMenu,
toggleGroupByMenu,
toggleMenuItem,
toggleSearchBarMenu,
validateSearch,
} from "./helpers";
@@ -32,7 +29,8 @@ function getDomain(controlPanel) {
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 serverData;
@@ -143,7 +141,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -161,7 +159,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
context: { search_default_date_group_by: 1 },
@@ -190,7 +188,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"],
searchViewId: false,
context: {
@@ -236,7 +234,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -248,7 +246,7 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" }); // select
assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, " ")),
getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Birthday 07/15/1983"],
"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
assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, " ")),
["Birth DateTime\n07/15/1983 00:00:00"],
getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Birth DateTime 07/15/1983 00:00:00"],
"The format of the datetime in the facet should be in locale"
);
@@ -279,7 +277,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -324,7 +322,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -352,19 +350,20 @@ QUnit.module("Search", (hooks) => {
assert.expect(8);
let updateCount = 0;
patchWithCleanup(ControlPanel.prototype, {
class TestComponent extends Component {
setup() {
this._super();
onWillUpdateProps(() => {
updateCount++;
});
},
});
}
}
TestComponent.template = xml`<SearchBar/>`;
TestComponent.components = { SearchBar };
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: TestComponent,
searchMenuTypes: [],
searchViewId: false,
});
@@ -378,8 +377,8 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, "")),
["BarFirst record"]
getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Bar First record"]
);
assert.strictEqual(updateCount, 1);
@@ -396,8 +395,8 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
assert.deepEqual(
getFacetTexts(target).map((str) => str.replace(/\s+/, "")),
["BarFirst recordorSecond record"]
getFacetTexts(target).map((str) => str.replace(/\s+/g, " ")),
["Bar First record or Second record"]
);
assert.strictEqual(updateCount, 2);
@@ -410,19 +409,20 @@ QUnit.module("Search", (hooks) => {
assert.expect(2);
let updateCount = 0;
patchWithCleanup(ControlPanel.prototype, {
class TestComponent extends Component {
setup() {
this._super();
onWillUpdateProps(() => {
updateCount++;
});
},
});
}
}
TestComponent.template = xml`<SearchBar/>`;
TestComponent.components = { SearchBar };
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: TestComponent,
searchMenuTypes: [],
searchViewId: false,
});
@@ -440,7 +440,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -487,7 +487,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -588,7 +588,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -610,7 +610,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -647,7 +647,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -672,7 +672,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -719,7 +719,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -759,7 +759,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -801,7 +801,7 @@ QUnit.module("Search", (hooks) => {
serverData,
mockRPC,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -840,7 +840,7 @@ QUnit.module("Search", (hooks) => {
serverData,
mockRPC,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -867,7 +867,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -895,7 +895,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -926,7 +926,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: /*xml*/ `
@@ -989,7 +989,7 @@ QUnit.module("Search", (hooks) => {
serverData,
mockRPC,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
});
@@ -1029,18 +1029,18 @@ QUnit.module("Search", (hooks) => {
serverData,
mockRPC,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
context: { search_default_company: 1 },
});
await nextTick();
assert.containsNone(target, ".o_control_panel");
assert.containsNone(target, ".o_cp_searchview");
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_control_panel");
assert.containsOnce(target, ".o_cp_searchview");
assert.strictEqual(getFacetTexts(target)[0].replace("\n", ""), "CompanyFirst record");
});
@@ -1050,7 +1050,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -1147,7 +1147,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -1211,7 +1211,7 @@ QUnit.module("Search", (hooks) => {
]);
// expand the selection properties
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a");
await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1233,7 +1233,7 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getDomain(controlPanel), expectedDomain);
// select the selection option "A"
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a");
await click(target.querySelector(".o_expand"));
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"));
// search a many2one value
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "Ali");
await click(target.querySelector(".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);
// search a tag value
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "A");
await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1290,7 +1290,7 @@ QUnit.module("Search", (hooks) => {
];
assert.deepEqual(getDomain(controlPanel), expectedDomain);
// add the tag "B"
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "B");
await click(target.querySelector(".o_expand"));
items = target.querySelectorAll(".o_searchview_input_container li");
@@ -1402,7 +1402,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: [],
searchViewId: false,
searchViewArch: `
@@ -1414,7 +1414,7 @@ QUnit.module("Search", (hooks) => {
context: { active_id: 2 },
});
await click(target.querySelector(".o_control_panel"));
await click(target.querySelector(".o_cp_searchview"));
await editSearch(target, "a");
await click(target.querySelector(".o_expand"));
@@ -1427,7 +1427,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model)
searchViewId: false,
searchViewArch: `
@@ -1490,7 +1490,7 @@ QUnit.module("Search", (hooks) => {
const controlPanel = await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchViewId: false,
searchViewArch: `
<search>
@@ -1527,7 +1527,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["groupBy"], // we need it to have facet (see facets getter in search_model)
searchViewId: false,
searchViewArch: `
@@ -1543,7 +1543,7 @@ QUnit.module("Search", (hooks) => {
".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label"
);
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Company");
assert.deepEqual(getFacetTexts(target), ["My favorite", "Company"]);
@@ -1562,7 +1562,7 @@ QUnit.module("Search", (hooks) => {
await click(target.querySelector(".modal footer button"));
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) {
@@ -1570,7 +1570,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchMenuTypes: ["filter", "comparison"],
searchViewId: false,
searchViewArch: `
@@ -1588,8 +1588,8 @@ QUnit.module("Search", (hooks) => {
".o_searchview_facet.o_facet_with_domain .o_searchview_facet_label"
);
await toggleComparisonMenu(target);
await toggleMenuItem(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Birthday: Previous Period");
assert.deepEqual(getFacetTexts(target), [
"Birthday: April 2023",
@@ -1628,7 +1628,7 @@ QUnit.module("Search", (hooks) => {
await makeWithSearch({
serverData,
resModel: "partner",
Component: ControlPanel,
Component: SearchBar,
searchViewId: false,
searchViewArch: `
<search>
@@ -1650,7 +1650,7 @@ QUnit.module("Search", (hooks) => {
await triggerEvent(searchInput, null, "keydown", { key: "ArrowDown" });
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");
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) => {
assert.expect(28);
assert.expect(30);
await makeView({
type: "calendar",
@@ -999,9 +957,26 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsN(target, ".fc-event-container .fc-event", 10, "should display 10 events");
// move to next month
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");
await navigate(target, "prev");
await pickDate(target, "2016-12-27");
await changeScale(target, "month");
await selectDateRange(target, "2016-12-20", "2016-12-21");
await editInput(target, ".o-calendar-quick-create--input", "test");
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
await toggleSectionFilter(target, "partner_ids");
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, ".fc-event", 2, "should display 2 events");
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) => {
assert.expect(1);
assert.expect(2);
serverData.views = {
"event,1,calendar": `<calendar date_start="start" date_stop="stop" mode="day"/>`,
"event,false,search": `<search />`,
@@ -4018,8 +3994,13 @@ QUnit.module("Views", ({ beforeEach }) => {
await doAction(webClient, 1);
await nextTick();
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"context initial date (January 30, 2016)",
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"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"
);
});
@@ -508,7 +508,7 @@ export async function changeScale(target, scale) {
}
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) {
@@ -376,7 +376,10 @@ QUnit.module("Fields", (hooks) => {
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.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);
serverData.models.partner.onchanges = {
document: function (obj) {
@@ -498,7 +501,7 @@ QUnit.module("Fields", (hooks) => {
await editInput(target, ".o_field_binary .o_input_file", file);
assert.equal(
target.querySelector(".o_select_file_button").innerText,
"UPLOAD YOUR FILE",
"Upload your file",
"displayed value should be upload your file"
);
});
@@ -224,7 +224,11 @@ QUnit.module("Fields", (hooks) => {
</tree>`,
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
.querySelector('.o_list_table thead th[data-name="date_field"]')
.style.width.replace("px", "");
@@ -268,7 +268,11 @@ QUnit.module("Fields", (hooks) => {
);
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(
target.querySelector(".o_field_widget").textContent,
"18.896",
@@ -652,7 +652,7 @@ QUnit.module("Fields", (hooks) => {
);
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(
target.querySelector("img[data-alt='Binary file']").dataset.src,
"/web/static/img/placeholder.png",
@@ -262,7 +262,11 @@ QUnit.module("Fields", (hooks) => {
"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(
target.querySelector("td:not(.o_list_record_selector)").textContent,
"-28",
@@ -181,7 +181,11 @@ QUnit.module("Fields", (hooks) => {
);
// 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(
target.querySelectorAll(".o_field_widget .badge:not(:empty)").length,
3,
@@ -59,13 +59,13 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".o_field_many2many_tags_avatar.o_field_widget .o_avatar",
".o_field_many2many_tags_avatar.o_field_widget .o_avatar img",
2,
"should have 2 records"
);
assert.strictEqual(
target.querySelector(".o_field_many2many_tags_avatar.o_field_widget .o_avatar img").dataset
.src,
target.querySelector(".o_field_many2many_tags_avatar.o_field_widget .o_avatar img")
.dataset.src,
"/web/image/partner/2/avatar_128",
"should have correct avatar image"
);
@@ -116,13 +116,13 @@ QUnit.module("Fields", (hooks) => {
);
assert.containsN(
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,
"should have 4 records"
);
assert.containsN(
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,
"should have 5 records"
);
@@ -175,7 +175,7 @@ QUnit.module("Fields", (hooks) => {
);
assert.containsN(
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,
"should have 4 records"
);
@@ -213,16 +213,20 @@ QUnit.module("Fields", (hooks) => {
await click(target.querySelector(".o_data_row .o_many2many_tags_avatar_cell"));
assert.containsN(
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,
"should have 1 many2many badges in edit mode"
);
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(
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,
"should have 2 records"
);
@@ -333,13 +337,13 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
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,
"should have 2 records"
);
assert.containsN(
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,
"should have 2 records"
);
@@ -374,7 +378,7 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
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,
"should have 2 records"
);
@@ -26,8 +26,7 @@ import {
import {
editSearch,
getFacetTexts,
toggleFilterMenu,
toggleGroupByMenu,
toggleSearchBarMenu,
toggleMenuItem,
validateSearch,
} from "@web/../tests/search/helpers";
@@ -626,7 +625,7 @@ QUnit.module("Fields", (hooks) => {
const modal = target.querySelector(".modal");
await toggleFilterMenu(modal);
await toggleSearchBarMenu(modal);
await toggleMenuItem(modal, "Filter");
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);
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);
@@ -3980,32 +3982,14 @@ QUnit.module("Fields", (hooks) => {
await click(target, `.o_field_widget[name="trululu"] .o_m2o_dropdown_option_search_more`);
// dropdown selector
const filterMenuCss = ".o_search_options > .o_filter_menu";
const groupByMenuCss = ".o_search_options > .o_group_by_menu";
const searchDropdown = ".o_control_panel_actions .o-dropdown";
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(
document.querySelector(`${filterMenuCss} > .dropdown-menu`),
"the filter 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"
document.querySelector(`${searchDropdown} > .dropdown-menu`),
"the search bar dropdown menu should be visible"
);
});
@@ -4198,7 +4182,7 @@ QUnit.module("Fields", (hooks) => {
await selectDropdownItem(target, "trululu", "Search More...");
const modal = target.querySelector(".modal");
await toggleGroupByMenu(modal);
await toggleSearchBarMenu(modal);
await toggleMenuItem(modal, "Bar");
await click(modal.querySelectorAll(".o_group_header")[1]);
@@ -4371,20 +4355,23 @@ QUnit.module("Fields", (hooks) => {
const target = getFixture();
await doAction(webClient, 1);
assert.containsOnce(target, "a.o_form_uri", "should display 1 m2o link in form");
assert.containsN(
assert.containsOnce(
target,
".breadcrumb-item",
1,
".o_breadcrumb",
"Should only contain one breadcrumb at the start"
);
await click(target.querySelector("a.o_form_uri"));
assert.verifySteps(["get_formview_action"]);
assert.containsN(
assert.containsOnce(
target,
".breadcrumb-item",
2,
"Should contain 2 breadcrumbs after the clicking on the link"
"Should contain 1 breadcrumb link 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");
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) {
@@ -771,7 +771,11 @@ QUnit.module("Fields", (hooks) => {
</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(
target,
".o_selected_row .o_field_widget[name=float_field] input",
@@ -63,72 +63,15 @@ QUnit.module("Fields", (hooks) => {
"should have a pie chart"
);
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,
"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"
);
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"
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie").style.background,
"conic-gradient( var(--PercentPieField-color-active) 0% 10%, var(--PercentPieField-color-static) 0% 100% )",
"pie should have a background computed for its value of 10%"
);
});
@@ -154,117 +97,15 @@ QUnit.module("Fields", (hooks) => {
"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.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")
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.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%"
);
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%"
target.querySelector(".o_field_percent_pie.o_field_widget .o_pie").style.background,
"conic-gradient( var(--PercentPieField-color-active) 0% 80%, var(--PercentPieField-color-static) 0% 100% )",
"pie should have a background computed for its value of 80%"
);
});
// 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");
// 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)");
assert.doesNotHaveClass(
cell.parentElement,
@@ -343,7 +343,10 @@ QUnit.module("Fields", (hooks) => {
assert.verifySteps(['write [[1],{"selection":"1"}]']);
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.querySelector(".o_priority a.o_priority_star.fa-star-o"), null, true);
assert.verifySteps(['write [[6],{"selection":"1"}]']);
@@ -404,7 +407,10 @@ QUnit.module("Fields", (hooks) => {
);
// 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(
target.querySelectorAll(".o_data_row")[0],
@@ -514,7 +520,10 @@ QUnit.module("Fields", (hooks) => {
);
// 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");
assert.containsN(
@@ -1,9 +1,6 @@
/** @odoo-module **/
import {
makeFakeLocalizationService,
makeFakeNotificationService,
} from "@web/../tests/helpers/mock_services";
import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
import {
click,
clickSave,
@@ -507,13 +504,6 @@ QUnit.module("Fields", (hooks) => {
"ProgressBarField: write gibbrish instead of int throws warning",
async function (assert) {
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({
serverData,
@@ -535,7 +525,11 @@ QUnit.module("Fields", (hooks) => {
await editInput(target, ".o_progressbar_value .o_input", "trente sept virgule neuf");
await clickSave(target);
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(
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"
);
}
@@ -865,7 +865,7 @@ QUnit.module("Fields", (hooks) => {
mockRPC: (route, { method, args }) => {
if (method === "onchange") {
return {
value: {reference: "partner,2"},
value: { reference: "partner,2" },
};
} else if (method === "create") {
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 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(
@@ -82,14 +82,18 @@ QUnit.module("Fields", (hooks) => {
".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"
);
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
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(
target,
".dropdown-menu .dropdown-item",
".o_content .dropdown-menu .dropdown-item",
3,
"there should be three options in the dropdown"
);
@@ -100,8 +104,12 @@ QUnit.module("Fields", (hooks) => {
);
// Click on the first option, "Normal"
await click(target.querySelector(".dropdown-menu .dropdown-item"));
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore");
await click(target.querySelector(".o_content .dropdown-menu .dropdown-item"));
assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsNone(
target,
".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"
);
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(
target,
".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
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(
target,
".dropdown-menu .dropdown-item",
@@ -146,8 +158,12 @@ QUnit.module("Fields", (hooks) => {
);
// Click on the last option, "Done"
await click(target, ".dropdown-menu .dropdown-item:last-child");
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore");
await click(target, ".o_content .dropdown-menu .dropdown-item:last-child");
assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsNone(
target,
".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"));
assert.containsNone(
target,
".dropdown-menu",
".o_content .dropdown-menu",
"there should still not be a dropdown anymore"
);
assert.containsNone(
@@ -281,7 +297,7 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status.o_status_green",
"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
let cell = target.querySelector("tbody td.o_state_selection_cell");
@@ -293,16 +309,16 @@ QUnit.module("Fields", (hooks) => {
"o_selected_row",
"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(
target,
".dropdown-menu .dropdown-item",
".o_content .dropdown-menu .dropdown-item",
3,
"there should be three options in the dropdown"
);
// 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(
target,
".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",
"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");
// 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",
"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
await click(
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(
target,
".dropdown-menu .dropdown-item",
".o_content .dropdown-menu .dropdown-item",
3,
"there should be three options in the dropdown"
);
@@ -359,7 +375,11 @@ QUnit.module("Fields", (hooks) => {
// Click on another row
const lastCell = target.querySelectorAll("tbody td.o_state_selection_cell")[4];
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");
assert.doesNotHaveClass(
firstCell.parentElement,
@@ -378,17 +398,21 @@ QUnit.module("Fields", (hooks) => {
".o_state_selection_cell .o_field_state_selection span.o_status"
)[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(
target,
".dropdown-menu .dropdown-item",
".o_content .dropdown-menu .dropdown-item",
3,
"there should be three options in the dropdown"
);
// Click on the last option, "Done"
await click(target, ".dropdown-menu .dropdown-item:last-child");
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown anymore");
await click(target, ".o_content .dropdown-menu .dropdown-item:last-child");
assert.containsNone(
target,
".o_content .dropdown-menu",
"there should not be a dropdown anymore"
);
assert.containsN(
target,
".o_state_selection_cell .o_field_state_selection span.o_status",
@@ -406,10 +430,14 @@ QUnit.module("Fields", (hooks) => {
2,
"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
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(
target,
".o_state_selection_cell .o_field_state_selection span.o_status",
@@ -427,7 +455,7 @@ QUnit.module("Fields", (hooks) => {
2,
"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(
@@ -584,7 +584,11 @@ QUnit.module("Fields", (hooks) => {
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(
target.querySelector("textarea"),
@@ -226,7 +226,11 @@ QUnit.module("Fields", (hooks) => {
await editInput(cell, "input", "brolo");
// 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)");
assert.doesNotHaveClass(
cell.parentElement,
@@ -184,7 +184,7 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ `
<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_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>
</t>`;
@@ -206,10 +206,10 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ `
<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_sheet_bg pt-2">
<div class="o_form_statusbar position-relative d-flex justify-content-between pb-3 px-3"><StatusBarButtons/></div>
<div class="o_form_sheet_bg">
<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 class="o_form_sheet position-relative clearfix px-3">
<div class="o_form_sheet position-relative">
<div>inside sheet</div>
</div>
</div>
@@ -267,7 +267,7 @@ QUnit.module("Form Compiler", (hooks) => {
</form>`;
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>
<t t-set-slot="button_0" isVisible="true">
<div>someDiv</div>
@@ -285,7 +285,7 @@ QUnit.module("Form Compiler", (hooks) => {
</form>`;
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/>
</div>`;
@@ -21,7 +21,11 @@ import {
triggerEvent,
triggerHotkey,
} 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 { createWebClient, doAction } from "@web/../tests/webclient/helpers";
import { browser } from "@web/core/browser/browser";
@@ -46,6 +50,11 @@ const widgetRegistry = registry.category("view_widgets");
let target;
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) => {
hooks.beforeEach(() => {
target = getFixture();
@@ -384,15 +393,15 @@ QUnit.module("Views", (hooks) => {
type: "form",
resModel: "partner",
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,
});
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");
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) => {
@@ -1708,7 +1717,7 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData });
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");
// sanity check: notebook active page is first page
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"));
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");
// check notebook active page is first page again
assert.hasClass(target.querySelector(".o_notebook .nav-link"), "active");
@@ -3187,16 +3196,10 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps(["read1", "willStart"]);
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"));
assert.verifySteps([
"willUpdateProps",
"willUpdateProps",
"read3",
"willUpdateProps",
"willUpdateProps",
]);
assert.verifySteps(["willUpdateProps", "read3", "willUpdateProps"]);
});
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;
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsOnce(target, ".o_form_editable");
assert.strictEqual(
target.querySelector(".o_field_char input").value,
@@ -3784,7 +3787,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_cp_action_menus");
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsOnce(target, ".o_cp_action_menus");
@@ -3897,13 +3900,13 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1);
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"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(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"New",
"should have the display name of the record as title"
);
@@ -4186,16 +4189,16 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"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 toggleMenuItem(target, "Duplicate");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"first record (copy)",
"should have duplicated the record"
);
@@ -4236,9 +4239,9 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"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");
await toggleActionMenu(target);
@@ -4342,15 +4345,14 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"second record",
"should have correct display_name"
);
await editInput(target, ".o_field_widget[name=name] input", "some other name");
await click(target.querySelector(".oe_stat_button"));
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"GOLDORAK",
"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.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
await editInput(target, ".o_field_widget[name=foo] input", "");
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.strictEqual(
target.querySelector(".breadcrumb-item > span").innerText,
"first record"
);
assert.strictEqual(
target.querySelector(".breadcrumb-item > .o_form_status_indicator").innerText.trim(),
"Unable to save"
target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"Unable to save. Correct the issue or discard changes"
);
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
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.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
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", "");
triggerHotkey("alt+n");
await nextTick();
assert.strictEqual(target.querySelector(".o_breadcrumb").innerText, "first record");
assert.strictEqual(
target.querySelector(".breadcrumb-item > span").innerText,
"first record"
);
assert.strictEqual(
target.querySelector(".breadcrumb-item > .o_form_status_indicator").innerText.trim(),
"Unable to save"
target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"Unable to save. Correct the issue or discard changes"
);
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
@@ -5116,17 +5112,17 @@ QUnit.module("Views", (hooks) => {
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.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
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");
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.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
});
@@ -5480,7 +5476,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".o_back_button");
// 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");
assert.hasClass(notebooks[0].querySelector(".nav-link"), "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_limit").textContent, "2");
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsNone(target, ".o_pager");
@@ -5557,7 +5553,7 @@ QUnit.module("Views", (hooks) => {
});
assert.containsNone(target, ".foo_field");
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsOnce(target, ".foo_field");
});
@@ -5582,7 +5578,7 @@ QUnit.module("Views", (hooks) => {
});
assert.containsOnce(target, ".o_field_empty");
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsNone(target, ".o_field_empty");
});
@@ -5883,7 +5879,7 @@ QUnit.module("Views", (hooks) => {
// create mode (leave edition first!)
await clickDiscard(target);
await click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.containsOnce(
target,
".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({
type: "form",
resModel: "partner",
@@ -7044,18 +7040,18 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".oe_button_box").children.length,
target.querySelector(".o-form-buttonbox").children.length,
2,
"button box should contain two children"
);
assert.containsOnce(
target,
".oe_button_box > .oe_stat_button",
".o-form-buttonbox > .oe_stat_button",
"button box should only contain one button"
);
assert.containsOnce(
target,
".oe_button_box > label",
".o-form-buttonbox > label",
"button box should only contain one label"
);
});
@@ -7085,12 +7081,12 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".oe_button_box").children.length,
target.querySelector(".o-form-buttonbox").children.length,
1,
"button box should contain only one child"
);
assert.hasClass(
target.querySelector(".oe_button_box"),
target.querySelector(".o-form-buttonbox"),
"o_not_full",
"the buttonbox should not be full"
);
@@ -7135,7 +7131,7 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
target.querySelector(".oe_button_box").children.length,
target.querySelector(".o-form-buttonbox").children.length,
2,
"button box should contain two children"
);
@@ -7557,7 +7553,7 @@ QUnit.module("Views", (hooks) => {
function getVisibleButtonTexts() {
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 click(target.querySelector(".o_form_button_create"));
await createRecord();
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"",
@@ -7647,11 +7643,9 @@ QUnit.module("Views", (hooks) => {
</sheet>
</form>`,
});
var $button = target.querySelector(
".o_form_view .o_form_sheet .oe_button_box .oe_stat_button"
);
const button = target.querySelector(".o_form_view .o-form-buttonbox .oe_stat_button");
assert.strictEqual(
$button.textContent,
button.textContent,
"Inventory Moves",
"the stat button should contain a span with the string attribute value"
);
@@ -7916,7 +7910,6 @@ QUnit.module("Views", (hooks) => {
<field name="bar"/>
</button>`);
// legacySelector = ".oe_stat_button:not(.dropdown-item, .dropdown-toggle)";
const statButtonSelector = ".o-form-buttonbox .oe_stat_button:not(.o-dropdown)";
const formView = await makeView({
@@ -7944,12 +7937,12 @@ QUnit.module("Views", (hooks) => {
);
};
await assertFormContainsNButtonsWithSizeClass(0, 2);
await assertFormContainsNButtonsWithSizeClass(1, 2);
await assertFormContainsNButtonsWithSizeClass(2, 2);
await assertFormContainsNButtonsWithSizeClass(3, 4);
await assertFormContainsNButtonsWithSizeClass(4, 7);
await assertFormContainsNButtonsWithSizeClass(5, 7);
await assertFormContainsNButtonsWithSizeClass(0, 3);
await assertFormContainsNButtonsWithSizeClass(1, 3);
await assertFormContainsNButtonsWithSizeClass(2, 3);
await assertFormContainsNButtonsWithSizeClass(3, 7);
await assertFormContainsNButtonsWithSizeClass(4, 3);
await assertFormContainsNButtonsWithSizeClass(5, 4);
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);
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(
target,
".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 toggleMenuItem(target, "Action Partner");
@@ -8203,7 +8195,7 @@ QUnit.module("Views", (hooks) => {
"My little Foo Value"
);
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 toggleMenuItem(target, "Action Partner");
@@ -9206,11 +9198,11 @@ QUnit.module("Views", (hooks) => {
</form>`,
resId: 1,
});
// Contains invisible buttons that are only displayed under xl screens
assert.containsN(
target,
".o_control_panel button:not(.fa):not(:disabled)",
3,
".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
5,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9221,17 +9213,18 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:not(:disabled)",
".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled"
);
await click(target.querySelector(".o_form_statusbar button"));
await nextTick();
// The unresolved promise lets us check the state of the buttons
assert.containsN(
target,
".o_control_panel button:not(.fa):disabled",
3,
".o_control_panel_breadcrumbs button:not(.fa):disabled",
5,
"control panel buttons should be disabled"
);
assert.containsN(
@@ -9242,7 +9235,7 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:disabled",
".o-form-buttonbox button:disabled",
"stat buttons should be disabled"
);
@@ -9250,8 +9243,8 @@ QUnit.module("Views", (hooks) => {
await nextTick();
assert.containsN(
target,
".o_control_panel button:not(.fa):not(:disabled)",
3,
".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
5,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9262,7 +9255,7 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:not(:disabled)",
".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled"
);
});
@@ -9306,8 +9299,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN(
target,
".o_control_panel button:not(.fa):not(:disabled)",
3,
".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
5,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9318,17 +9311,17 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:not(:disabled)",
".o-form-buttonbox button:not(:disabled)",
"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
assert.containsN(
target,
".o_control_panel button:not(.fa):disabled",
3,
".o_control_panel_breadcrumbs button:not(.fa):disabled",
5,
"control panel buttons should be disabled"
);
assert.containsN(
@@ -9339,16 +9332,16 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:disabled",
".o-form-buttonbox button:disabled",
"stat buttons should be disabled"
);
def.resolve();
await nextTick();
assert.containsN(
target,
".o_control_panel button:not(.fa):not(:disabled)",
3,
".o_control_panel_breadcrumbs button:not(.fa):not(:disabled)",
5,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9359,7 +9352,7 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(
target,
".oe_button_box button:not(:disabled)",
".o-form-buttonbox button:not(:disabled)",
"stat buttons should be enabled"
);
});
@@ -9538,14 +9531,14 @@ QUnit.module("Views", (hooks) => {
});
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"));
assert.ok(target.querySelector(".modal .oe_button_box button").disabled);
await click(target.querySelector(".modal .o-form-buttonbox button"));
assert.ok(target.querySelector(".modal .o-form-buttonbox button").disabled);
def.resolve();
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",
]);
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "bar");
assert.containsN(target, ".o_group_header", 2);
assert.containsNone(target, ".o_data_row");
@@ -10659,7 +10652,7 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
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
onchangeDef = makeDeferred();
@@ -10796,7 +10789,9 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData });
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
await click(target.querySelector(".o_control_panel .o_form_button_save"));
@@ -10832,7 +10827,7 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
await click(target.querySelector(".o_form_button_create"));
await createRecord();
await click(target.querySelector(".o-kanban-button-new"));
assert.containsOnce(target, ".modal");
@@ -11335,29 +11330,29 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1);
await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await click(target.querySelector(`.o_pager button.o_pager_next`));
assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"second record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnersecond record"
);
assert.strictEqual(
target.querySelector('.o_field_widget[name="name"] input').value,
"name"
);
await clickDiscard(target);
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"second record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnersecond record"
);
assert.strictEqual(
target.querySelector('.o_field_widget[name="name"] input').value,
"name"
@@ -11365,10 +11360,10 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(`.o_pager button.o_pager_previous`));
assert.containsOnce(target, ".o_form_saved");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
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 click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
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");
await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
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 click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
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 click(target.querySelector(".o_data_row td.o_data_cell"));
assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
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
await click(target.querySelector(".o_data_row td.o_data_cell"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
assert.strictEqual(
target.querySelector(".o_breadcrumb").textContent,
"Partnerfirst record"
);
// Return in the list view to detach the form view
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
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");
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.strictEqual(
target.querySelector(".o_field_widget[name='foo'] input").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) {
@@ -12141,7 +12139,7 @@ QUnit.module("Views", (hooks) => {
});
await editInput(target, ".o_field_widget[name='foo'] input", "test");
await click(target, ".o_form_button_create");
await createRecord();
assert.verifySteps(["write"]);
await nextTick();
assert.containsOnce(target, ".o_error_dialog");
@@ -12410,7 +12408,7 @@ QUnit.module("Views", (hooks) => {
});
assert.containsOnce(target, ".o_form_readonly");
await click(target.querySelector(".o_form_button_create"));
await createRecord();
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");
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");
await click(target.querySelector(".o_form_view .breadcrumb-item a"));
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");
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.containsNone(target, ".o_view_nocontent");
});
@@ -12756,8 +12754,8 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_form_status_indicator").textContent, "");
await clickSave(target);
assert.strictEqual(
target.querySelector(".o_form_status_indicator").textContent.trim(),
"Unable to save"
target.querySelector(".o_form_status_indicator .text-danger").dataset.tooltip,
"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"));
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");
await click(target, ".modal-footer button.btn-primary");
@@ -13,14 +13,11 @@ import {
editFavoriteName,
saveFavorite,
switchView,
toggleComparisonMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleMenu,
toggleMenuItem,
toggleMenuItemOption,
toggleSaveFavorite,
toggleSearchBarMenu,
validateSearch,
} from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
@@ -2292,7 +2289,7 @@ QUnit.module("Views", (hooks) => {
await toggleMenuItem(target, "Revenue");
assert.strictEqual(getYAxeLabel(graph), "Revenue");
assert.ok(true, "Message");
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color");
checkModeIs(assert, graph, "line");
assert.strictEqual(getXAxeLabel(graph), "Color");
@@ -2459,7 +2456,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "div.o_graph_canvas_container canvas");
assert.containsNone(target, "div.o_view_nocontent");
assert.containsNone(target, ".abc");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain");
assert.containsOnce(target, "div.o_graph_canvas_container canvas");
assert.containsNone(target, "div.o_view_nocontent");
@@ -2484,7 +2481,7 @@ QUnit.module("Views", (hooks) => {
`,
});
checkLabels(assert, graph, ["xphone", "xpad"]);
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color");
checkLabels(assert, graph, ["Undefined", "red"]);
});
@@ -2560,7 +2557,7 @@ QUnit.module("Views", (hooks) => {
`,
});
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "First Favorite");
await saveFavorite(target);
@@ -2568,23 +2565,21 @@ QUnit.module("Views", (hooks) => {
await toggleMenu(target, "Measures");
await toggleMenuItem(target, "Foo");
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Second Favorite");
await saveFavorite(target);
await selectMode(target, "line");
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Third Favorite");
await saveFavorite(target);
await toggleGroupByMenu(target);
await toggleMenuItem(target, "Product");
await toggleMenuItem(target, "Color");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Fourth Favorite");
await saveFavorite(target);
@@ -2751,7 +2746,7 @@ QUnit.module("Views", (hooks) => {
checkLegend(assert, graph, "Count");
assert.strictEqual(getYAxeLabel(graph), "Count");
checkModeIs(assert, graph, "bar");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Context");
checkLegend(assert, graph, "Foo");
assert.strictEqual(getYAxeLabel(graph), "Foo");
@@ -2780,7 +2775,7 @@ QUnit.module("Views", (hooks) => {
</search>
`,
});
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain");
});
@@ -2812,7 +2807,7 @@ QUnit.module("Views", (hooks) => {
checkDatasets(assert, graph, "data", { data: [82, 157] });
assert.strictEqual(getXAxeLabel(graph), "Product");
assert.strictEqual(getYAxeLabel(graph), "Foo");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain");
checkLabels(assert, graph, []);
checkLegend(assert, graph, []);
@@ -2908,9 +2903,7 @@ QUnit.module("Views", (hooks) => {
});
await toggleMenu(target, "Measures");
assert.deepEqual(
[...target.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map(
(el) => el.innerText
),
[...target.querySelectorAll(".o-dropdown .o_menu_item")].map((el) => el.innerText),
["Foo", "Revenue", "Count"]
);
});
@@ -2953,9 +2946,7 @@ QUnit.module("Views", (hooks) => {
});
await toggleMenu(target, "Measures");
assert.deepEqual(
[...target.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map(
(el) => el.innerText
),
[...target.querySelectorAll(".o-dropdown .o_menu_item")].map((el) => el.innerText),
["Bouh", "Foo", "Revenue", "Count"]
);
}
@@ -3122,7 +3113,7 @@ QUnit.module("Views", (hooks) => {
views: [[false, "graph"]],
});
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item.active").innerText,
target.querySelector(".o_control_panel .o_breadcrumb .active:first-child").innerText,
"Glou glou"
);
});
@@ -3619,7 +3610,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_view_nocontent");
assert.containsOnce(target, ".o_graph_canvas_container canvas");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain");
assert.doesNotHaveClass(
@@ -3652,7 +3643,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, ".o_graph_canvas_container canvas");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "False Domain");
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"]);
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Foo");
checkLabels(assert, graph, ["xphone", "xpad"]);
}
@@ -3786,7 +3777,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
checkDatasets(assert, graph, ["data", "label"], {
@@ -3842,7 +3833,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
checkDatasets(assert, graph, ["data", "label"], {
@@ -3899,7 +3890,7 @@ QUnit.module("Views", (hooks) => {
checkDatasets(assert, graph, "data", { data: [82, 157] });
def = makeDeferred();
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Color");
await toggleMenuItem(target, "Color");
await toggleMenuItem(target, "Date");
@@ -3984,7 +3975,7 @@ QUnit.module("Views", (hooks) => {
`,
});
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
checkLabels(assert, graph, ["", ""]);
@@ -4018,7 +4009,7 @@ QUnit.module("Views", (hooks) => {
`,
});
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
checkDatasets(assert, graph, "backgroundColor", {
@@ -4075,7 +4066,7 @@ QUnit.module("Views", (hooks) => {
checkLabels(assert, graph, ["Q1 2016", "Q2 2016", "Undefined"]);
checkLegend(assert, graph, "Count");
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite");
checkModeIs(assert, graph, "bar");
@@ -19,12 +19,12 @@ import {
triggerHotkey,
} from "@web/../tests/helpers/utils";
import {
getButtons,
getVisibleButtons,
getFacetTexts,
getPagerLimit,
getPagerValue,
pagerNext,
toggleFilterMenu,
toggleSearchBarMenu,
validateSearch,
} from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
@@ -104,7 +104,7 @@ function getTooltips(groupIndex) {
// Record
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) {
@@ -432,7 +432,7 @@ QUnit.module("Views", (hooks) => {
});
QUnit.test("basic grouped rendering", async (assert) => {
assert.expect(14);
assert.expect(13);
await makeView({
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_renderer"), "o_kanban_grouped");
assert.containsN(target, ".o_kanban_group", 2);
@@ -712,7 +706,7 @@ QUnit.module("Views", (hooks) => {
[...target.querySelectorAll(".o_kanban_group")].map((el) =>
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));
@@ -1600,7 +1594,7 @@ QUnit.module("Views", (hooks) => {
assert.containsN(target, ".o_kanban_group", 2);
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.verifySteps(["create record"]);
@@ -1622,7 +1616,10 @@ QUnit.module("Views", (hooks) => {
});
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");
await createRecord();
@@ -1996,7 +1993,7 @@ QUnit.module("Views", (hooks) => {
groupBy: ["bar"],
});
await click(target, ".o-kanban-button-new");
await createRecord();
assert.strictEqual(
document.activeElement,
target.querySelector(".o_field_widget[name=int_field] input")
@@ -2027,7 +2024,7 @@ QUnit.module("Views", (hooks) => {
groupBy: ["bar"],
});
await click(target, ".o-kanban-button-new");
await createRecord();
assert.strictEqual(
document.activeElement,
target.querySelector(".o_field_widget[name=foo] input")
@@ -5482,7 +5479,7 @@ QUnit.module("Views", (hooks) => {
assert.deepEqual(getFacetTexts(target), []);
// validate presence of the search arch info
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
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.strictEqual(
getColumn(0).querySelector(".o_column_title").innerText,
"None (2)",
"None\n2",
"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.deepEqual(
[...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 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) => {
@@ -11373,7 +11373,7 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps([]);
await click(target, ".o-kanban-button-new");
await createRecord();
assert.verifySteps(["create record"]);
assert.containsNone(target, ".o_kanban_quick_create");
@@ -11457,7 +11457,7 @@ QUnit.module("Views", (hooks) => {
);
assert.verifySteps([]);
await click(target, ".o-kanban-button-new");
await createRecord();
assert.verifySteps(["create record"]);
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");
assert.containsOnce(target, ".dropdown-menu");
assert.containsOnce(target, ".o_content .dropdown-menu");
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) => {
@@ -12276,13 +12276,13 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2);
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");
assert.containsN(getColumn(0), ".o_kanban_record", 1);
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) => {
@@ -12310,13 +12310,13 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2);
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");
assert.containsN(getColumn(0), ".o_kanban_record", 1);
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) => {
@@ -12356,7 +12356,7 @@ QUnit.module("Views", (hooks) => {
assert.containsN(getColumn(0), ".o_kanban_record", 2);
assert.hasClass(getColumn(1), "o_column_folded");
assert.strictEqual(getColumn(1).innerText, "Yes (2)");
assert.strictEqual(getColumn(1).innerText, "Yes\n2");
await dragAndDrop(
".o_kanban_group:first-child .o_kanban_record",
@@ -12364,7 +12364,7 @@ QUnit.module("Views", (hooks) => {
);
assert.containsOnce(getColumn(0), ".o_kanban_record");
assert.strictEqual(getColumn(1).innerText, "Yes (3)");
assert.strictEqual(getColumn(1).innerText, "Yes\n3");
assert.deepEqual(
getProgressBars(0).map((pb) => pb.style.width),
["100%"]
@@ -12575,8 +12575,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN(target, ".o_column_folded", 2);
assert.strictEqual(
getNodesTextContent(target.querySelectorAll("span.o_column_title")).join(" "),
"hello (2) xmo (2)"
getNodesTextContent(target.querySelectorAll(".o_column_title")).join(" "),
"hello2 xmo2"
);
assert.containsNone(target, ".o_nocontent_help");
@@ -13084,10 +13084,10 @@ QUnit.module("Views", (hooks) => {
},
});
const cpButtons = getButtons(target);
const cpButtons = getVisibleButtons(target);
assert.deepEqual(
[...cpButtons].map((button) => button.textContent.trim()),
["New", "display"]
["New", "display", ""]
);
assert.hasClass(cpButtons[1], "display");
+12 -12
View File
@@ -70,7 +70,7 @@ QUnit.module("Views", (hooks) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout display="props.display">
<t t-set-slot="control-panel-top-right">
<t t-set-slot="layout-actions">
<div class="toy_search_bar" />
</t>
<div class="toy_content" />
@@ -84,7 +84,7 @@ QUnit.module("Views", (hooks) => {
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.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content");
@@ -106,7 +106,7 @@ QUnit.module("Views", (hooks) => {
}
ToyComponent.template = xml`
<Layout className="'o_view_sample_data'" display="{
controlPanel: { 'top-right': false, 'bottom-right': false, 'bottom-left': false },
controlPanel: {},
searchPanel: true,
}">
<div class="toy_content" />
@@ -122,7 +122,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_search_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_content > .toy_content");
});
@@ -159,7 +159,7 @@ QUnit.module("Views", (hooks) => {
}
ToyB.template = xml`
<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" />
</t>
<ToyC/>
@@ -170,7 +170,7 @@ QUnit.module("Views", (hooks) => {
class ToyA extends Component {}
ToyA.template = xml`
<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" />
</t>
<ToyB display="props.display"/>
@@ -291,21 +291,21 @@ QUnit.module("Views", (hooks) => {
});
QUnit.test("Simple rendering: with dynamically displayed search", async (assert) => {
let displayControlPanelTopRight = true;
let displayLayoutActions = true;
class ToyComponent extends Component {
get display() {
return {
...this.props.display,
controlPanel: {
...this.props.display.controlPanel,
"top-right": displayControlPanelTopRight,
layoutActions: displayLayoutActions,
},
};
}
}
ToyComponent.template = xml`
<Layout display="display">
<t t-set-slot="control-panel-top-right">
<t t-set-slot="layout-actions">
<div class="toy_search_bar" />
</t>
<div class="toy_content" />
@@ -319,16 +319,16 @@ QUnit.module("Views", (hooks) => {
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.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content");
displayControlPanelTopRight = false;
displayLayoutActions = false;
comp.render();
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.containsNone(target, ".o_cp_searchview");
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,
setupControlPanelServiceRegistry,
toggleAddCustomGroup,
toggleComparisonMenu,
toggleFavoriteMenu,
toggleFilterMenu,
toggleGroupByMenu,
toggleSearchBarMenu,
toggleMenu,
toggleMenuItem,
toggleMenuItemOption,
@@ -265,9 +262,9 @@ QUnit.module("Views", (hooks) => {
</pivot>`,
});
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle"));
await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item").innerText,
target.querySelector(".o_pivot_buttons .dropdown-menu .dropdown-item").innerText,
"BAR"
);
assert.strictEqual(
@@ -366,9 +363,9 @@ QUnit.module("Views", (hooks) => {
// there should be only one displayed measure as the other one is invisible
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
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
await click(target.querySelector(".o_pivot_header_cell_closed"));
assert.containsNone(target, '.dropdown-menu a[data-field="foo2"]');
@@ -432,10 +429,10 @@ QUnit.module("Views", (hooks) => {
</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-menu .dropdown-item:contains(Computed and not stored)"
".o_pivot_buttons .dropdown-menu .dropdown-item:contains(Computed and not stored)"
);
assert.strictEqual(
target.querySelector(".o_pivot_measure_row").innerText,
@@ -580,7 +577,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true },
});
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
// hover Count in first group
@@ -648,7 +645,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true },
});
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
// hover the second origin in second group
@@ -773,7 +770,7 @@ QUnit.module("Views", (hooks) => {
context: { search_default_date_filter: true },
});
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
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"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu .dropdown-item");
const measure = target.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item");
await click(target.querySelector(".o_pivot_buttons .dropdown-toggle"));
assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu .dropdown-item");
const measure = target.querySelector(".o_pivot_buttons .dropdown-menu .dropdown-item");
assert.strictEqual(measure.innerText, "Count");
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");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter");
assert.containsOnce(
target,
@@ -1064,16 +1061,16 @@ QUnit.module("Views", (hooks) => {
});
// open group by dropdown
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsN(
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,
"should have 3 dropdown items in searchview groupby"
);
assert.containsOnce(
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"
);
@@ -1129,10 +1126,10 @@ QUnit.module("Views", (hooks) => {
});
// open group by dropdown
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsN(
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,
"should have 2 dropdown items in searchview groupby"
);
@@ -1147,12 +1144,12 @@ QUnit.module("Views", (hooks) => {
);
// add a custom group in searchview groupby
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
await applyGroup(target);
assert.containsN(
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,
"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
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsN(
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,
"should still have 3 dropdown items in searchview groupby dropdown"
);
@@ -1208,10 +1205,10 @@ QUnit.module("Views", (hooks) => {
});
// open group by dropdown
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsN(
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,
"should have 2 dropdown items in searchview groupby"
);
@@ -1219,7 +1216,7 @@ QUnit.module("Views", (hooks) => {
await applyGroup(target);
assert.containsN(
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,
"should have 3 dropdown items in searchview groupby now"
);
@@ -1333,15 +1330,15 @@ QUnit.module("Views", (hooks) => {
});
// open group by dropdown
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsNone(
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"
);
assert.containsOnce(
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"
);
// click on closed header to open dropdown
@@ -1403,15 +1400,15 @@ QUnit.module("Views", (hooks) => {
});
// open group by dropdown
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
assert.containsOnce(
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"
);
assert.containsNone(
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"
);
@@ -1497,16 +1494,16 @@ QUnit.module("Views", (hooks) => {
"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(
$(target).find(".dropdown-item:contains(Count)"),
"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(
$(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)"),
$(target).find(".o_pivot_buttons .dropdown-item:contains(Count)"),
"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");
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(
$(target).find(".dropdown-item:contains(Count)")[0],
@@ -1545,8 +1542,8 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, "table");
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle"));
await click($(target).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]);
await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
await click($(target).find(".o_pivot_buttons .dropdown-item:contains(Count)")[0]);
assert.containsOnce(target, ".o_view_nocontent");
assert.containsNone(target, "table");
@@ -1567,7 +1564,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent");
assert.containsOnce(target, "table");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter");
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_view_nocontent");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter");
assert.containsN(target, ".o_searchview .o_searchview_facet", 2);
assert.containsOnce(target, ".o_view_nocontent");
@@ -1659,7 +1656,7 @@ QUnit.module("Views", (hooks) => {
"should have 1 row for measure Foo"
);
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
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, "tbody tr", "should have 1 rows");
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product");
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
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Month");
nbReadGroups = 0;
@@ -1835,7 +1832,7 @@ QUnit.module("Views", (hooks) => {
});
// expand on date:days, product
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "Month");
await toggleMenuItem(target, "Product");
@@ -1963,7 +1960,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav1");
await saveFavorite(target);
@@ -1977,7 +1974,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav2");
await saveFavorite(target);
@@ -1991,7 +1988,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav3");
await saveFavorite(target);
@@ -2051,7 +2048,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "1");
await saveFavorite(target);
@@ -2064,7 +2061,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "2");
await saveFavorite(target);
@@ -2078,7 +2075,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "3");
await saveFavorite(target);
@@ -2092,7 +2089,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "4");
await saveFavorite(target);
@@ -2106,7 +2103,7 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["foo"],
pivot_row_groupby: ["product_id"],
};
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "5");
await saveFavorite(target);
@@ -2139,7 +2136,7 @@ QUnit.module("Views", (hooks) => {
);
// Apply both groupbys
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product");
assert.strictEqual(
target.querySelector("tbody .o_pivot_header_cell_closed").textContent,
@@ -2198,7 +2195,7 @@ QUnit.module("Views", (hooks) => {
);
// Apply BAR groupbys
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bar");
assert.strictEqual(
target.querySelector("tbody .o_pivot_header_cell_closed").textContent,
@@ -2317,7 +2314,7 @@ QUnit.module("Views", (hooks) => {
);
// activate the unique existing favorite
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0);
assert.strictEqual(
@@ -2358,7 +2355,7 @@ QUnit.module("Views", (hooks) => {
);
// activate AGAIN the unique existing favorite
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0);
assert.strictEqual(
@@ -2446,7 +2443,7 @@ QUnit.module("Views", (hooks) => {
);
// Equivalent to unload the filter
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite");
// collapse all headers
await click(target, ".o_pivot_header_cell_opened:first-child");
@@ -2488,7 +2485,7 @@ QUnit.module("Views", (hooks) => {
// Equivalent to load another filter
await removeFacet(target); // remove previously saved favorite
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite 2");
// Check Columns
@@ -2553,7 +2550,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("thead .dropdown-item")[1]);
// Set a domain
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 1");
// Save to favorites and check that column groupbys were not lost
@@ -2563,7 +2560,6 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["__count"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 1");
await saveFavorite(target);
@@ -2574,7 +2570,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]);
// Set a domain
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 2");
expectedContext = {
@@ -2583,7 +2579,6 @@ QUnit.module("Views", (hooks) => {
pivot_measures: ["__count"],
pivot_row_groupby: [],
};
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 2");
await saveFavorite(target);
@@ -2626,7 +2621,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(getCurrentValues(target), values.join(","));
// reload (should keep folded groups folded as col/row groupbys didn't change)
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Dummy Filter");
assert.strictEqual(getCurrentValues(target), values.join(","));
@@ -2692,11 +2687,10 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "table");
// Set a domain for empty results
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 1");
assert.containsNone(target, "table");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 1");
await saveFavorite(target);
@@ -2705,11 +2699,10 @@ QUnit.module("Views", (hooks) => {
await removeFacet(target); // remove previously saved favorite
assert.containsOnce(target, "table");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter 2");
assert.containsOnce(target, "table");
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite 2");
await saveFavorite(target);
@@ -2807,7 +2800,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelectorAll(".o_pivot_cell_value")[4].innerText, ""); // xphone December 2016
// 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_closed"));
await click(target.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]);
@@ -2847,7 +2840,7 @@ QUnit.module("Views", (hooks) => {
);
// select filter "Bayou" in control panel
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou");
assert.deepEqual(
@@ -2889,7 +2882,7 @@ QUnit.module("Views", (hooks) => {
);
// select filter "Bayou" in control panel
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou");
assert.deepEqual(
@@ -2906,7 +2899,7 @@ QUnit.module("Views", (hooks) => {
);
// unselect filter "Bayou" in control panel
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bayou");
assert.deepEqual(
@@ -2964,7 +2957,7 @@ QUnit.module("Views", (hooks) => {
"the active measure should be amount"
);
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My fake favorite");
assert.containsOnce(
@@ -3145,13 +3138,13 @@ QUnit.module("Views", (hooks) => {
},
});
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-item");
await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.containsOnce(target, ".o_pivot_buttons .dropdown-item");
assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-item").innerText,
target.querySelector(".o_pivot_buttons .dropdown-item").innerText,
"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) {
@@ -3167,13 +3160,13 @@ QUnit.module("Views", (hooks) => {
<field name="date" interval="month" type="col"/>
</pivot>`,
});
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-item");
await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.containsOnce(target, ".o_pivot_buttons .dropdown-item");
assert.strictEqual(
target.querySelector(".o_cp_bottom_left .dropdown-item").innerText,
target.querySelector(".o_pivot_buttons .dropdown-item").innerText,
"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) {
@@ -3261,7 +3254,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelectorAll("tbody .dropdown-item")[4]);
// Add a filter
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Some Filter");
assert.containsOnce(
@@ -3276,7 +3269,6 @@ QUnit.module("Views", (hooks) => {
);
// Save current search to favorite
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "My favorite");
await saveFavorite(target);
@@ -3312,7 +3304,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "tbody tr", "should have 1 row initially");
def = makeDeferred();
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Product");
await toggleMenuItem(target, "Customer");
@@ -3361,9 +3353,9 @@ QUnit.module("Views", (hooks) => {
</pivot>`,
});
await click(target.querySelector(".o_cp_bottom_left button.dropdown-toggle"));
await click(target.querySelector(".o_pivot_buttons button.dropdown-toggle"));
assert.strictEqual(
[...target.querySelectorAll(".o_cp_bottom_left .dropdown-item")]
[...target.querySelectorAll(".o_pivot_buttons .dropdown-item")]
.map((i) => i.innerText)
.join(""),
"bouhFoomoddZipCount"
@@ -3479,12 +3471,11 @@ QUnit.module("Views", (hooks) => {
});
// with no data
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
assert.containsOnce(target, "p.o_view_nocontent_empty_folder");
await toggleFilterMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "December");
await toggleMenuItemOption(target, "Date", "2016");
@@ -3530,10 +3521,10 @@ QUnit.module("Views", (hooks) => {
];
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_cp_bottom_left .dropdown-menu .dropdown-item")[1]);
await click(target.querySelectorAll(".o_pivot_buttons .dropdown-menu .dropdown-item")[0]);
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%"];
assert.strictEqual(getCurrentValues(target), values.join());
@@ -3541,7 +3532,7 @@ QUnit.module("Views", (hooks) => {
values = ["2", "2", "0%", "2", "1", "-50%", "0", "1", "100%"];
assert.strictEqual(getCurrentValues(target), values.join());
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Fav");
await saveFavorite(target);
@@ -3596,7 +3587,7 @@ QUnit.module("Views", (hooks) => {
});
// open comparison menu
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
// compare October 2016 to September 2016
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");
// export data should be impossible since the pivot buttons
// 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 toggleMenuItemOption(target, "Date", "December");
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.
// 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([
// col group headers
@@ -3673,7 +3663,7 @@ QUnit.module("Views", (hooks) => {
mockMock = true;
// compare December 2016 to November 2016
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
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
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
// initial sanity check
@@ -3968,21 +3958,21 @@ QUnit.module("Views", (hooks) => {
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
await click(target.querySelector(".o_cp_bottom_left .dropdown-toggle"));
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu");
await click(target.querySelector(".o_pivot_buttons .dropdown-toggle"));
assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu");
// 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
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
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
assert.containsOnce(target, ".o_cp_bottom_left .dropdown-menu");
assert.containsOnce(target, ".o_pivot_buttons .dropdown-menu");
});
QUnit.test(
@@ -4038,7 +4028,7 @@ QUnit.module("Views", (hooks) => {
views: [[false, "pivot"]],
});
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, 0);
await nextTick();
@@ -4090,7 +4080,7 @@ QUnit.module("Views", (hooks) => {
});
// compare December 2016 to November 2016
await toggleComparisonMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date: Previous period");
// initial sanity check
@@ -4237,12 +4227,11 @@ QUnit.module("Views", (hooks) => {
);
// Filter on December 2016
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "December");
// compare December 2016 to November 2016
await toggleComparisonMenu(target);
await toggleMenuItem(target, "Date: Previous period");
assert.deepEqual(
@@ -4384,7 +4373,7 @@ QUnit.module("Views", (hooks) => {
);
// open group by menu and add new groupby
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
await applyGroup(target);
@@ -4415,7 +4404,7 @@ QUnit.module("Views", (hooks) => {
);
// open groupby menu generator and add a new groupby
await toggleGroupByMenu(target);
await toggleSearchBarMenu(target);
await toggleAddCustomGroup(target);
await selectGroup(target, "bar");
await applyGroup(target);
@@ -4648,7 +4637,7 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_view_nocontent .abc");
assert.containsOnce(target, "table");
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Small Than 0");
assert.doesNotHaveClass(target, "o_view_sample_data");
@@ -4911,7 +4900,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), values.join(","));
@@ -4951,7 +4940,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -4992,7 +4981,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5033,7 +5022,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5079,7 +5068,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "12", "20"].join(","));
@@ -5122,7 +5111,7 @@ QUnit.module("Views", (hooks) => {
// Set a domain (this reload is delayed)
def = makeDeferred();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My Filter");
assert.strictEqual(getCurrentValues(target), ["32", "12", "20"].join(","));
@@ -5215,13 +5204,13 @@ QUnit.module("Views", (hooks) => {
// "Count" is the only measure available
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
),
["Count"]
);
// 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(
@@ -5257,11 +5246,10 @@ QUnit.module("Views", (hooks) => {
});
// compare 2021 to 2020
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Date");
await toggleMenuItemOption(target, "Date", "2021");
await toggleComparisonMenu(target);
await toggleMenuItem(target, 0);
await toggleMenuItem(target.querySelector(".o_comparison_menu"), 0);
assert.deepEqual(
[...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"
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite");
await saveFavorite(target);
@@ -5352,7 +5340,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected"
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite");
assert.deepEqual(
@@ -5361,7 +5349,6 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected"
);
await toggleGroupByMenu(target);
await toggleMenuItem(target, "Customer");
assert.deepEqual(
@@ -5380,7 +5367,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected"
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite 2");
await saveFavorite(target);
@@ -5429,7 +5416,7 @@ QUnit.module("Views", (hooks) => {
"The row headers should be as expected"
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Favorite");
assert.deepEqual(
@@ -5492,7 +5479,7 @@ QUnit.module("Views", (hooks) => {
["Total", "", "No", "Yes", "Computed and not stored"]
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "My favorite 2");
assert.deepEqual(
@@ -5554,7 +5541,7 @@ QUnit.module("Views", (hooks) => {
["Total", "Computed and not stored"]
);
await toggleFavoriteMenu(target);
await toggleSearchBarMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "Favorite");
await saveFavorite(target);
@@ -19,6 +19,11 @@ import { makeFakeUserService } from "../../helpers/mock_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) => {
let serverData;
let target;
@@ -947,7 +952,7 @@ QUnit.module("ViewDialogs", (hooks) => {
domain: [["bar", "!=", "glou"]],
});
await click(target.querySelector(".o_list_export_xlsx"));
await exportAllAction(target);
});
QUnit.test("Direct export grouped list ", async function (assert) {
@@ -999,7 +1004,7 @@ QUnit.module("ViewDialogs", (hooks) => {
domain: [["bar", "!=", "glou"]],
});
await click(target.querySelector(".o_list_export_xlsx"));
await exportAllAction(target);
});
QUnit.test("Export dialog with duplicated fields", async function (assert) {
@@ -19,8 +19,7 @@ import {
editFavoriteName,
removeFacet,
saveFavorite,
toggleFavoriteMenu,
toggleFilterMenu,
toggleSearchBarMenu,
toggleMenuItem,
toggleSaveFavorite,
} from "@web/../tests/search/helpers";
@@ -401,13 +400,12 @@ QUnit.module("ViewDialogs", (hooks) => {
assert.containsN(target, ".o_data_row", 3, "should contain 3 records");
// filter on bar
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Bar");
assert.containsN(target, ".o_data_row", 2, "should contain 2 records");
// save filter
await toggleFavoriteMenu(target);
await toggleSaveFavorite(target);
await editFavoriteName(target, "some name");
await saveFavorite(target);
@@ -430,7 +430,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target, ".my_owl_action");
await doAction(webClient, 3);
assert.strictEqual(
target.querySelector(".breadcrumb").textContent,
target.querySelector(".o_breadcrumb").textContent,
"Favorite PoniesnewOwlTitlePartners"
);
});
@@ -3,14 +3,16 @@
import {
click,
getFixture,
getNodesTextContent,
legacyExtraNextTick,
makeDeferred,
nextTick,
} from "@web/../tests/helpers/utils";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { SearchBar } from "@web/search/search_bar/search_bar";
import {
isItemSelected,
toggleFilterMenu,
toggleSearchBarMenu,
toggleMenuItem,
switchView,
} from "@web/../tests/search/helpers";
@@ -26,6 +28,10 @@ import {
import { Component, xml } from "@odoo/owl";
const actionRegistry = registry.category("actions");
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData;
let target;
@@ -109,12 +115,7 @@ QUnit.module("ActionManager", (hooks) => {
doAction(webClient, 4);
def.resolve();
await nextTick();
await legacyExtraNextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
});
QUnit.test("clicking quickly on breadcrumbs...", async function (assert) {
@@ -140,11 +141,7 @@ QUnit.module("ActionManager", (hooks) => {
// resolve the form view read
def.resolve();
await nextTick();
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Partners Action 4",
"action 4 should be loaded and visible"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
});
QUnit.test(
@@ -335,11 +332,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4");
assert.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -370,11 +363,7 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick();
assert.containsOnce(target, ".o_kanban_view", "should display the kanban view of action 4");
assert.containsNone(target, ".o_list_view", "should not display the list view of action 3");
assert.containsOnce(
target,
".o_control_panel .breadcrumb-item",
"there should be one controller in the breadcrumbs"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -398,12 +387,12 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
assert.containsOnce(target, ".o_list_view");
assert.containsN(target, ".o_list_view .o_data_row", 5);
assert.containsOnce(target, ".o_control_panel .o_list_buttons");
assert.containsOnce(target, ".o_control_panel .d-none.d-xl-inline-flex .o_list_buttons");
// reload (the search_read RPC will be blocked)
def = makeDeferred();
await switchView(target, "list");
assert.containsN(target, ".o_list_view .o_data_row", 5);
assert.containsOnce(target, ".o_control_panel .o_list_buttons");
assert.containsOnce(target, ".o_control_panel .d-none.d-xl-inline-flex .o_list_buttons");
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
@@ -468,10 +457,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_list_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_form_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -505,10 +491,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -540,10 +523,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -575,10 +555,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Partners"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
assert.containsNone(target, ".o_list_view");
assert.verifySteps([
"/web/webclient/load_menus",
@@ -616,18 +593,12 @@ QUnit.module("ActionManager", (hooks) => {
await click(row1.querySelector(".o_data_cell"));
await click(row2.querySelector(".o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
target.querySelector(".breadcrumb-item.active").innerText,
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
});
QUnit.test("local state, global state, and race conditions", async function (assert) {
@@ -659,15 +630,15 @@ QUnit.module("ActionManager", (hooks) => {
ToyController.template = xml`
<div class="o_toy_view">
<ControlPanel />
<SearchBar />
</div>`;
ToyController.components = { ControlPanel };
ToyController.components = { ControlPanel, SearchBar };
registry.category("views").add("toy", {
type: "toy",
display_name: "Toy",
icon: "fab fa-android",
multiRecord: true,
searchMenuTypes: ["filter"],
Controller: ToyController,
});
@@ -683,7 +654,7 @@ QUnit.module("ActionManager", (hooks) => {
],
});
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Foo");
assert.ok(isItemSelected(target, "Foo"));
@@ -695,7 +666,7 @@ QUnit.module("ActionManager", (hooks) => {
def.resolve();
await nextTick();
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
assert.ok(isItemSelected(target, "Foo"));
// this test is not able to detect that getGlobalState is put on the right place:
// currentController.action.globalState contains in any case the search state
@@ -33,7 +33,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, "1");
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partners Action 1");
assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partners Action 1");
assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"]
@@ -46,7 +46,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.ok(e.cause instanceof TypeError);
}
assert.containsOnce(target, ".o_kanban_view");
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Partners Action 1");
assert.strictEqual(target.querySelector(".o_breadcrumb").textContent, "Partners Action 1");
assert.deepEqual(
[...target.querySelectorAll(".o_kanban_record span")].map((el) => el.textContent),
["yop", "blip", "gnap", "plop", "zoup"]
@@ -17,8 +17,9 @@ import {
nextTick,
makeDeferred,
editInput,
getNodesTextContent,
} from "../../helpers/utils";
import { pagerNext, toggleFilterMenu, toggleMenuItem } from "@web/../tests/search/helpers";
import { pagerNext, toggleMenuItem, toggleSearchBarMenu } from "@web/../tests/search/helpers";
import { session } from "@web/session";
import {
createWebClient,
@@ -31,6 +32,10 @@ import { errorService } from "@web/core/errors/error_service";
import { Component, xml } from "@odoo/owl";
function getBreadCrumbTexts(target) {
return getNodesTextContent(target.querySelectorAll(".breadcrumb-item, .o_breadcrumb .active"));
}
let serverData;
let target;
@@ -233,13 +238,8 @@ QUnit.module("ActionManager", (hooks) => {
model: "partner",
});
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
});
@@ -261,11 +261,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.nextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Second record",
"should have opened the second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
assert.containsNone(target, ".o_menu_brand");
assert.verifySteps(["/web/webclient/load_menus", "get_views", "read"]);
});
@@ -318,7 +314,7 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test(
"lazy load multi record view if mono record one is requested",
async function (assert) {
assert.expect(12);
assert.expect(11);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -332,15 +328,9 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsNone(target, ".o_list_view");
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".o_control_panel .breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Second record",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Second record"]);
// go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_list_view");
assert.containsNone(target, ".o_form_view");
assert.verifySteps([
@@ -354,48 +344,21 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("lazy load multi record view with previous action", async function (assert) {
assert.expect(6);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 4);
assert.containsOnce(
target,
".o_control_panel .breadcrumb li",
"there should be one controller in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4",
"breadcrumbs should contain the display_name of the opened record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
await doAction(webClient, 3, {
props: { resId: 2 },
viewType: "form",
});
assert.containsN(
target,
".o_control_panel .breadcrumb li",
3,
"there should be three controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4PartnersSecond record",
"the breadcrumb elements should be correctly ordered"
);
assert.deepEqual(getBreadCrumbTexts(target), [
"Partners Action 4",
"Partners",
"Second record",
]);
// go back to List
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:last"));
await legacyExtraNextTick();
assert.containsN(
target,
".o_control_panel .breadcrumb li",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb li").text(),
"Partners Action 4Partners",
"the breadcrumb elements should be correctly ordered"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4", "Partners"]);
});
QUnit.test(
@@ -421,7 +384,7 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("change the viewType of the current action", async function (assert) {
assert.expect(14);
assert.expect(13);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -447,17 +410,7 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsNone(target, ".o_kanban_view");
assert.containsOnce(target, ".o_form_view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Fourth record",
"should have opened the requested record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
// verify steps to ensure that the whole action hasn't been re-executed
// (if it would have been, /web/action/load and get_views would appear
// several times)
@@ -472,7 +425,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("change the id of the current action", async function (assert) {
assert.expect(12);
assert.expect(11);
const mockRPC = async function (route, args) {
assert.step((args && args.method) || route);
};
@@ -480,13 +433,8 @@ QUnit.module("ActionManager", (hooks) => {
// execute action 3 and open the first record in a form view
await doAction(webClient, 3);
await testUtils.dom.click($(target).find(".o_list_view .o_data_cell:first"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"First record",
"should have opened the first record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "First record"]);
// switch to record 4
webClient.env.bus.trigger("test:hashchange", {
action: 3,
@@ -494,19 +442,8 @@ QUnit.module("ActionManager", (hooks) => {
view_type: "form",
});
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
2,
"there should be two controllers in the breadcrumbs"
);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item:last").text(),
"Fourth record",
"should have switched to the requested record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners", "Fourth record"]);
// verify steps to ensure that the whole action hasn't been re-executed
// (if it would have been, /web/action/load and get_views would appear
// twice)
@@ -699,20 +636,12 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 4);
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
await loadState(webClient, {
model: "partner",
view_type: "list",
});
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 4",
"should still be in the same action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 4"]);
assert.containsNone(target, ".o_kanban_view", "should no longer display a kanban view");
assert.containsOnce(target, ".o_list_view", "should display a list view");
assert.verifySteps([
@@ -742,11 +671,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await loadState(webClient, { menu_id: 666 });
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1",
"breadcrumbs should display the display_name of the action"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -762,21 +687,14 @@ QUnit.module("ActionManager", (hooks) => {
1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1 },
};
const webClient = await createWebClient({ serverData });
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
await loadState(webClient, { action: 3 });
assert.containsOnce(target, ".o_list_view"); // action 3
assert.strictEqual($(target).find(".o_control_panel .breadcrumb-item").text(), "Partners");
assert.deepEqual(getBreadCrumbTexts(target), ["Partners"]);
await loadState(webClient, { home: 1 });
assert.containsOnce(target, ".o_kanban_view"); // action 1 (default app)
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
});
QUnit.test("load state supports #home as initial state", async function (assert) {
@@ -793,10 +711,7 @@ QUnit.module("ActionManager", (hooks) => {
await createWebClient({ serverData, mockRPC });
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view", "should display a kanban view");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
"Partners Action 1"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partners Action 1"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -806,7 +721,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("load state: in a form view, remove the id from the state", async function (assert) {
assert.expect(13);
assert.expect(11);
serverData.actions[999] = {
id: 999,
name: "Partner",
@@ -823,11 +738,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999, { viewType: "form", props: { resId: 2 } });
assert.containsOnce(target, ".o_form_view");
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"Second record"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "Second record"]);
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -841,11 +752,7 @@ QUnit.module("ActionManager", (hooks) => {
});
assert.verifySteps(["/web/dataset/call_kw/partner/onchange"]);
assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.containsN(target, ".breadcrumb-item", 2);
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item.active").text(),
"New"
);
assert.deepEqual(getBreadCrumbTexts(target), ["Partner", "New"]);
});
QUnit.test("hashchange does not trigger canberemoved right away", async function (assert) {
@@ -957,11 +864,10 @@ QUnit.module("ActionManager", (hooks) => {
});
await click(target.querySelector(".o_control_panel .breadcrumb-item"));
await legacyExtraNextTick();
assert.containsN(target, ".o_list_view .o_data_row", 5);
await toggleFilterMenu(target);
await toggleSearchBarMenu(target);
await toggleMenuItem(target, "Filter");
assert.containsN(target, ".o_list_view .o_data_row", 1);
@@ -982,18 +888,18 @@ QUnit.module("ActionManager", (hooks) => {
},
{ props: { resIds: [1, 2] } }
);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "First record");
assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
await pagerNext(target);
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "Second record");
assert.deepEqual(getBreadCrumbTexts(target), ["Second record"]);
await editInput(target, "[name=display_name] input", "new name");
// without saving we now make a loadState which should commit changes
await loadState(webClient, { action: 1337, id: 1, model: "partner", view_type: "form" });
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "First record");
assert.deepEqual(getBreadCrumbTexts(target), ["First record"]);
// loadState again just to check if changes were commited
await loadState(webClient, { action: 1337, id: 2, model: "partner", view_type: "form" });
assert.strictEqual(target.querySelector(".breadcrumb").textContent, "new name");
assert.deepEqual(getBreadCrumbTexts(target), ["new name"]);
});
QUnit.test("initial action crashes", async (assert) => {
@@ -5,7 +5,6 @@ import { registry } from "@web/core/registry";
import { session } from "@web/session";
import AbstractAction from "web.AbstractAction";
import core from "web.core";
import testUtils from "web.test_utils";
import { makeTestEnv } from "../../helpers/mock_env";
import {
click,
@@ -207,10 +206,10 @@ QUnit.module("ActionManager", (hooks) => {
serverData.actions[4].context = { no_breadcrumbs: true };
const webClient = await createWebClient({ serverData });
await doAction(webClient, 3);
assert.containsOnce(target, ".o_control_panel .breadcrumb-item");
assert.containsOnce(target, ".o_control_panel .o_breadcrumb");
// push another action flagged with 'no_breadcrumbs=true'
await doAction(webClient, 4);
assert.containsNone(target, ".o_control_panel .breadcrumb-item");
assert.containsNone(target, ".o_control_panel .o_breadcrumb");
});
QUnit.test("document's title is updated when an action is executed", async function (assert) {
@@ -272,10 +271,10 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, "ClientAction");
assert.containsOnce(target, ".my_button");
await testUtils.dom.click(target.querySelector(".my_button"));
await click(target.querySelector(".my_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view");
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb a:first"));
await click(target, ".o_control_panel .breadcrumb a");
await legacyExtraNextTick();
assert.containsOnce(target, ".my_button");
assert.verifySteps(["on_reverse_breadcrumb"]);
@@ -284,7 +283,7 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test('handles "history_back" event', async function (assert) {
assert.expect(3);
assert.expect(4);
let list;
patchWithCleanup(listView.Controller.prototype, {
setup() {
@@ -295,13 +294,13 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, 4);
await doAction(webClient, 3);
assert.containsN(target, ".o_control_panel .breadcrumb-item", 2);
assert.containsOnce(target, "ol.breadcrumb");
assert.containsOnce(target, ".o_breadcrumb span");
list.env.config.historyBack();
await testUtils.nextTick();
await legacyExtraNextTick();
assert.containsOnce(target, ".o_control_panel .breadcrumb-item");
await nextTick();
assert.containsOnce(target, ".o_breadcrumb span");
assert.strictEqual(
$(target).find(".o_control_panel .breadcrumb-item").text(),
target.querySelector(".o_control_panel .o_breadcrumb").textContent,
"Partners Action 4",
"breadcrumbs should display the display_name of the action"
);

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