From b63ee52552d38ac1e5d8ce824b91ab2a6d05b110 Mon Sep 17 00:00:00 2001 From: Bruno Boi Date: Thu, 30 Sep 2021 13:31:00 +0000 Subject: [PATCH] [FIX] *: remove scss 'extend' from dropdown components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit removes all the 'extend' initially introduced to avoid code repetition and ensure visual consistency across Bootstrap and Owl dropdowns. Despite achieving the desired results, using 'extend' in this context was seriously impacting the bundle generation time, probably due to an underestimated amount of Apps' legacy-code applied on these elements. In order to achieve the same results, the chosen strategy is to add Bootstrap default classes directly into Owl dropdowns. Also, it moves code related to bootstrap dropdown in 'webclient.scss', leaving 'core/dropdown/dropdown.scss' for Owl code only. Due to the discrepancies between Bootstrap and Owl html structure, the '.dropdown-item' class could not have been added directly to Owl's '.o_dropdown_item' itself, without refactoring the Dropdown component structure. // ==== Bootstrap 4.6 default Structure ================================ // ==== OWL default Structure before this commit ======================= // ==== OWL Structure after this commit ================================ // ==== web.assets_backend.css Bundle Generation Comparison ============ With all modules installed (enterprise edition over runbot): Before this commit, bundle took ~2.5s and ~4s to generate and weighted ~322kB (~2.5MB uncompressed) After this commit, it takes between ~1.2s and ~1.6s and weights ~257kB (~1.6MB uncompressed) closes odoo/odoo#77649 X-original-commit: 84715436d87bb05b421bc9ccaacda67d07571690 Related: odoo/enterprise#21370 Signed-off-by: Géry Debongnie (ged) Co-authored-by: Stefano Rigano Co-authored-by: François Georis Co-authored-by: Bruno Boi --- .../account_dashboard_setup_bar_tests.js | 2 +- addons/auth_totp/static/tests/totp_flow.js | 4 +- .../static/src/add_to_board/add_to_board.xml | 8 +- addons/board/static/tests/dashboard_tests.js | 29 +- .../crm/static/tests/forecast_view_tests.js | 5 +- .../static/tests/tours/crm_forecast_tour.js | 4 +- .../static/src/js/tours/hr_expense.js | 2 +- .../messaging_menu/messaging_menu.scss | 2 +- .../messaging_menu/messaging_menu.xml | 6 +- .../tests/messaging_menu_tests.js | 4 +- .../rtc_activity_notice.xml | 4 +- .../rtc_activity_notice.xml | 2 +- addons/mail/static/src/xml/systray.xml | 6 +- addons/mail/static/tests/activity_tests.js | 6 +- .../static/tests/tools/debug_manager_tests.js | 4 +- .../static/tests/tours/sale_timesheet_tour.js | 4 +- .../src/xml/report_stock_forecasted.xml | 6 +- .../web/static/src/core/debug/debug_menu.scss | 2 +- .../web/static/src/core/debug/debug_menu.xml | 19 +- .../web/static/src/core/dropdown/dropdown.js | 23 +- .../static/src/core/dropdown/dropdown.scss | 193 +++------ .../web/static/src/core/dropdown/dropdown.xml | 21 +- .../static/src/core/dropdown/dropdown_item.js | 9 +- .../src/core/dropdown/dropdown_item.xml | 8 +- .../core/dropdown/dropdown_navigation_hook.js | 79 ++-- .../src/legacy/js/fields/relational_fields.js | 12 + .../legacy/js/views/graph/graph_controller.js | 2 +- .../src/legacy/scss/bootstrap_overridden.scss | 2 - .../web/static/src/legacy/scss/dropdown.scss | 8 +- addons/web/static/src/legacy/scss/navbar.scss | 77 ++-- addons/web/static/src/legacy/scss/utils.scss | 8 +- addons/web/static/src/legacy/xml/base.xml | 12 +- addons/web/static/src/legacy/xml/pivot.xml | 2 +- .../comparison_menu/comparison_menu.xml | 13 +- .../search/control_panel/control_panel.scss | 15 +- .../search/control_panel/control_panel.xml | 2 +- .../favorite_menu/custom_favorite_item.xml | 8 +- .../search/favorite_menu/favorite_menu.xml | 9 +- .../search/filter_menu/custom_filter_item.xml | 8 +- .../src/search/filter_menu/filter_menu.xml | 29 +- .../group_by_menu/custom_group_by_item.xml | 8 +- .../search/group_by_menu/group_by_menu.xml | 28 +- .../src/search/search_bar/search_bar.xml | 2 +- .../static/src/views/pivot/pivot_renderer.xml | 1 - .../static/src/views/pivot/pivot_view.scss | 2 +- .../static/src/webclient/clickbot/clickbot.js | 18 +- .../web/static/src/webclient/navbar/navbar.js | 12 +- .../static/src/webclient/navbar/navbar.xml | 71 +-- .../switch_company_menu.xml | 2 +- .../src/webclient/user_menu/user_menu.xml | 14 +- .../web/static/src/webclient/webclient.scss | 47 ++ .../tests/core/debug/debug_manager_tests.js | 42 +- .../web/static/tests/core/dropdown_tests.js | 405 ++++++++++-------- addons/web/static/tests/helpers/utils.js | 4 + .../legacy/components/action_menus_tests.js | 14 +- .../legacy/components/dropdown_menu_tests.js | 26 +- .../control_panel/comparison_menu_tests.js | 11 +- .../control_panel/custom_filter_item_tests.js | 39 +- .../custom_group_by_item_tests.js | 21 +- .../control_panel/favorite_menu_tests.js | 10 +- .../legacy/control_panel/filter_menu_tests.js | 9 +- .../control_panel/groupby_menu_tests.js | 7 +- .../legacy/control_panel/search_bar_tests.js | 3 + .../relational_fields/field_many2one_tests.js | 20 +- .../helpers/test_utils_control_panel.js | 4 +- .../static/tests/legacy/views/form_tests.js | 4 +- .../static/tests/legacy/views/graph_tests.js | 5 +- .../static/tests/legacy/views/list_tests.js | 20 +- .../static/tests/legacy/views/pivot_tests.js | 111 ++--- .../tests/legacy/views/state_mapping_tests.js | 4 +- .../tests/legacy/views/view_dialogs_tests.js | 7 + .../tests/search/comparison_menu_tests.js | 15 +- .../search/custom_favorite_item_tests.js | 7 +- .../tests/search/custom_filter_item_tests.js | 17 +- .../search/custom_group_by_item_tests.js | 24 +- .../tests/search/favorite_menu_tests.js | 12 +- .../static/tests/search/filter_menu_tests.js | 9 +- .../tests/search/group_by_menu_tests.js | 6 + addons/web/static/tests/search/helpers.js | 44 +- .../static/tests/views/graph_view_tests.js | 19 +- .../static/tests/views/pivot_view_tests.js | 260 ++++++----- .../webclient/actions/load_state_tests.js | 4 +- .../webclient/actions/push_state_tests.js | 6 +- .../webclient/actions/window_action_tests.js | 23 +- .../static/tests/webclient/navbar_tests.js | 45 +- .../webclient/switch_company_menu_tests.js | 38 +- .../static/tests/webclient/user_menu_tests.js | 22 +- .../static/lib/odoo-editor/src/style.css | 4 +- .../web_editor/static/src/scss/wysiwyg.scss | 2 +- .../static/tests/debug_manager_tests.js | 6 +- .../static/tests/tours/dashboard_tour.js | 2 +- .../views/website_navbar_templates.xml | 60 +-- .../views/website_customer_templates.xml | 2 +- .../website_event/views/website_templates.xml | 2 +- .../views/event_exhibitor_templates_page.xml | 2 +- .../views/website_templates.xml | 2 +- .../website_hr_recruitment_templates.xml | 2 +- .../tours/website_sale_shop_cart_recovery.js | 2 +- addons/website_sale/views/templates.xml | 2 +- .../views/slide_channel_views.xml | 2 +- .../views/website_slides_templates_utils.xml | 2 +- .../static/tests/tours/main_flow.js | 22 +- .../test_new_api/static/tests/tours/x2many.js | 4 +- 103 files changed, 1218 insertions(+), 1081 deletions(-) diff --git a/addons/account/static/tests/tours/account_dashboard_setup_bar_tests.js b/addons/account/static/tests/tours/account_dashboard_setup_bar_tests.js index 0d11b027163..cdbe6c75339 100644 --- a/addons/account/static/tests/tours/account_dashboard_setup_bar_tests.js +++ b/addons/account/static/tests/tours/account_dashboard_setup_bar_tests.js @@ -20,7 +20,7 @@ odoo.define('account.dashboard.setup.tour', function (require) { }, { trigger: '.o_control_panel button:contains("' + _t('Print') + '")', }, { - trigger: '.o_control_panel .o_dropdown_menu a:contains("' + _t('Invoices without Payment') + '")', + trigger: '.o_control_panel .dropdown-menu a:contains("' + _t('Invoices without Payment') + '")', }, { trigger: 'iframe .o_report_layout_standard h2', content: 'Primary color is correct', diff --git a/addons/auth_totp/static/tests/totp_flow.js b/addons/auth_totp/static/tests/totp_flow.js index 868be3db6a0..6f2f29ba7eb 100644 --- a/addons/auth_totp/static/tests/totp_flow.js +++ b/addons/auth_totp/static/tests/totp_flow.js @@ -161,7 +161,7 @@ tour.register('totp_login_device', { run: 'click', }, { content: "click the Log out button", - trigger: 'li[data-menu=logout] > a', + trigger: '.dropdown-item[data-menu=logout]', }, { content: "check that we're back on the login page or go to it", trigger: 'input#login, a:contains(Log in)' @@ -280,7 +280,7 @@ tour.register('totp_admin_disables', { } }, { content: "Open Actions menu", - trigger: 'button.o_dropdown_toggler:contains("Action")' + trigger: 'button.dropdown-toggle:contains("Action")' }, { content: "Select totp remover", trigger: 'a.dropdown-item:contains(Disable two-factor authentication)' diff --git a/addons/board/static/src/add_to_board/add_to_board.xml b/addons/board/static/src/add_to_board/add_to_board.xml index 6419bd154af..98fdb8aad9b 100644 --- a/addons/board/static/src/add_to_board/add_to_board.xml +++ b/addons/board/static/src/add_to_board/add_to_board.xml @@ -4,12 +4,12 @@ Add to my dashboard -
  • +
    -
  • -
  • + +
    -
  • +
    diff --git a/addons/board/static/tests/dashboard_tests.js b/addons/board/static/tests/dashboard_tests.js index 7d2129d8a7f..8b05c697b55 100644 --- a/addons/board/static/tests/dashboard_tests.js +++ b/addons/board/static/tests/dashboard_tests.js @@ -7,6 +7,8 @@ odoo.define("board.dashboard_tests", function (require) { var testUtils = require("web.test_utils"); var ListRenderer = require("web.ListRenderer"); var pyUtils = require("web.py_utils"); + const { browser } = require("@web/core/browser/browser"); + const { patchWithCleanup } = require("@web/../tests/helpers/utils"); const { registry } = require("@web/core/registry"); const { makeFakeUserService } = require("@web/../tests/helpers/mock_services"); const { @@ -844,6 +846,7 @@ odoo.define("board.dashboard_tests", function (require) { "partner,false,list": '', "partner,false,search": "", }; + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const mockRPC = (route, args) => { if (route === "/board/add_to_dashboard") { @@ -895,9 +898,9 @@ odoo.define("board.dashboard_tests", function (require) { // add this action to dashboard await toggleFavoriteMenu(webClient); - await testUtils.dom.click($(".o_add_to_board button.o_dropdown_toggler")); + 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 .o_dropdown_menu button")); + await testUtils.dom.click($(".o_add_to_board .dropdown-menu button")); testUtils.mock.unpatch(ListController); }); @@ -906,6 +909,7 @@ odoo.define("board.dashboard_tests", function (require) { // the second search saved should not be influenced by the first assert.expect(2); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); serverData.views = { "partner,false,list": '', "partner,false,search": "", @@ -951,8 +955,8 @@ odoo.define("board.dashboard_tests", function (require) { // Add it to dashboard await toggleFavoriteMenu(webClient); - await testUtils.dom.click($(".o_add_to_board button.o_dropdown_toggler")); - await testUtils.dom.click($(".o_add_to_board .o_dropdown_menu button")); + await testUtils.dom.triggerEvent($(".o_add_to_board button.dropdown-toggle"), "mouseenter"); + await testUtils.dom.click($(".o_add_to_board .dropdown-menu button")); // Remove it await testUtils.dom.click(webClient.el.querySelector(".o_facet_remove")); @@ -964,11 +968,12 @@ odoo.define("board.dashboard_tests", function (require) { await applyFilter(webClient); // Add it to dashboard await toggleFavoriteMenu(webClient); - await testUtils.dom.click( - webClient.el.querySelector(".o_add_to_board button.o_dropdown_toggler") + await testUtils.dom.triggerEvent( + webClient.el.querySelector(".o_add_to_board button.dropdown-toggle"), + "mouseenter" ); await testUtils.dom.click( - webClient.el.querySelector(".o_add_to_board .o_dropdown_menu button") + webClient.el.querySelector(".o_add_to_board .dropdown-menu button") ); }); @@ -976,6 +981,7 @@ odoo.define("board.dashboard_tests", function (require) { // View domains are to be added to the dashboard domain assert.expect(1); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); var view_domain = ["display_name", "ilike", "a"]; var filter_domain = ["display_name", "ilike", "b"]; @@ -1011,12 +1017,13 @@ odoo.define("board.dashboard_tests", function (require) { await applyFilter(webClient); // Add it to dashboard await toggleFavoriteMenu(webClient); - await testUtils.dom.click( - webClient.el.querySelector(".o_add_to_board button.o_dropdown_toggler") + await testUtils.dom.triggerEvent( + webClient.el.querySelector(".o_add_to_board button.dropdown-toggle"), + "mouseenter" ); // add await testUtils.dom.click( - webClient.el.querySelector(".o_add_to_board .o_dropdown_menu button") + webClient.el.querySelector(".o_add_to_board .dropdown-menu button") ); }); @@ -1255,7 +1262,7 @@ odoo.define("board.dashboard_tests", function (require) { // add the view to the dashboard await toggleFavoriteMenu(webClient); - await testUtils.dom.click($(".o_add_to_board button.o_dropdown_toggler")); + await testUtils.dom.click($(".o_add_to_board button.dropdown-toggle")); await testUtils.fields.editInput($(".o_add_to_board input"), "a name"); await testUtils.dom.click($(".o_add_to_board div button")); diff --git a/addons/crm/static/tests/forecast_view_tests.js b/addons/crm/static/tests/forecast_view_tests.js index 7d2992142e7..030adc9c560 100644 --- a/addons/crm/static/tests/forecast_view_tests.js +++ b/addons/crm/static/tests/forecast_view_tests.js @@ -7,7 +7,7 @@ import { toggleFilterMenu, toggleGroupByMenu, toggleMenuItem, - toggleMenuItemOption + toggleMenuItemOption, } from "@web/../tests/search/helpers"; import { makeView } from "@web/../tests/views/helpers"; import { createWebClient, doAction } from "@web/../tests/webclient/helpers"; @@ -18,6 +18,7 @@ import AbstractModel from "web.AbstractModel"; import AbstractView from "web.AbstractView"; import { controlPanel as cpHelpers, mock } from "web.test_utils"; import legacyViewRegistry from "web.view_registry"; +import { browser } from "@web/core/browser/browser"; const patchDate = mock.patchDate; @@ -72,6 +73,7 @@ QUnit.module("Views", (hooks) => { QUnit.test("Forecast graph view", async function (assert) { assert.expect(5); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const unpatchDate = patchDate(2021, 8, 16, 16, 54, 0); const expectedDomains = [ @@ -167,6 +169,7 @@ QUnit.module("Views", (hooks) => { async function (assert) { assert.expect(16); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const unpatchDate = patchDate(2021, 8, 16, 16, 54, 0); const expectedDomains = [ diff --git a/addons/crm/static/tests/tours/crm_forecast_tour.js b/addons/crm/static/tests/tours/crm_forecast_tour.js index df08fea7171..730c9c82ac0 100644 --- a/addons/crm/static/tests/tours/crm_forecast_tour.js +++ b/addons/crm/static/tests/tours/crm_forecast_tour.js @@ -11,11 +11,11 @@ tour.register('crm_forecast', { trigger: ".o_app[data-menu-xmlid='crm.crm_menu_root']", content: "open crm app", }, { - trigger: '.o_dropdown_toggler[data-menu-xmlid="crm.crm_menu_report"]', + trigger: '.dropdown-toggle[data-menu-xmlid="crm.crm_menu_report"]', content: 'Open Reporting menu', run: 'click', }, { - trigger: '.o_dropdown_item[data-menu-xmlid="crm.crm_menu_forecast"]', + trigger: '.dropdown-item[data-menu-xmlid="crm.crm_menu_forecast"]', content: 'Open Forecast menu', run: 'click', }, { diff --git a/addons/hr_expense/static/src/js/tours/hr_expense.js b/addons/hr_expense/static/src/js/tours/hr_expense.js index b8200677c51..a2dffe7f4f0 100644 --- a/addons/hr_expense/static/src/js/tours/hr_expense.js +++ b/addons/hr_expense/static/src/js/tours/hr_expense.js @@ -35,7 +35,7 @@ tour.register('hr_expense_tour' , { content: Markup(_t('

    Select expenses to submit them to your manager

    ')), position: 'bottom' }, { - trigger: '.o_dropdown_toggler', + trigger: '.dropdown-toggle', extra_trigger: ".o_expense_tree", content: Markup(_t('

    Click on Action Create Report to submit selected expenses to your manager

    ')), position: 'right', diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu.scss b/addons/mail/static/src/components/messaging_menu/messaging_menu.scss index ad9e3a144a3..3d48947cad9 100644 --- a/addons/mail/static/src/components/messaging_menu/messaging_menu.scss +++ b/addons/mail/static/src/components/messaging_menu/messaging_menu.scss @@ -107,7 +107,7 @@ // ------------------------------------------------------------------ // Make hightlight more consistent, due to messaging menu looking quite similar to discuss app in mobile -.o_MessagingMenu.o-is-open { +.o_MessagingMenu.show { background-color: rgba($black, 0.1); } diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu.xml b/addons/mail/static/src/components/messaging_menu/messaging_menu.xml index e9e56f7c906..66bafea4bad 100644 --- a/addons/mail/static/src/components/messaging_menu/messaging_menu.xml +++ b/addons/mail/static/src/components/messaging_menu/messaging_menu.xml @@ -2,8 +2,8 @@ -
  • - + -
  • +
    diff --git a/addons/mail/static/src/components/messaging_menu/tests/messaging_menu_tests.js b/addons/mail/static/src/components/messaging_menu/tests/messaging_menu_tests.js index f773ce7c05e..756c193a224 100644 --- a/addons/mail/static/src/components/messaging_menu/tests/messaging_menu_tests.js +++ b/addons/mail/static/src/components/messaging_menu/tests/messaging_menu_tests.js @@ -201,7 +201,7 @@ QUnit.test('basic rendering', async function (assert) { await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click()); assert.hasClass( document.querySelector('.o_MessagingMenu'), - "o-is-open", + "show", "should mark messaging menu as opened" ); assert.strictEqual( @@ -280,7 +280,7 @@ QUnit.test('basic rendering', async function (assert) { await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click()); assert.doesNotHaveClass( document.querySelector('.o_MessagingMenu'), - "o-is-open", + "show", "should mark messaging menu as closed" ); }); diff --git a/addons/mail/static/src/components/rtc_activity_notice/rtc_activity_notice.xml b/addons/mail/static/src/components/rtc_activity_notice/rtc_activity_notice.xml index 5379d073179..81ea5e4a35c 100644 --- a/addons/mail/static/src/components/rtc_activity_notice/rtc_activity_notice.xml +++ b/addons/mail/static/src/components/rtc_activity_notice/rtc_activity_notice.xml @@ -2,7 +2,7 @@ - +
  • +
  • diff --git a/addons/mail/static/src/widgets/rtc_activity_notice/rtc_activity_notice.xml b/addons/mail/static/src/widgets/rtc_activity_notice/rtc_activity_notice.xml index c30a12bc03e..d5eb221310e 100644 --- a/addons/mail/static/src/widgets/rtc_activity_notice/rtc_activity_notice.xml +++ b/addons/mail/static/src/widgets/rtc_activity_notice/rtc_activity_notice.xml @@ -2,7 +2,7 @@ -
  • +
    diff --git a/addons/mail/static/src/xml/systray.xml b/addons/mail/static/src/xml/systray.xml index 55a5c5c6614..ddfbee91c0c 100644 --- a/addons/mail/static/src/xml/systray.xml +++ b/addons/mail/static/src/xml/systray.xml @@ -49,13 +49,13 @@ -
  • -
  • +
    diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js index 7d41db1da5b..780fab2a5d4 100644 --- a/addons/mail/static/tests/activity_tests.js +++ b/addons/mail/static/tests/activity_tests.js @@ -402,16 +402,16 @@ QUnit.test("activity view: no group_by_menu and no comparison_menu", async funct assert.containsN( webClient, - ".o_search_options .o_dropdown button:visible", + ".o_search_options .dropdown button:visible", 2, "only two elements should be available in view search" ); assert.isVisible( - $(webClient.el).find(".o_search_options .o_dropdown.o_filter_menu > button"), + $(webClient.el).find(".o_search_options .dropdown.o_filter_menu > button"), "filter should be available in view search" ); assert.isVisible( - $(webClient.el).find(".o_search_options .o_dropdown.o_favorite_menu > button"), + $(webClient.el).find(".o_search_options .dropdown.o_favorite_menu > button"), "favorites should be available in view search" ); }); diff --git a/addons/mail/static/tests/tools/debug_manager_tests.js b/addons/mail/static/tests/tools/debug_manager_tests.js index 0a50e4cd123..f3a7e667ebf 100644 --- a/addons/mail/static/tests/tools/debug_manager_tests.js +++ b/addons/mail/static/tests/tools/debug_manager_tests.js @@ -40,10 +40,10 @@ QUnit.test("Manage Messages", async function (assert) { const wc = await createWebClient({ serverData, mockRPC }); await doAction(wc, 3, { viewType: "form", props: { resId: 5 } }); await legacyExtraNextTick(); - await click(wc.el, ".o_debug_manager .o_dropdown_toggler"); + await click(wc.el, ".o_debug_manager .dropdown-toggle"); const dropdownItems = wc.el.querySelectorAll( - ".o_debug_manager .o_dropdown_menu .o_dropdown_item" + ".o_debug_manager .dropdown-menu .dropdown-item" ); assert.strictEqual(dropdownItems.length, 1); assert.strictEqual( diff --git a/addons/sale_timesheet/static/tests/tours/sale_timesheet_tour.js b/addons/sale_timesheet/static/tests/tours/sale_timesheet_tour.js index 6e1fa4176f7..6aefb825e58 100644 --- a/addons/sale_timesheet/static/tests/tours/sale_timesheet_tour.js +++ b/addons/sale_timesheet/static/tests/tours/sale_timesheet_tour.js @@ -156,7 +156,7 @@ tour.register('sale_timesheet_tour', { content: 'Click on the Configuration menu.', run: 'click', }, { - trigger: 'li[data-menu-xmlid="project.menu_projects_config"]', + trigger: '.dropdown-item[data-menu-xmlid="project.menu_projects_config"]', content: 'Select Configuration > Projects.', run: 'click', }, { @@ -238,7 +238,7 @@ tour.register('sale_timesheet_tour', { trigger: '.o_form_button_save', content: 'Save Project', }, { - trigger: 'li[data-menu-xmlid="project.menu_projects"]', + trigger: '.dropdown-item[data-menu-xmlid="project.menu_projects"]', content: 'Select Projects', }, { // an invisible element cannot be used as a trigger so this small hack is mandatory for the next step diff --git a/addons/stock/static/src/xml/report_stock_forecasted.xml b/addons/stock/static/src/xml/report_stock_forecasted.xml index 2c294cf4b09..20edf8c3ad2 100644 --- a/addons/stock/static/src/xml/report_stock_forecasted.xml +++ b/addons/stock/static/src/xml/report_stock_forecasted.xml @@ -8,13 +8,13 @@ -
    - - diff --git a/addons/web/static/src/core/dropdown/dropdown_item.js b/addons/web/static/src/core/dropdown/dropdown_item.js index c51361aec57..9d321cc8dab 100644 --- a/addons/web/static/src/core/dropdown/dropdown_item.js +++ b/addons/web/static/src/core/dropdown/dropdown_item.js @@ -27,8 +27,11 @@ export const ParentClosingMode = { export class DropdownItem extends Component { /** * Triggers a custom DropdownItemSelectedEvent + * @param {MouseEvent} ev */ - onClick() { + onClick(ev) { + ev.preventDefault(); + /** @type DropdownItemSelectedEventDetail */ const detail = { payload: this.props.payload, @@ -54,6 +57,10 @@ DropdownItem.props = { type: String, optional: true, }, + href: { + type: String, + optional: true, + }, title: { type: String, optional: true, diff --git a/addons/web/static/src/core/dropdown/dropdown_item.xml b/addons/web/static/src/core/dropdown/dropdown_item.xml index f1533698cf6..34163198921 100644 --- a/addons/web/static/src/core/dropdown/dropdown_item.xml +++ b/addons/web/static/src/core/dropdown/dropdown_item.xml @@ -2,14 +2,16 @@ -
  • -
  • +
    diff --git a/addons/web/static/src/core/dropdown/dropdown_navigation_hook.js b/addons/web/static/src/core/dropdown/dropdown_navigation_hook.js index 40ff77bc486..37c4bb7a09a 100644 --- a/addons/web/static/src/core/dropdown/dropdown_navigation_hook.js +++ b/addons/web/static/src/core/dropdown/dropdown_navigation_hook.js @@ -10,6 +10,7 @@ import { scrollTo } from "../utils/scrolling"; * el: HTMLElement, * isActive: boolean, * makeOnlyActive: ()=>void, + * navTarget: HTMLElement, * isSubDropdown: boolean, * isSubDropdownOpen: boolean, * closeSubDropdown: ()=>void, @@ -21,7 +22,7 @@ const { hooks } = owl; const { useComponent, useRef } = hooks; const ACTIVE_MENU_ELEMENT_CLASS = "focus"; -const MENU_ELEMENTS_SELECTORS = [":scope > li.o_dropdown_item", ":scope > li.o_dropdown"]; +const MENU_ELEMENTS_SELECTORS = [":scope > .dropdown-item", ":scope > .dropdown"]; const NEXT_ACTIVE_INDEX_FNS = { FIRST: () => 0, LAST: (list) => list.length - 1, @@ -33,12 +34,30 @@ export function useDropdownNavigation() { /** @type {import("./dropdown").Dropdown} */ const comp = useComponent(); - // As this navigation hook relies on clicking ".o_dropdown_toggler" elements, + // As this navigation hook relies on clicking ".dropdown-toggle" elements, // it is incompatible with a toggler="parent" strategy for subdropdowns. if (comp.hasParentDropdown && comp.props.toggler === "parent") { throw new Error("A nested Dropdown must use its standard toggler"); } + // Needed to avoid unwanted mouseclick behavior on a subdropdown toggler. + const originalOnTogglerClick = comp.onTogglerClick.bind(comp); + comp.onTogglerClick = (ev) => { + if (comp.hasParentDropdown && !ev.__fromDropdownNavigation) { + return; + } + originalOnTogglerClick(); + }; + + // Needed to avoid unwanted mouseenter behavior on a subdropdown toggler. + const originalOnTogglerMouseEnter = comp.onTogglerMouseEnter.bind(comp); + comp.onTogglerMouseEnter = () => { + if (comp.hasParentDropdown) { + return; + } + originalOnTogglerMouseEnter(); + }; + // Needed to avoid unwanted selection when the mouse pointer is not in use // but still somewhere in the middle of the dropdown menu list. let mouseSelectionActive = true; @@ -56,20 +75,17 @@ export function useDropdownNavigation() { /** @type {NodeListOf} */ const queryResult = menuRef.el.querySelectorAll(MENU_ELEMENTS_SELECTORS.join()); for (const el of queryResult) { - const isSubDropdown = el.classList.contains("o_dropdown"); + const isSubDropdown = el.classList.contains("dropdown"); const isSubDropdownOpen = () => el.classList.contains("show"); - const togglerClick = () => { - const toggler = el.querySelector(":scope > .o_dropdown_toggler"); - if (toggler) { - toggler.dispatchEvent(new MouseEvent("click", { bubbles: false })); - } - }; + const navTarget = isSubDropdown ? el.querySelector(":scope > .dropdown-toggle") : el; let subDropdownTimeout; const closeSubDropdown = () => { browser.clearTimeout(subDropdownTimeout); subDropdownTimeout = browser.setTimeout(() => { if (isSubDropdownOpen()) { - togglerClick(); + const ev = new MouseEvent("click", { bubbles: false }); + ev.__fromDropdownNavigation = true; + navTarget.dispatchEvent(ev); } }, 200); }; @@ -78,7 +94,9 @@ export function useDropdownNavigation() { subDropdownTimeout = browser.setTimeout( () => { if (!isSubDropdownOpen()) { - togglerClick(); + const ev = new MouseEvent("click", { bubbles: false }); + ev.__fromDropdownNavigation = true; + navTarget.dispatchEvent(ev); } }, immediate ? 0 : 200 @@ -90,22 +108,23 @@ export function useDropdownNavigation() { if (menuElement.el === el) { continue; } - menuElement.el.classList.remove(ACTIVE_MENU_ELEMENT_CLASS); + menuElement.navTarget.classList.remove(ACTIVE_MENU_ELEMENT_CLASS); if (menuElement.isSubDropdown) { menuElement.closeSubDropdown(); } } // Make myself active - el.classList.add(ACTIVE_MENU_ELEMENT_CLASS); + navTarget.classList.add(ACTIVE_MENU_ELEMENT_CLASS); }; /** @type {MenuElement} */ const menuElement = { el, get isActive() { - return el.classList.contains(ACTIVE_MENU_ELEMENT_CLASS); + return navTarget.classList.contains(ACTIVE_MENU_ELEMENT_CLASS); }, makeOnlyActive, + navTarget, get isSubDropdownOpen() { return isSubDropdownOpen(); }, @@ -117,12 +136,11 @@ export function useDropdownNavigation() { // Set up selection listeners const elementListeners = { - click: makeOnlyActive, mouseenter: () => { if (!mouseSelectionActive) { mouseSelectionActive = true; } else { - menuElement.makeOnlyActive(); + makeOnlyActive(); if (isSubDropdown) { openSubDropdown(); } @@ -130,18 +148,18 @@ export function useDropdownNavigation() { }, }; for (const [eventType, listener] of Object.entries(elementListeners)) { - menuElement.el.addEventListener(eventType, listener); + navTarget.addEventListener(eventType, listener); } - addedListeners.push([menuElement, elementListeners]); + addedListeners.push([navTarget, elementListeners]); } return () => { menuElements = []; mouseSelectionActive = true; // Clear mouse selection listeners - for (const [menuElement, listeners] of addedListeners) { + for (const [navTarget, listeners] of addedListeners) { for (const [eventType, listener] of Object.entries(listeners)) { - menuElement.el.removeEventListener(eventType, listener); + navTarget.removeEventListener(eventType, listener); } } }; @@ -191,6 +209,16 @@ export function useDropdownNavigation() { menuElement.openSubDropdown(true); } }; + const selectActiveMenuElement = () => { + const menuElement = getActiveMenuElement(); + if (menuElement) { + if (menuElement.isSubDropdown) { + menuElement.openSubDropdown(true); + } else { + menuElement.navTarget.click(); + } + } + }; let hotkeyRemoves = []; const hotkeyCallbacks = { home: () => setActiveMenuElement("FIRST"), @@ -201,16 +229,7 @@ export function useDropdownNavigation() { arrowup: () => setActiveMenuElement("PREV"), arrowleft: localization.direction === "rtl" ? openSubDropdown : closeSubDropdown, arrowright: localization.direction === "rtl" ? closeSubDropdown : openSubDropdown, - enter: () => { - const menuElement = getActiveMenuElement(); - if (menuElement) { - if (menuElement.isSubDropdown) { - menuElement.openSubDropdown(true); - } else { - menuElement.el.click(); - } - } - }, + enter: selectActiveMenuElement, escape: comp.close, }; useEffect( diff --git a/addons/web/static/src/legacy/js/fields/relational_fields.js b/addons/web/static/src/legacy/js/fields/relational_fields.js index 876bf19d5c8..b943a398aff 100644 --- a/addons/web/static/src/legacy/js/fields/relational_fields.js +++ b/addons/web/static/src/legacy/js/fields/relational_fields.js @@ -333,6 +333,18 @@ var FieldMany2One = AbstractField.extend({ html: true, minLength: 0, delay: this.AUTOCOMPLETE_DELAY, + classes: { + "ui-autocomplete": "dropdown-menu", + }, + create: function() { + $(this).data('ui-autocomplete')._renderMenu = function(ulWrapper, entries) { + var render = this; + $.each(entries, function(index, entry) { + render._renderItemData(ulWrapper, entry); + }); + $(ulWrapper).find( "li > a" ).addClass( "dropdown-item" ); + } + }, }); this.$input.autocomplete("option", "position", { my : "left top", at: "left bottom" }); this.autocomplete_bound = true; diff --git a/addons/web/static/src/legacy/js/views/graph/graph_controller.js b/addons/web/static/src/legacy/js/views/graph/graph_controller.js index bbd5d490b35..23b274ee697 100644 --- a/addons/web/static/src/legacy/js/views/graph/graph_controller.js +++ b/addons/web/static/src/legacy/js/views/graph/graph_controller.js @@ -193,7 +193,7 @@ var GraphController = AbstractController.extend({ this.groupByMenu.el.classList.add('o_group_by_menu'); } // Update button classes accordingly to the current mode - const buttons = actionsContainer.querySelectorAll('.o_dropdown_toggler'); + const buttons = actionsContainer.querySelectorAll('.dropdown-toggle'); for (const button of buttons) { button.classList.remove('btn-secondary'); if (this.isEmbedded) { diff --git a/addons/web/static/src/legacy/scss/bootstrap_overridden.scss b/addons/web/static/src/legacy/scss/bootstrap_overridden.scss index c1e3e70d954..63a22b729f5 100644 --- a/addons/web/static/src/legacy/scss/bootstrap_overridden.scss +++ b/addons/web/static/src/legacy/scss/bootstrap_overridden.scss @@ -33,8 +33,6 @@ $danger: $o-danger !default; // // Quickly modify global styling by enabling or disabling optional features. -$enable-caret: false !default; // Disable pseudo element caret on .dropdown-toggle. - // Body // // Settings for the `` element. diff --git a/addons/web/static/src/legacy/scss/dropdown.scss b/addons/web/static/src/legacy/scss/dropdown.scss index 21cda1c543f..d89e0c14a7f 100644 --- a/addons/web/static/src/legacy/scss/dropdown.scss +++ b/addons/web/static/src/legacy/scss/dropdown.scss @@ -1,7 +1,6 @@ // = jQueryUI dropdown adaptations // ---------------------------------------------------------------------------- .ui-widget.ui-autocomplete { - @extend .dropdown-menu; top: 0; // Compute initial position min-width: 0; // Compute initial width @@ -10,11 +9,10 @@ z-index: $zindex-modal + 1; .ui-menu-item { - padding: 0; - > a { - @extend .dropdown-item; - + &.dropdown-item { + padding: $o-dropdown-vpadding $o-dropdown-hpadding; + } &.ui-state-active { margin: 0; border: none; diff --git a/addons/web/static/src/legacy/scss/navbar.scss b/addons/web/static/src/legacy/scss/navbar.scss index 28e3dd95ead..2bae3381567 100644 --- a/addons/web/static/src/legacy/scss/navbar.scss +++ b/addons/web/static/src/legacy/scss/navbar.scss @@ -44,6 +44,7 @@ height: $o-navbar-height; cursor: pointer; user-select: none; + background: transparent; @include o-hover-text-color(rgba($white, .9), $white); } @@ -61,8 +62,6 @@ %-main-navbar-entry-active { @include plain-hover-focus() { background: $-backend-entry-hover-bg; - outline: 1px solid $o-navbar-inverse-link-hover-bg; - outline-offset: -1px; color: $white; } } @@ -77,54 +76,53 @@ // = Owl components // -------------------------------------------------------------------------- - .o_dropdown .o_dropdown_toggler { - @extend %-main-navbar-entry-base; - @extend %-main-navbar-entry-padding; - @extend %-main-navbar-entry-bg-hover; - border: 0; - white-space: nowrap; + &,.o_menu_sections, .o_menu_systray { - &, &:focus { - background: none; - } - } - - .o-dropdown { - &.show > .o_dropdown_toggler { - @extend %-main-navbar-entry-active; - } - } - - .o_nav_entry { - padding: 0; - @extend %-main-navbar-entry-base; - @extend %-main-navbar-entry-padding; - } - - .o_dropdown .o_dropdown_menu, .dropdown-menu { - margin-top: 0; - border-top: 0; - @include border-top-radius(0); - } - - .o_dropdown_menu_group_entry.o_dropdown_item { - > *:first-child { - padding-left: $o-dropdown-hpadding * 1.5; + .dropdown .dropdown-toggle { + @extend %-main-navbar-entry-base; + @extend %-main-navbar-entry-padding; + @extend %-main-navbar-entry-bg-hover; + border: 0; + white-space: nowrap; } - + .o_dropdown_item:not(.o_dropdown_menu_group_entry) { - margin-top: .8em; + .dropdown { + &.show > .dropdown-toggle { + @extend %-main-navbar-entry-active; + } + } + + .o_nav_entry { + @extend %-main-navbar-entry-base; + @extend %-main-navbar-entry-padding; + @extend %-main-navbar-entry-bg-hover; + } + + .dropdown-menu { + margin-top: 0; + border-top: 0; + @include border-top-radius(0); + } + + .o_dropdown_menu_group_entry { + > .dropdown-item { + padding-left: $o-dropdown-hpadding * 1.5; + } + + + .dropdown-item:not(.o_dropdown_menu_group_entry) { + margin-top: .8em; + } } } // = Legacy elements adaptations // -------------------------------------------------------------------------- - > ul { - > li > a, > li > label:only-child, .o_dropdown_toggler { + > .o_menu_sections, .o_menu_systray { + > div > a, > div > label:only-child, .dropdown-toggle, .dropdown-toggle.o-dropdown--narrow { padding: 0 $dropdown-item-padding-x * .5; } - > li { + > div { &, > a { @extend %-main-navbar-entry-base; } @@ -138,7 +136,6 @@ } } } - // = Main Navbar Elements // -------------------------------------------------------------------------- .o_menu_toggle, .o_navbar_apps_menu { diff --git a/addons/web/static/src/legacy/scss/utils.scss b/addons/web/static/src/legacy/scss/utils.scss index 0608ea491b0..f5e10117abc 100644 --- a/addons/web/static/src/legacy/scss/utils.scss +++ b/addons/web/static/src/legacy/scss/utils.scss @@ -383,9 +383,15 @@ padding: 0; > a { - @extend .dropdown-item; margin: auto auto auto (-$link-padding-gap); padding: 3px $link-padding-gap; + color: $dropdown-link-color; + display: block; + + &:hover { + background-color: $dropdown-link-hover-bg; + color: $dropdown-link-hover-color; + } } &:last-child { diff --git a/addons/web/static/src/legacy/xml/base.xml b/addons/web/static/src/legacy/xml/base.xml index 587126d3a27..19aedeac394 100644 --- a/addons/web/static/src/legacy/xml/base.xml +++ b/addons/web/static/src/legacy/xml/base.xml @@ -152,9 +152,9 @@ -
    + +
    - +
    diff --git a/addons/web/static/src/search/favorite_menu/favorite_menu.xml b/addons/web/static/src/search/favorite_menu/favorite_menu.xml index 4631765e594..50e359d7b60 100644 --- a/addons/web/static/src/search/favorite_menu/favorite_menu.xml +++ b/addons/web/static/src/search/favorite_menu/favorite_menu.xml @@ -2,10 +2,7 @@ - + Favorites @@ -13,10 +10,10 @@ - +
    - +
    - +
    diff --git a/addons/web/static/src/search/filter_menu/filter_menu.xml b/addons/web/static/src/search/filter_menu/filter_menu.xml index a3fe871b295..56949943b31 100644 --- a/addons/web/static/src/search/filter_menu/filter_menu.xml +++ b/addons/web/static/src/search/filter_menu/filter_menu.xml @@ -2,10 +2,7 @@ - + Filters @@ -13,44 +10,42 @@ -
  • +
    -
  • - +
    +
    - +
    diff --git a/addons/web/static/src/search/group_by_menu/group_by_menu.xml b/addons/web/static/src/search/group_by_menu/group_by_menu.xml index c606555dd9b..9efe09be6f7 100644 --- a/addons/web/static/src/search/group_by_menu/group_by_menu.xml +++ b/addons/web/static/src/search/group_by_menu/group_by_menu.xml @@ -3,10 +3,10 @@ + > Group By @@ -14,43 +14,41 @@ -
  • coucou
  • '); + assert.strictEqual(parent.el.outerHTML, 'coucou'); + }); + + QUnit.test("DropdownItem (with href prop) can be rendered as ", async (assert) => { + class Parent extends owl.Component {} + Parent.template = owl.tags.xml`coucou`; + env = await makeTestEnv(); + parent = await mount(Parent, { env, target }); + assert.strictEqual(parent.el.outerHTML, 'coucou'); + }); + + QUnit.test("DropdownItem: prevents click default when item clicked", async (assert) => { + assert.expect(2); + // A DropdownItem should preventDefault a click as it may take the shape + // of an tag with an [href] attribute and e.g. could change the url when clicked. + patchWithCleanup(DropdownItem.prototype, { + onClick(ev) { + assert.ok(!ev.defaultPrevented); + this._super(...arguments); + assert.ok(ev.defaultPrevented); + }, + }); + class Parent extends owl.Component {} + Parent.template = owl.tags.xml``; + env = await makeTestEnv(); + parent = await mount(Parent, { env, target }); + await click(target, ".dropdown-item"); }); QUnit.test("can be styled", async (assert) => { @@ -75,14 +95,14 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler"); - assert.hasClass(parent.el, "o_dropdown one"); - const toggler = parent.el.querySelector("button"); - assert.hasClass(toggler, "o_dropdown_toggler two"); - const menu = parent.el.querySelector("ul"); - assert.hasClass(menu, "o_dropdown_menu three"); - const item = parent.el.querySelector("li"); - assert.hasClass(item, "o_dropdown_item four"); + await click(parent.el, "button.dropdown-toggle"); + assert.hasClass(parent.el, "dropdown one"); + const toggler = parent.el.querySelector(".dropdown-toggle"); + assert.hasClass(toggler, "two"); + const menu = parent.el.querySelector(".dropdown-menu"); + assert.hasClass(menu, "three"); + const item = parent.el.querySelector(".dropdown-item"); + assert.hasClass(item, "four"); }); QUnit.test("menu can be toggled", async (assert) => { @@ -100,14 +120,14 @@ QUnit.module("Components", ({ beforeEach }) => { Parent.template = owl.tags.xml``; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler"); + await click(parent.el, "button.dropdown-toggle"); assert.verifySteps(["beforeOpen"]); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsNone(parent.el, ".dropdown-menu"); beforeOpenProm.resolve(); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - await click(parent.el, "button.o_dropdown_toggler"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + await click(parent.el, "button.dropdown-toggle"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("initial open state can be true", async (assert) => { @@ -124,7 +144,7 @@ QUnit.module("Components", ({ beforeEach }) => { env = await makeTestEnv(); parent = await mount(Parent, { env, target }); assert.verifySteps(["beforeOpen"]); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); }); QUnit.test("close on outside click", async (assert) => { @@ -137,10 +157,10 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + await click(parent.el, "button.dropdown-toggle"); + assert.containsOnce(parent.el, ".dropdown-menu"); await click(parent.el, "div.outside"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("close on item selection", async (assert) => { @@ -152,9 +172,9 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler"); - await click(parent.el, "ul.o_dropdown_menu li"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + await click(parent.el, "button.dropdown-toggle"); + await click(parent.el, ".dropdown-menu .dropdown-item"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("payload received on item selection", async (assert) => { @@ -170,8 +190,8 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler"); - await click(parent.el, "ul.o_dropdown_menu li"); + await click(parent.el, "button.dropdown-toggle"); + await click(parent.el, ".dropdown-menu .dropdown-item"); }); QUnit.test("multi-level dropdown: can be rendered and toggled", async (assert) => { @@ -185,10 +205,10 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 3); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 3); }); QUnit.test("multi-level dropdown: initial open state can be true", async (assert) => { @@ -202,7 +222,7 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - assert.containsN(parent.el, "ul.o_dropdown_menu", 3); + assert.containsN(parent.el, ".dropdown-menu", 3); }); QUnit.test("multi-level dropdown: close on outside click", async (assert) => { @@ -219,12 +239,12 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 3); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 3); await click(parent.el, "div.outside"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("multi-level dropdown: close on item selection", async (assert) => { @@ -238,11 +258,17 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); - await click(parent.el, ".o_dropdown_item:not(.o_dropdown)"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 2); + assert.containsN(parent.el, ".dropdown-item", 2); + assert.containsOnce( + parent.el, + ".dropdown-menu > .dropdown > .dropdown-toggle.dropdown-item" + ); + assert.containsOnce(parent.el, ".dropdown-menu > .dropdown-item"); + await click(parent.el, ".dropdown-menu > .dropdown-item"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("multi-level dropdown: parent closing modes on item selection", async (assert) => { @@ -260,28 +286,28 @@ QUnit.module("Components", ({ beforeEach }) => { env = await makeTestEnv(); parent = await mount(Parent, { env, target }); // Open the 2-level dropdowns - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 2); // Select item (parentClosingMode=none) - await click(parent.el, "li.item1"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); + await click(parent.el, ".item1"); + assert.containsN(parent.el, ".dropdown-menu", 2); // Select item (parentClosingMode=closest) - await click(parent.el, "li.item2"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 1); + await click(parent.el, ".item2"); + assert.containsN(parent.el, ".dropdown-menu", 1); // Reopen second level dropdown - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 2); // Select item (parentClosingMode=all) - await click(parent.el, "li.item3"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + await click(parent.el, ".item3"); + assert.containsNone(parent.el, ".dropdown-menu"); // Reopen the 2-level dropdowns - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); + assert.containsN(parent.el, ".dropdown-menu", 2); // Select item (default should be parentClosingMode=all) - await click(parent.el, "li.item4"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + await click(parent.el, ".item4"); + assert.containsNone(parent.el, ".dropdown-menu"); }); QUnit.test("multi-level dropdown: payload bubbles on item selection", async (assert) => { @@ -300,11 +326,11 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - await click(parent.el, "button.o_dropdown_toggler:last-child"); - await click(parent.el, "button.o_dropdown_toggler:last-child"); + await click(parent.el, "button.dropdown-toggle:last-child"); + await mouseEnter(parent.el, "button.dropdown-toggle:last-child"); // As two listeners are defined in the template, // clicking once the item would execute the handler twice. - await click(parent.el, ".o_dropdown_item:not(.o_dropdown)"); + await click(parent.el, ".dropdown-menu > .dropdown-item"); }); QUnit.test("multi-level dropdown: recursive template can be rendered", async (assert) => { @@ -364,7 +390,7 @@ QUnit.module("Components", ({ beforeEach }) => { env.qweb.addTemplate("recursive.Template", recursiveTemplate); parent = await mount(Parent, { env, target }); assert.deepEqual( - [...parent.el.querySelectorAll("button,.o_dropdown_item:not(.o_dropdown)")].map( + [...parent.el.querySelectorAll("button,.dropdown-menu > .dropdown-item")].map( (el) => el.textContent ), [ @@ -413,34 +439,34 @@ QUnit.module("Components", ({ beforeEach }) => { const one = parent.el.querySelector(".one"); await click(one, "button"); assert.verifySteps([]); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsOnce(one, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsOnce(one, ".dropdown-menu"); // Hover on TWO const two = parent.el.querySelector(".two"); two.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); assert.verifySteps(["beforeOpen"]); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsNone(two, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsNone(two, ".dropdown-menu"); beforeOpenProm.resolve(); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsOnce(two, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsOnce(two, ".dropdown-menu"); // Hover on THREE const three = parent.el.querySelector(".three"); three.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsOnce(three, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsOnce(three, ".dropdown-menu"); // Click on OUTSIDE await click(parent.el, "div.outside"); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsNone(parent.el, ".dropdown-menu"); // Hover on ONE, TWO, THREE one.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); two.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); three.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); await nextTick(); - assert.containsNone(parent.el, "ul.o_dropdown_menu"); + assert.containsNone(parent.el, ".dropdown-menu"); } ); @@ -459,13 +485,13 @@ QUnit.module("Components", ({ beforeEach }) => { parent = await mount(Parent, { env, target }); // Click on FOO await click(parent.el, ".foo button"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); // Hover on BAR1 const bar1 = parent.el.querySelector(".bar1"); bar1.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsNone(bar1, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsNone(bar1, ".dropdown-menu"); } ); @@ -484,16 +510,16 @@ QUnit.module("Components", ({ beforeEach }) => { parent = await mount(Parent, { env, target }); // Click on BAR1 await click(parent.el, ".bar1 button"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); // Click on FOO await click(parent.el, ".foo button"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); // Hover on BAR1 const bar1 = parent.el.querySelector(".bar1"); bar1.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsNone(bar1, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsNone(bar1, ".dropdown-menu"); } ); @@ -511,23 +537,23 @@ QUnit.module("Components", ({ beforeEach }) => { parent = await mount(Parent, { env, target }); // Click on one await click(parent.el, ".one button"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); // Click on two await click(parent.el, ".two button"); - assert.containsN(parent.el, "ul.o_dropdown_menu", 2); + assert.containsN(parent.el, ".dropdown-menu", 2); // Click on one again await click(parent.el, ".one button"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsNone(parent.el.querySelector(".one"), "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsNone(parent.el.querySelector(".one"), ".dropdown-menu"); // Hover on one const one = parent.el.querySelector(".one"); one.querySelector("button").dispatchEvent(new MouseEvent("mouseenter")); await nextTick(); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); - assert.containsNone(parent.el.querySelector(".one"), "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); + assert.containsNone(parent.el.querySelector(".one"), ".dropdown-menu"); // Click outside await click(parent.el, "div.outside"); - assert.containsOnce(parent.el, "ul.o_dropdown_menu"); + assert.containsOnce(parent.el, ".dropdown-menu"); }); QUnit.test("dropdowns keynav", async (assert) => { @@ -547,20 +573,20 @@ QUnit.module("Components", ({ beforeEach }) => { `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - assert.containsNone(parent.el, ".o_dropdown_menu", "menu is closed at start"); + assert.containsNone(parent.el, ".dropdown-menu", "menu is closed at start"); triggerHotkey("m", true); await nextTick(); assert.containsOnce( parent.el, - ".o_dropdown_menu", + ".dropdown-menu", "menu is opened after pressing the toggler hotkey" ); // Navigate with arrows assert.containsNone( parent.el, - ".o_dropdown_menu > .focus", + ".dropdown-menu > .focus", "menu should not have any active items" ); @@ -585,41 +611,41 @@ QUnit.module("Components", ({ beforeEach }) => { for (const step of scenarioSteps) { triggerHotkey(step.hotkey); await nextTick(); - assert.hasClass(parent.el.querySelector(".o_dropdown_menu > .focus"), step.expected); + assert.hasClass(parent.el.querySelector(".dropdown-menu > .focus"), step.expected); } // Select last one activated in previous scenario (item1) triggerHotkey("enter"); await nextTick(); - assert.containsNone(parent.el, ".o_dropdown_menu", "menu is closed after item selection"); + assert.containsNone(parent.el, ".dropdown-menu", "menu is closed after item selection"); // Reopen dropdown triggerHotkey("m", true); await nextTick(); assert.containsOnce( parent.el, - ".o_dropdown_menu", + ".dropdown-menu", "menu is opened after pressing the toggler hotkey" ); // Select second item through data-hotkey attribute triggerHotkey("2", true); await nextTick(); - assert.containsNone(parent.el, ".o_dropdown_menu", "menu is closed after item selection"); + assert.containsNone(parent.el, ".dropdown-menu", "menu is closed after item selection"); // Reopen dropdown triggerHotkey("m", true); await nextTick(); assert.containsOnce( parent.el, - ".o_dropdown_menu", + ".dropdown-menu", "menu is opened after pressing the toggler hotkey" ); // Close dropdown with keynav triggerHotkey("escape"); await nextTick(); - assert.containsNone(parent.el, ".o_dropdown_menu", "menu is closed after item selection"); + assert.containsNone(parent.el, ".dropdown-menu", "menu is closed after item selection"); assert.verifySteps(["1", "2"], "items should have been selected in this order"); }); @@ -639,16 +665,16 @@ QUnit.module("Components", ({ beforeEach }) => { env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - assert.containsOnce(parent, ".o_dropdown"); - assert.containsNone(parent, ".o_dropdown .o_dropdown_menu"); - assert.containsNone(parent, ".o_dropdown button.o_dropdown_toggler"); + assert.containsOnce(parent, ".dropdown"); + assert.containsNone(parent, ".dropdown .dropdown-menu"); + assert.containsNone(parent, ".dropdown button.dropdown-toggle"); await click(parent.el, ".my_custom_toggler"); - assert.containsOnce(parent, ".o_dropdown .o_dropdown_menu"); - assert.containsN(parent, ".o_dropdown .o_dropdown_menu .o_dropdown_item", 2); + assert.containsOnce(parent, ".dropdown .dropdown-menu"); + assert.containsN(parent, ".dropdown .dropdown-menu .dropdown-item", 2); }); QUnit.test("multi-level dropdown: keynav", async (assert) => { - assert.expect(126); + assert.expect(125); class Parent extends owl.Component { onItemSelected(ev) { const { payload } = ev.detail; @@ -657,51 +683,21 @@ QUnit.module("Components", ({ beforeEach }) => { } Parent.template = owl.tags.xml` - O - - O - - O - O + O + + O + + O + O - O + O - O + O `; env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - assert.containsNone(parent.el, ".o_dropdown_menu", "menus are closed at start"); - - // Open through hotkeys - triggerHotkey("alt+2"); - await nextTick(); - assert.containsNone(parent.el, ".o_dropdown_menu", "no menu is opened"); - - triggerHotkey("alt+1"); - await nextTick(); - assert.containsOnce(parent.el, ".o_dropdown_menu", "first menu is opened"); - - triggerHotkey("alt+2"); - await nextTick(); - assert.containsN(parent.el, ".o_dropdown_menu", 2, "second menu is opened"); - - triggerHotkey("alt+3"); - await nextTick(); - assert.containsN(parent.el, ".o_dropdown_menu", 3, "both menus are opened"); - - // Close through hotkeys - triggerHotkey("escape"); - await nextTick(); - assert.containsN(parent.el, ".o_dropdown_menu", 2, "third menu is closed"); - - triggerHotkey("escape"); - await nextTick(); - assert.containsOnce(parent.el, ".o_dropdown_menu", "second menu is closed"); - - triggerHotkey("escape"); - await nextTick(); - assert.containsNone(parent.el, ".o_dropdown_menu", "both menus are closed"); + assert.containsNone(parent.el, ".dropdown-menu", "menus are closed at start"); // Highlighting and selecting items const scenarioSteps = [ @@ -743,15 +739,15 @@ QUnit.module("Components", ({ beforeEach }) => { { hotkey: "enter", highlighted: ["second", "third", "third-first"] }, { hotkey: "enter", selected: "third-first" }, { hotkey: "alt+1" }, - { hotkey: "alt+e", selected: false }, - { hotkey: "alt+f", selected: "first-last" }, - { hotkey: "alt+1" }, - { hotkey: "alt+2", highlighted: ["second", "second-first"] }, - { hotkey: "alt+3", highlighted: ["second", "third", "third-first"] }, - { hotkey: "alt+d", selected: "third-last" }, - { hotkey: "alt+1" }, - { hotkey: "alt+2", highlighted: ["second", "second-first"] }, - { hotkey: "alt+e", selected: "second-last" }, + { hotkey: "arrowup", highlighted: ["first-last"] }, + { hotkey: "arrowup", highlighted: ["second"] }, + { hotkey: "arrowright", highlighted: ["second", "second-first"] }, + { hotkey: "arrowup", highlighted: ["second", "second-last"] }, + { hotkey: "arrowup", highlighted: ["second", "third"] }, + { hotkey: "arrowright", highlighted: ["second", "third", "third-first"] }, + { hotkey: "escape", highlighted: ["second", "third"] }, + { hotkey: "escape", highlighted: ["second"] }, + { hotkey: "escape", highlighted: [] }, ]; for (const [stepIndex, step] of scenarioSteps.entries()) { @@ -759,7 +755,9 @@ QUnit.module("Components", ({ beforeEach }) => { await nextTick(); if (step.highlighted !== undefined) { let index = 0; - const activeElements = parent.el.querySelectorAll(".focus"); + const activeElements = [...parent.el.querySelectorAll(".focus")].map((el) => + el.classList.contains("dropdown-toggle") ? el.parentElement : el + ); assert.ok( activeElements.length === step.highlighted.length, `step ${stepIndex}: all active elements to check are found` @@ -781,7 +779,7 @@ QUnit.module("Components", ({ beforeEach }) => { Parent.template = owl.tags.xml` O - + O @@ -789,7 +787,7 @@ QUnit.module("Components", ({ beforeEach }) => { serviceRegistry.add("localization", makeFakeLocalizationService({ direction: "rtl" })); env = await makeTestEnv(); parent = await mount(Parent, { env, target }); - assert.containsNone(parent.el, ".o_dropdown_menu", "menus are closed at start"); + assert.containsNone(parent.el, ".dropdown-menu", "menus are closed at start"); // Highlighting and selecting items const scenarioSteps = [ @@ -805,7 +803,9 @@ QUnit.module("Components", ({ beforeEach }) => { await nextTick(); if (step.highlighted !== undefined) { let index = 0; - const activeElements = parent.el.querySelectorAll(".focus"); + const activeElements = [...parent.el.querySelectorAll(".focus")].map((el) => + el.classList.contains("dropdown-toggle") ? el.parentElement : el + ); assert.ok( activeElements.length === step.highlighted.length, `step ${stepIndex}: all active elements to check are found` @@ -817,6 +817,35 @@ QUnit.module("Components", ({ beforeEach }) => { } }); + QUnit.test( + "multi-level dropdown: mouseentering a dropdown item should close any subdropdown", + async (assert) => { + assert.expect(4); + class Parent extends owl.Component {} + Parent.template = owl.tags.xml` + + + + + `; + env = await makeTestEnv(); + parent = await mount(Parent, { env, target }); + assert.containsNone(parent.el, ".dropdown-menu", "menus are closed at start"); + + // Open main dropdown + await click(parent.el, ".main"); + assert.containsOnce(parent.el, ".dropdown-menu", "1st menu is opened"); + + // Mouse enter sub dropdown + await mouseEnter(parent.el, ".sub"); + assert.containsN(parent.el, ".dropdown-menu", 2, "all menus are opened"); + + // Mouse enter the adjacent dropdown item + await mouseEnter(parent.el, ".item"); + assert.containsOnce(parent.el, ".dropdown-menu", "only 1st menu is opened"); + } + ); + QUnit.test("multi-level dropdown: unsubscribe all keynav when root close", async (assert) => { assert.expect(14); class Parent extends owl.Component {} @@ -840,35 +869,41 @@ QUnit.module("Components", ({ beforeEach }) => { }, }); parent = await mount(Parent, { env, target }); - assert.containsNone(parent.el, ".o_dropdown_menu", "menus are closed at start"); + assert.containsNone(parent.el, ".dropdown-menu", "menus are closed at start"); assert.strictEqual(hotkeyRegistrationsCount, 0, "no hotkey registered"); // Open dropdowns one by one await click(parent.el, ".first"); - assert.containsOnce(parent.el, ".o_dropdown_menu", "1st menu is opened"); + assert.containsOnce(parent.el, ".dropdown-menu", "1st menu is opened"); assert.strictEqual(hotkeyRegistrationsCount, 10, "1st menu hotkeys registered"); - await click(parent.el, ".second"); - assert.containsN(parent.el, ".o_dropdown_menu", 2, "2nd menu is also opened"); + await mouseEnter(parent.el, ".second"); + assert.containsN(parent.el, ".dropdown-menu", 2, "2nd menu is also opened"); assert.strictEqual(hotkeyRegistrationsCount, 20, "2nd menu hotkeys also registered"); - await click(parent.el, ".third"); - assert.containsN(parent.el, ".o_dropdown_menu", 3, "3rd menu is also opened"); + await mouseEnter(parent.el, ".third"); + assert.containsN(parent.el, ".dropdown-menu", 3, "3rd menu is also opened"); assert.strictEqual(hotkeyRegistrationsCount, 30, "3rd menu hotkeys also registered"); - // Close second - await click(parent.el, ".second"); - assert.containsN(parent.el, ".o_dropdown_menu", 1, "only 1st menu stay opened"); - assert.strictEqual(hotkeyRegistrationsCount, 10, "only 1st menu hotkeys registered"); + // Close third + triggerHotkey("escape"); + await nextTick(); + assert.containsN(parent.el, ".dropdown-menu", 2, "two menus still opened"); + assert.strictEqual(hotkeyRegistrationsCount, 20, "two menus hotkeys registered"); // Reopen second - await click(parent.el, ".second"); - assert.containsN(parent.el, ".o_dropdown_menu", 2, "2nd menu is also opened"); - assert.strictEqual(hotkeyRegistrationsCount, 20, "2nd menu hotkeys also registered"); + await mouseEnter(parent.el, ".third"); + assert.containsN(parent.el, ".dropdown-menu", 3, "3rd menu is also opened"); + assert.strictEqual(hotkeyRegistrationsCount, 30, "3rd menu hotkeys also registered"); - // Close first - await click(parent.el, ".first"); - assert.containsNone(parent.el, ".o_dropdown_menu", "all menus are now closed"); + // Close third, second and first + triggerHotkey("escape"); + await nextTick(); + triggerHotkey("escape"); + await nextTick(); + triggerHotkey("escape"); + await nextTick(); + assert.containsNone(parent.el, ".dropdown-menu", "all menus are now closed"); assert.strictEqual(hotkeyRegistrationsCount, 0, "no hotkey registration left"); }); }); diff --git a/addons/web/static/tests/helpers/utils.js b/addons/web/static/tests/helpers/utils.js index c128add7b7d..204b4c9b30e 100644 --- a/addons/web/static/tests/helpers/utils.js +++ b/addons/web/static/tests/helpers/utils.js @@ -228,6 +228,10 @@ export function click(el, selector) { return triggerEvent(el, selector, "click", { bubbles: true, cancelable: true }); } +export async function mouseEnter(el, selector) { + return triggerEvent(el, selector, "mouseenter"); +} + /** * Triggers an hotkey properly disregarding the operating system. * diff --git a/addons/web/static/tests/legacy/components/action_menus_tests.js b/addons/web/static/tests/legacy/components/action_menus_tests.js index 2cc2f46f5db..ab2aac9be9c 100644 --- a/addons/web/static/tests/legacy/components/action_menus_tests.js +++ b/addons/web/static/tests/legacy/components/action_menus_tests.js @@ -56,16 +56,16 @@ odoo.define('web.action_menus_tests', function (require) { props: this.props, }); - const dropdowns = actionMenus.el.getElementsByClassName('o_dropdown'); + const dropdowns = actionMenus.el.getElementsByClassName('dropdown'); assert.strictEqual(dropdowns.length, 2, "ActionMenus should contain 2 menus"); assert.strictEqual(dropdowns[0].querySelector('.o_dropdown_title').innerText.trim(), "Print"); assert.strictEqual(dropdowns[1].querySelector('.o_dropdown_title').innerText.trim(), "Action"); - assert.containsNone(actionMenus, '.o_dropdown_menu'); + assert.containsNone(actionMenus, '.dropdown-menu'); await testUtils.controlPanel.toggleActionMenu(actionMenus, "Action"); - assert.containsOnce(actionMenus, '.o_dropdown_menu'); - assert.containsN(actionMenus, '.o_dropdown_menu .o_menu_item', 4); + assert.containsOnce(actionMenus, '.dropdown-menu'); + assert.containsN(actionMenus, '.dropdown-menu .o_menu_item', 4); const actionsTexts = [...dropdowns[1].querySelectorAll('.o_menu_item')].map(el => el.innerText.trim()); assert.deepEqual(actionsTexts, [ "Boil'em", @@ -76,12 +76,12 @@ odoo.define('web.action_menus_tests', function (require) { await testUtils.controlPanel.toggleActionMenu(actionMenus, "Print"); - assert.containsOnce(actionMenus, '.o_dropdown_menu'); - assert.containsN(actionMenus, '.o_dropdown_menu .o_menu_item', 1); + assert.containsOnce(actionMenus, '.dropdown-menu'); + assert.containsN(actionMenus, '.dropdown-menu .o_menu_item', 1); await testUtils.controlPanel.toggleActionMenu(actionMenus, "Print"); - assert.containsNone(actionMenus, '.o_dropdown_menu'); + assert.containsNone(actionMenus, '.dropdown-menu'); actionMenus.destroy(); }); diff --git a/addons/web/static/tests/legacy/components/dropdown_menu_tests.js b/addons/web/static/tests/legacy/components/dropdown_menu_tests.js index 3aff0ae14ea..af65c970eca 100644 --- a/addons/web/static/tests/legacy/components/dropdown_menu_tests.js +++ b/addons/web/static/tests/legacy/components/dropdown_menu_tests.js @@ -42,7 +42,7 @@ odoo.define('web.dropdown_menu_tests', function (require) { }); assert.strictEqual(dropdown.el.querySelector('button').innerText.trim(), "Dropdown"); - assert.containsNone(dropdown, 'ul.o_dropdown_menu'); + assert.containsNone(dropdown, '.dropdown-menu'); await testUtils.dom.click(dropdown.el.querySelector('button')); @@ -57,12 +57,12 @@ odoo.define('web.dropdown_menu_tests', function (require) { for (const dropdownEl of dropdownElements) { await testUtils.dom.click(dropdownEl); } - assert.containsOnce(dropdown, 'ul.o_dropdown_menu', + assert.containsOnce(dropdown, '.dropdown-menu', "Clicking on any item of the dropdown should not close it"); await testUtils.dom.click(document.body); - assert.containsNone(dropdown, 'ul.o_dropdown_menu', + assert.containsNone(dropdown, '.dropdown-menu', "Clicking outside of the dropdown should close it"); dropdown.destroy(); @@ -349,7 +349,7 @@ odoo.define('web.dropdown_menu_tests', function (require) { await navigate('Escape', true); // Close the dropdown - assert.containsNone(dropdown, 'ul.o_dropdown_menu', "Dropdown should be folded"); + assert.containsNone(dropdown, '.dropdown-menu', "Dropdown should be folded"); dropdown.destroy(); }); @@ -373,25 +373,25 @@ odoo.define('web.dropdown_menu_tests', function (require) { const parent = new Parent(); await parent.mount(testUtils.prepareTarget(), { position: 'first-child' }); - const [menu1, menu2] = parent.el.querySelectorAll('.o_dropdown'); + const [menu1, menu2] = parent.el.querySelectorAll('.dropdown'); - assert.containsNone(parent, '.o_dropdown_menu'); + assert.containsNone(parent, '.dropdown-menu'); await testUtils.dom.click(menu1.querySelector('button')); - assert.containsOnce(parent, '.o_dropdown_menu'); - assert.containsOnce(parent, '.o_dropdown.first .o_dropdown_menu'); + assert.containsOnce(parent, '.dropdown-menu'); + assert.containsOnce(parent, '.dropdown.first .dropdown-menu'); await testUtils.dom.click(menu2.querySelector('button')); - assert.containsOnce(parent, '.o_dropdown_menu'); - assert.containsOnce(parent, '.o_dropdown.second .o_dropdown_menu'); + assert.containsOnce(parent, '.dropdown-menu'); + assert.containsOnce(parent, '.dropdown.second .dropdown-menu'); await testUtils.dom.click(menu2.querySelector('.o_menu_item a')); await testUtils.dom.click(menu1.querySelector('button')); - assert.containsOnce(parent, '.o_dropdown_menu'); - assert.containsOnce(parent, '.o_dropdown.first .o_dropdown_menu'); + assert.containsOnce(parent, '.dropdown-menu'); + assert.containsOnce(parent, '.dropdown.first .dropdown-menu'); parent.destroy(); }); @@ -419,7 +419,7 @@ odoo.define('web.dropdown_menu_tests', function (require) { const parent = new Parent(); await parent.mount(testUtils.prepareTarget(), { position: "first-child" }); - const menu = parent.el.querySelector(".o_dropdown"); + const menu = parent.el.querySelector(".dropdown"); assert.doesNotHaveClass(menu, "show", "dropdown should not be open"); await testUtils.dom.click(menu.querySelector("button")); diff --git a/addons/web/static/tests/legacy/control_panel/comparison_menu_tests.js b/addons/web/static/tests/legacy/control_panel/comparison_menu_tests.js index 82d4fb2128c..ab697122950 100644 --- a/addons/web/static/tests/legacy/control_panel/comparison_menu_tests.js +++ b/addons/web/static/tests/legacy/control_panel/comparison_menu_tests.js @@ -1,6 +1,8 @@ odoo.define('web.comparison_menu_tests', function (require) { "use strict"; + const { browser } = require('@web/core/browser/browser'); + const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const cpHelpers = require('@web/../tests/search/helpers'); const { createControlPanel, @@ -27,6 +29,9 @@ odoo.define('web.comparison_menu_tests', function (require) { fields: this.fields, searchMenuTypes, }; + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); }, }, function () { @@ -42,8 +47,8 @@ odoo.define('web.comparison_menu_tests', function (require) { }; const controlPanel = await createControlPanel(params); - assert.containsOnce(controlPanel, ".o_dropdown.o_filter_menu"); - assert.containsNone(controlPanel, ".o_dropdown.o_comparison_menu"); + assert.containsOnce(controlPanel, ".dropdown.o_filter_menu"); + assert.containsNone(controlPanel, ".dropdown.o_comparison_menu"); await cpHelpers.toggleFilterMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, "Birthday"); @@ -55,7 +60,7 @@ odoo.define('web.comparison_menu_tests', function (require) { await cpHelpers.toggleComparisonMenu(controlPanel); const comparisonOptions = [...controlPanel.el.querySelectorAll( - '.o_comparison_menu li' + '.o_comparison_menu .o_menu_item' )]; assert.strictEqual(comparisonOptions.length, 2); assert.deepEqual( diff --git a/addons/web/static/tests/legacy/control_panel/custom_filter_item_tests.js b/addons/web/static/tests/legacy/control_panel/custom_filter_item_tests.js index 95b8af4338f..9f715adc989 100644 --- a/addons/web/static/tests/legacy/control_panel/custom_filter_item_tests.js +++ b/addons/web/static/tests/legacy/control_panel/custom_filter_item_tests.js @@ -10,6 +10,10 @@ odoo.define('web.filter_menu_generator_tests', function (require) { const cpHelpers = require('@web/../tests/search/helpers'); const { createComponent } = testUtils; + const toggleAddCustomFilterStandalone = async (el) => { + await cpHelpers.toggleMenu(el, "Add Custom Filter"); + }; + QUnit.module('Components', { beforeEach: function () { this.fields = { @@ -42,7 +46,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { assert.hasClass(cfi.el, 'o_add_custom_filter_menu'); assert.strictEqual(cfi.el.children.length, 1); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); // Single condition assert.containsOnce(cfi, '.o_filter_condition'); @@ -82,7 +86,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { }); // Open custom filter form - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); // Retrieve second selectable values for field and operator dropdowns const fieldSecondValue = cfi.el.querySelector('.o_generator_menu_field option:nth-of-type(2)').value; @@ -137,7 +141,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { domain: '[["binary_field","!=",False]]', type: 'filter', }]; - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'binary_field'); await cpHelpers.applyFilter(cfi); @@ -147,7 +151,6 @@ odoo.define('web.filter_menu_generator_tests', function (require) { domain: '[["binary_field","=",False]]', type: 'filter', }]; - await cpHelpers.toggleAddCustomFilter(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'binary_field'); await cpHelpers.editConditionOperator(cfi, 0, '='); await cpHelpers.applyFilter(cfi); @@ -180,7 +183,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { domain: '[["color","=","black"]]', type: 'filter', }]; - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'color'); await cpHelpers.applyFilter(cfi); @@ -190,7 +193,6 @@ odoo.define('web.filter_menu_generator_tests', function (require) { domain: '[["color","=","white"]]', type: 'filter', }]; - await cpHelpers.toggleAddCustomFilter(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'color'); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_value select'), 'white'); await cpHelpers.applyFilter(cfi); @@ -199,7 +201,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { }); QUnit.test('adding a simple filter works', async function (assert) { - assert.expect(6); + assert.expect(7); delete this.fields.date_field; @@ -221,13 +223,14 @@ odoo.define('web.filter_menu_generator_tests', function (require) { env: { searchModel }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'boolean_field'); await cpHelpers.applyFilter(cfi); - // The only thing visible should be the button 'Add Custome Filter'; - assert.strictEqual(cfi.el.children.length, 1); - assert.containsOnce(cfi, 'button.o_dropdown_toggler'); + // The only things visible should be the button 'Add Custom Filter' and the menu; + assert.strictEqual(cfi.el.children.length, 2); + assert.containsOnce(cfi, 'button.dropdown-toggle'); + assert.containsOnce(cfi, '.dropdown-menu'); cfi.destroy(); }); @@ -262,7 +265,6 @@ odoo.define('web.filter_menu_generator_tests', function (require) { async function testValue(operator, value) { // open filter menu generator, select ID field, switch operator, type value, then click apply - await cpHelpers.toggleAddCustomFilter(cfi); await cpHelpers.editConditionField(cfi, 0, 'id_field'); await cpHelpers.editConditionOperator(cfi, 0, operator); await cpHelpers.editConditionValue(cfi, 0, @@ -271,6 +273,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { await cpHelpers.applyFilter(cfi); } + await toggleAddCustomFilterStandalone(cfi); for (const domain of [...expectedDomains]) { await testValue(domain[0][1], domain[0][2]); } @@ -314,7 +317,6 @@ odoo.define('web.filter_menu_generator_tests', function (require) { async function testValue(value) { // open filter menu generator, select trululu field and enter string `a`, then click apply - await cpHelpers.toggleAddCustomFilter(cfi); await cpHelpers.editConditionField(cfi, 0, 'many2one_field'); await cpHelpers.editConditionValue(cfi, 0, value @@ -322,6 +324,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { await cpHelpers.applyFilter(cfi); } + await toggleAddCustomFilterStandalone(cfi); for (const value of testedValues) { await testValue(value); } @@ -359,7 +362,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { env: { searchModel }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'date_time_field'); assert.strictEqual(cfi.el.querySelector('.o_generator_menu_field').value, 'date_time_field'); @@ -402,7 +405,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { env: { searchModel }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'date_time_field'); assert.strictEqual(cfi.el.querySelector('.o_generator_menu_field').value, 'date_time_field'); @@ -428,7 +431,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await cpHelpers.addCondition(cfi); await cpHelpers.editConditionField(cfi, 0, "float_field"); @@ -477,7 +480,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await cpHelpers.addCondition(cfi); await cpHelpers.editConditionField(cfi, 0, "float_field"); @@ -542,7 +545,7 @@ odoo.define('web.filter_menu_generator_tests', function (require) { env: { searchModel }, }); - await cpHelpers.toggleAddCustomFilter(cfi); + await toggleAddCustomFilterStandalone(cfi); await cpHelpers.addCondition(cfi); await cpHelpers.addCondition(cfi); await cpHelpers.addCondition(cfi); diff --git a/addons/web/static/tests/legacy/control_panel/custom_group_by_item_tests.js b/addons/web/static/tests/legacy/control_panel/custom_group_by_item_tests.js index 7fbca38fcde..baed11f3cdc 100644 --- a/addons/web/static/tests/legacy/control_panel/custom_group_by_item_tests.js +++ b/addons/web/static/tests/legacy/control_panel/custom_group_by_item_tests.js @@ -29,21 +29,21 @@ odoo.define('web.groupby_menu_generator_tests', function (require) { assert.hasClass(cgi.el, 'o_add_custom_group_menu'); assert.strictEqual(cgi.el.children.length, 1); - await testUtils.dom.click(cgi.el.querySelector('.o_add_custom_group_menu .o_dropdown_toggler')); + await testUtils.dom.click(cgi.el.querySelector('.o_add_custom_group_menu .dropdown-toggle')); // Single select node with a single option - assert.containsOnce(cgi, 'li > select'); - assert.strictEqual(cgi.el.querySelector('li > select option').innerText.trim(), + assert.containsOnce(cgi, 'div > select'); + assert.strictEqual(cgi.el.querySelector('div > select option').innerText.trim(), "Super Date"); // Button apply - assert.containsOnce(cgi, 'li > button.btn.btn-primary'); + assert.containsOnce(cgi, 'div > button.btn.btn-primary'); cgi.destroy(); }); QUnit.test('select a field name in Add Custom Group menu properly trigger the corresponding field', async function (assert) { - assert.expect(4); + assert.expect(5); const fields = [ { sortable: true, name: 'candlelight', string: 'Candlelight', type: 'boolean' }, @@ -61,12 +61,13 @@ odoo.define('web.groupby_menu_generator_tests', function (require) { env: { searchModel }, }); - await testUtils.dom.click(cgi.el.querySelector('.o_add_custom_group_menu .o_dropdown_toggler')); - await testUtils.dom.click(cgi.el.querySelector('li > button.btn.btn-primary')); + await testUtils.dom.click(cgi.el.querySelector('.o_add_custom_group_menu .dropdown-toggle')); + await testUtils.dom.click(cgi.el.querySelector('div > button.btn.btn-primary')); - // The only thing visible should be the button 'Add Custome Group'; - assert.strictEqual(cgi.el.children.length, 1); - assert.containsOnce(cgi, '.o_dropdown_toggler'); + // The only things visible should be the button 'Add Custome Group' and the dropdown menu; + assert.strictEqual(cgi.el.children.length, 2); + assert.containsOnce(cgi, '.dropdown-toggle'); + assert.containsOnce(cgi, '.dropdown-menu'); cgi.destroy(); }); diff --git a/addons/web/static/tests/legacy/control_panel/favorite_menu_tests.js b/addons/web/static/tests/legacy/control_panel/favorite_menu_tests.js index f047a98ee61..7434c619cda 100644 --- a/addons/web/static/tests/legacy/control_panel/favorite_menu_tests.js +++ b/addons/web/static/tests/legacy/control_panel/favorite_menu_tests.js @@ -1,6 +1,9 @@ odoo.define('web.favorite_menu_tests', function (require) { "use strict"; + const { browser } = require('@web/core/browser/browser'); + const { patchWithCleanup } = require('@web/../tests/helpers/utils'); + const FormView = require('web.FormView'); const testUtils = require('web.test_utils'); @@ -19,6 +22,9 @@ odoo.define('web.favorite_menu_tests', function (require) { float_field: { string: "Float", type: "float", group_operator: 'sum' }, foo: { string: "Foo", type: "char", store: true, sortable: true }, }; + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); }, }, function () { @@ -39,7 +45,7 @@ odoo.define('web.favorite_menu_tests', function (require) { await cpHelpers.toggleFavoriteMenu(controlPanel); assert.containsNone(controlPanel, '.dropdown-divider'); assert.containsOnce(controlPanel, '.o_add_favorite'); - assert.strictEqual(controlPanel.el.querySelector('.o_add_favorite > button span').innerText.trim(), + assert.strictEqual(controlPanel.el.querySelector('.o_add_favorite > button').innerText.trim(), "Save current search"); await cpHelpers.toggleSaveFavorite(controlPanel); @@ -288,7 +294,7 @@ odoo.define('web.favorite_menu_tests', function (require) { // confirm deletion await testUtils.dom.click(document.querySelector('div.o_dialog footer button')); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); - const itemEls = controlPanel.el.querySelectorAll('.o_favorite_menu .o_dropdown_item'); + const itemEls = controlPanel.el.querySelectorAll('.o_favorite_menu .dropdown-item'); assert.deepEqual([...itemEls].map(e => e.innerText.trim()), ["Save current search"]); controlPanel.destroy(); diff --git a/addons/web/static/tests/legacy/control_panel/filter_menu_tests.js b/addons/web/static/tests/legacy/control_panel/filter_menu_tests.js index e1f52fbef5d..1fa900093e6 100644 --- a/addons/web/static/tests/legacy/control_panel/filter_menu_tests.js +++ b/addons/web/static/tests/legacy/control_panel/filter_menu_tests.js @@ -1,6 +1,8 @@ odoo.define('web.filter_menu_tests', function (require) { "use strict"; + const { browser } = require('@web/core/browser/browser'); + const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const testUtils = require('web.test_utils'); const cpHelpers = require('@web/../tests/search/helpers'); @@ -15,6 +17,9 @@ odoo.define('web.filter_menu_tests', function (require) { date_field: { string: "Date", type: "date", store: true, sortable: true, searchable: true }, foo: { string: "Foo", type: "char", store: true, sortable: true }, }; + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); }, }, function () { @@ -52,7 +57,7 @@ odoo.define('web.filter_menu_tests', function (require) { await cpHelpers.toggleFilterMenu(controlPanel); assert.containsOnce(controlPanel, '.o_menu_item'); assert.containsOnce(controlPanel, '.dropdown-divider'); - assert.containsOnce(controlPanel, 'li.o_add_custom_filter_menu'); + assert.containsOnce(controlPanel, 'div.o_add_custom_filter_menu'); controlPanel.destroy(); }); @@ -225,7 +230,7 @@ odoo.define('web.filter_menu_tests', function (require) { await cpHelpers.toggleFilterMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, "Date"); - const optionEls = controlPanel.el.querySelectorAll('li.o_item_option'); + const optionEls = controlPanel.el.querySelectorAll('span.o_item_option'); // default filter should be activated with the global default period 'this_month' const { domain } = controlPanel.getQuery(); diff --git a/addons/web/static/tests/legacy/control_panel/groupby_menu_tests.js b/addons/web/static/tests/legacy/control_panel/groupby_menu_tests.js index a3d2e638923..648a84b7a14 100644 --- a/addons/web/static/tests/legacy/control_panel/groupby_menu_tests.js +++ b/addons/web/static/tests/legacy/control_panel/groupby_menu_tests.js @@ -1,6 +1,8 @@ odoo.define('web.groupby_menu_tests', function (require) { "use strict"; + const { browser } = require('@web/core/browser/browser'); + const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const testUtils = require('web.test_utils'); const cpHelpers = require('@web/../tests/search/helpers'); @@ -18,6 +20,9 @@ odoo.define('web.groupby_menu_tests', function (require) { foo: { string: "Foo", type: "char", store: true, sortable: true }, m2m: { string: "Many2Many", type: "many2many", store: true}, }; + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); }, }, function () { @@ -210,7 +215,7 @@ odoo.define('web.groupby_menu_tests', function (require) { await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, 0); - const optionEls = controlPanel.el.querySelectorAll('li.o_item_option'); + const optionEls = controlPanel.el.querySelectorAll('span.o_item_option'); // default groupby should be activated with the default inteval 'week' const { groupBy } = controlPanel.getQuery(); diff --git a/addons/web/static/tests/legacy/control_panel/search_bar_tests.js b/addons/web/static/tests/legacy/control_panel/search_bar_tests.js index cf4afa89cb5..65095939e3e 100644 --- a/addons/web/static/tests/legacy/control_panel/search_bar_tests.js +++ b/addons/web/static/tests/legacy/control_panel/search_bar_tests.js @@ -8,6 +8,8 @@ import Registry from "web.Registry"; import SearchBar from "web.SearchBar"; import { registry } from "@web/core/registry"; import * as cpHelpers from "@web/../tests/search/helpers"; +import { patchWithCleanup } from "@web/../tests/helpers/utils"; +import { browser } from "@web/core/browser/browser"; let serverData; QUnit.module("Search Bar (legacy)", (hooks) => { @@ -74,6 +76,7 @@ QUnit.module("Search Bar (legacy)", (hooks) => { QUnit.test("navigation with facets", async function (assert) { assert.expect(4); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const webClient = await createWebClient({ serverData }); await doAction(webClient, 1); diff --git a/addons/web/static/tests/legacy/fields/relational_fields/field_many2one_tests.js b/addons/web/static/tests/legacy/fields/relational_fields/field_many2one_tests.js index 620c25d8c40..5ef7d10c595 100644 --- a/addons/web/static/tests/legacy/fields/relational_fields/field_many2one_tests.js +++ b/addons/web/static/tests/legacy/fields/relational_fields/field_many2one_tests.js @@ -10,6 +10,8 @@ var StandaloneFieldManagerMixin = require('web.StandaloneFieldManagerMixin'); var testUtils = require('web.test_utils'); var Widget = require('web.Widget'); +const { browser } = require('@web/core/browser/browser'); +const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const cpHelpers = require('@web/../tests/search/helpers'); var createView = testUtils.createView; @@ -544,6 +546,12 @@ QUnit.module('fields', {}, function () { display_name: "Partner 9", }); this.data.partner.fields.datetime.searchable = true; + + // add custom filter needs this + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); + var form = await createView({ View: FormView, model: 'partner', @@ -3126,21 +3134,21 @@ QUnit.module('fields', {}, function () { let filterMenuCss = '.o_search_options > .o_filter_menu'; let groupByMenuCss = '.o_search_options > .o_group_by_menu'; - await testUtils.dom.click(document.querySelector(`${filterMenuCss} > .o_dropdown_toggler`)); + await testUtils.dom.click(document.querySelector(`${filterMenuCss} > .dropdown-toggle`)); assert.hasClass(document.querySelector(filterMenuCss), 'show'); - assert.isVisible(document.querySelector(`${filterMenuCss} > .o_dropdown_menu`), + 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} > .o_dropdown_menu`), + assert.isNotVisible(document.querySelector(`${groupByMenuCss} > .dropdown-menu`), "the Group by dropdown menu should be not visible"); - await testUtils.dom.click(document.querySelector(`${groupByMenuCss} > .o_dropdown_toggler`)); + await testUtils.dom.click(document.querySelector(`${groupByMenuCss} > .dropdown-toggle`)); assert.hasClass(document.querySelector(groupByMenuCss), 'show'); - assert.isVisible(document.querySelector(`${groupByMenuCss} > .o_dropdown_menu`), + 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} > .o_dropdown_menu`), + assert.isNotVisible(document.querySelector(`${filterMenuCss} > .dropdown-menu`), "the filter dropdown menu should be not visible"); $fakeDialog.remove(); diff --git a/addons/web/static/tests/legacy/helpers/test_utils_control_panel.js b/addons/web/static/tests/legacy/helpers/test_utils_control_panel.js index a4b6e2d47fa..f0b4391b478 100644 --- a/addons/web/static/tests/legacy/helpers/test_utils_control_panel.js +++ b/addons/web/static/tests/legacy/helpers/test_utils_control_panel.js @@ -14,7 +14,7 @@ odoo.define('web.test_utils_control_panel', function (require) { * @returns {Promise} */ async function toggleMenu(el, menuFinder) { - const menu = findItem(el, `.o_dropdown > button`, menuFinder); + const menu = findItem(el, `.dropdown > button`, menuFinder); await click(menu); } @@ -67,7 +67,7 @@ odoo.define('web.test_utils_control_panel', function (require) { * @returns {string[]} */ function getMenuItemTexts(el) { - return [...getNode(el).querySelectorAll(`.o_dropdown ul .o_menu_item`)].map( + return [...getNode(el).querySelectorAll(`.dropdown ul .o_menu_item`)].map( e => e.innerText.trim() ); } diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js index c723a5db7a0..cf9b2b61b77 100644 --- a/addons/web/static/tests/legacy/views/form_tests.js +++ b/addons/web/static/tests/legacy/views/form_tests.js @@ -6252,8 +6252,8 @@ QUnit.module('Views', { }, }); - assert.containsNone(form, '.o_cp_action_menus .o_dropdown:contains(Print)'); - assert.containsOnce(form, '.o_cp_action_menus .o_dropdown:contains(Action)'); + assert.containsNone(form, '.o_cp_action_menus .dropdown:contains(Print)'); + assert.containsOnce(form, '.o_cp_action_menus .dropdown:contains(Action)'); await testUtils.controlPanel.toggleActionMenu(form); diff --git a/addons/web/static/tests/legacy/views/graph_tests.js b/addons/web/static/tests/legacy/views/graph_tests.js index 29312aa9b1e..321c4b30d17 100644 --- a/addons/web/static/tests/legacy/views/graph_tests.js +++ b/addons/web/static/tests/legacy/views/graph_tests.js @@ -5,7 +5,8 @@ const searchUtils = require('web.searchUtils'); const GraphView = require('web.GraphView'); const testUtils = require('web.test_utils'); const { sortBy } = require('web.utils'); -const { legacyExtraNextTick } = require("@web/../tests/helpers/utils"); +const { browser } = require('@web/core/browser/browser'); +const { legacyExtraNextTick, patchWithCleanup } = require("@web/../tests/helpers/utils"); const { createWebClient, doAction } = require('@web/../tests/webclient/helpers'); const legacyViewRegistry = require("web.view_registry"); const { registry } = require("@web/core/registry"); @@ -1615,6 +1616,8 @@ QUnit.module('Views', { this.unpatchDate = patchDate(2016, 11, 20, 1, 0, 0); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); + const graph = await createView({ View: GraphView, model: "foo", diff --git a/addons/web/static/tests/legacy/views/list_tests.js b/addons/web/static/tests/legacy/views/list_tests.js index bfa5a6eb3e9..ab1356f30a1 100644 --- a/addons/web/static/tests/legacy/views/list_tests.js +++ b/addons/web/static/tests/legacy/views/list_tests.js @@ -228,7 +228,7 @@ QUnit.module('Views', { assert.ok(list.$('tbody td.o_list_record_selector').length, 'should have at least one record'); await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); - assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus .o_dropdown_menu'); + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus .dropdown-menu'); list.destroy(); }); @@ -1405,15 +1405,15 @@ QUnit.module('Views', { await testUtils.dom.click(list.$('.o_group_header:first')); // open first group await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_list_record_selector input')); assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus'); - assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus .o_dropdown', + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus .dropdown', "should not have dropdown as delete item is not there"); // reload withoud grouping by m2m await list.reload({groupBy: []}); await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_list_record_selector input')); assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus'); - assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus .o_dropdown'); - await testUtils.dom.click(list.$('div.o_control_panel .o_cp_action_menus .o_dropdown button')); + assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus .dropdown'); + await testUtils.dom.click(list.$('div.o_control_panel .o_cp_action_menus .dropdown button')); assert.deepEqual( [...list.el.querySelectorAll('.o_cp_action_menus .o_menu_item')].map((el) => el.innerText), ["Delete"] @@ -2007,7 +2007,7 @@ QUnit.module('Views', { "create button should be invisible"); assert.isVisible($(webClient.el).find('.o_list_button_save'), "save button should be visible"); - await testUtils.dom.click($(webClient.el).find('.o_dropdown_toggler:contains("Group By")')); + await testUtils.dom.click($(webClient.el).find('.dropdown-toggle:contains("Group By")')); await testUtils.dom.click($(webClient.el).find('.o_group_by_menu .o_menu_item:contains("candle")')); assert.isNotVisible($(webClient.el).find('.o_list_button_add'), "create button should be invisible"); @@ -3957,8 +3957,8 @@ QUnit.module('Views', { await click(webClient.el.querySelector('tbody td.o_list_record_selector input')); assert.containsOnce(webClient, '.o_cp_action_menus', 'sidebar should be visible'); - await click(webClient.el.querySelector('.o_cp_action_menus .o_dropdown_toggler')); - const archiveItem = [...webClient.el.querySelectorAll('.o_cp_action_menus .o_dropdown_menu li > a')] + await click(webClient.el.querySelector('.o_cp_action_menus .dropdown-toggle')); + const archiveItem = [...webClient.el.querySelectorAll('.o_cp_action_menus .dropdown-menu li > a')] .filter((elem) => elem.textContent === 'Archive'); await click(archiveItem[0]); assert.strictEqual(document.querySelectorAll('.modal').length, 1, @@ -9497,7 +9497,7 @@ QUnit.module('Views', { // delete a record await testUtils.dom.click(list.$('tbody .o_data_row:first td.o_list_record_selector:first input')); checkSearchRead = true; - await testUtils.dom.click(list.$('.o_dropdown_toggler:contains(Action)')); + await testUtils.dom.click(list.$('.dropdown-toggle:contains(Action)')); await testUtils.dom.click(list.$('a:contains(Delete)')); await testUtils.dom.click($('body .modal button span:contains(Ok)')); assert.strictEqual(list.$('.o_pager_counter').text().trim(), '1-3 / 3', @@ -9547,7 +9547,7 @@ QUnit.module('Views', { // delete a record await testUtils.dom.click(list.$('tbody .o_data_row:first td.o_list_record_selector:first input')); checkSearchRead = true; - await testUtils.dom.click(list.$('.o_dropdown_toggler:contains(Action)')); + await testUtils.dom.click(list.$('.dropdown-toggle:contains(Action)')); await testUtils.dom.click(list.$('a:contains(Delete)')); await testUtils.dom.click($('body .modal button span:contains(Ok)')); @@ -9597,7 +9597,7 @@ QUnit.module('Views', { assert.containsOnce(list, '.o_cp_action_menus', 'sidebar should be available'); // archive all records of current page - await testUtils.dom.click(list.$('.o_cp_action_menus .o_dropdown_toggler:contains(Action)')); + await testUtils.dom.click(list.$('.o_cp_action_menus .dropdown-toggle:contains(Action)')); await testUtils.dom.click(list.$('a:contains(Archive)')); assert.strictEqual($('.modal').length, 1, 'a confirm modal should be displayed'); diff --git a/addons/web/static/tests/legacy/views/pivot_tests.js b/addons/web/static/tests/legacy/views/pivot_tests.js index 0de856711db..8a85ea42361 100644 --- a/addons/web/static/tests/legacy/views/pivot_tests.js +++ b/addons/web/static/tests/legacy/views/pivot_tests.js @@ -6,6 +6,8 @@ var PivotView = require('web.PivotView'); const PivotController = require("web.PivotController"); var testUtils = require('web.test_utils'); var testUtilsDom = require('web.test_utils_dom'); +const { browser } = require('@web/core/browser/browser'); +const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const { registry } = require('@web/core/registry'); const legacyViewRegistry = require('web.view_registry'); @@ -120,6 +122,7 @@ QUnit.module('Views', { }; serverData = { models: this.data }; + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); }, }, function () { QUnit.module('Legacy PivotView'); @@ -622,24 +625,24 @@ QUnit.module('Views', { // click on closed header to open dropdown await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - assert.containsOnce(pivot, ".o_legacy_pivot .o_dropdown_menu"); + assert.containsOnce(pivot, ".o_legacy_pivot .dropdown-menu"); assert.strictEqual( - pivot.el.querySelector(".o_legacy_pivot .o_dropdown_menu").innerText.replace(/\s/g, ""), + pivot.el.querySelector(".o_legacy_pivot .dropdown-menu").innerText.replace(/\s/g, ""), "CompanyTypeCustomerDateOtherProductProductbar" ); // open the Date sub dropdown - await testUtils.dom.click(pivot.el.querySelector(".o_legacy_pivot .o_dropdown_menu .o_dropdown_toggler.o_menu_item")); + await testUtils.dom.triggerEvent(pivot.el.querySelector(".o_legacy_pivot .dropdown-menu .dropdown-toggle.o_menu_item"), "mouseenter"); assert.strictEqual( pivot.el - .querySelector(".o_legacy_pivot .o_dropdown_menu .o_dropdown_menu") + .querySelector(".o_legacy_pivot .dropdown-menu .dropdown-menu") .innerText.replace(/\s/g, ""), "YearQuarterMonthWeekDay" ); await testUtils.dom.click( pivot.el.querySelectorAll( - ".o_legacy_pivot .o_dropdown_menu .o_dropdown_menu .o_dropdown_item" + ".o_legacy_pivot .dropdown-menu .dropdown-menu .dropdown-item" )[2] ); @@ -667,9 +670,9 @@ QUnit.module('Views', { // open dropdown to zoom into first row await testUtils.dom.click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); // click on date by day - await testUtils.dom.click(pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_toggler")); + await testUtils.dom.triggerEvent(pivot.el.querySelector("tbody .dropdown-menu .dropdown-toggle"), "mouseenter"); await testUtils.dom.click( - pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_menu li:nth-child(5)") + pivot.el.querySelector("tbody .dropdown-menu .dropdown-menu span:nth-child(5)") ); // open dropdown to zoom into second row @@ -702,7 +705,7 @@ QUnit.module('Views', { // unfold it await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelector(".o_dropdown_menu li:nth-child(5)")); + await testUtils.dom.click(pivot.el.querySelector(".dropdown-menu span:nth-child(5)")); assert.containsN(pivot, 'thead tr', 3); pivot.destroy(); @@ -727,7 +730,7 @@ QUnit.module('Views', { // unfold it await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed:nth(1)')); - await testUtils.dom.click(pivot.el.querySelector(".o_dropdown_menu li:nth-child(1)")); + await testUtils.dom.click(pivot.el.querySelector(".dropdown-menu span:nth-child(1)")); assert.containsN(pivot, 'thead tr', 4); values = ['12', '3', '17', '32']; assert.strictEqual(getCurrentValues(pivot), values.join(',')); @@ -761,22 +764,22 @@ QUnit.module('Views', { // open group by dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 3, - "should have 2 dropdown items in searchview groupby"); - assert.containsOnce(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_add_custom_group_menu', + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 3, + "should have 3 dropdown items in searchview groupby"); + assert.containsOnce(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu', "should have custom group generator in searchview groupby"); // click on closed header to open dropdown await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); - assert.containsN(pivot, '.o_pivot_field_menu .dropdown-item', 3, + assert.containsN(pivot, '.o_pivot_field_menu .o_menu_item', 3, "should have 3 dropdown items same as searchview groupby"); assert.containsOnce(pivot, '.o_pivot_field_menu .o_add_custom_group_menu', "should have custom group generator same as searchview groupby"); // check custom groupby selection has groupable fields only - await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_toggler')); - assert.containsN(pivot, '.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_menu option', 6, + await testUtils.dom.triggerEvent(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-toggle'), "mouseenter"); + assert.containsN(pivot, '.o_pivot_field_menu .o_add_custom_group_menu .dropdown-menu option', 6, "should have 6 fields in custom groupby"); - const optionDescriptions = [...pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_menu option')] + const optionDescriptions = [...pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-menu option')] .map(option => option.innerText.trim()); assert.deepEqual( optionDescriptions, @@ -817,14 +820,14 @@ QUnit.module('Views', { // open group by dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 2, + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 2, "should have 2 dropdown items in searchview groupby"); // click on closed header to open dropdown await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); assert.containsN( pivot.el, - ".o_dropdown_menu .o_menu_item", + ".dropdown-menu .o_menu_item", 2, "should have 2 dropdown items in pivot groupby" ); @@ -832,19 +835,19 @@ QUnit.module('Views', { await cpHelpers.toggleGroupByMenu(pivot.el); await cpHelpers.toggleAddCustomGroup(pivot.el); await cpHelpers.applyGroup(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 3, + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 3, "should have 3 dropdown items in searchview groupby now"); // click on closed header to open dropdown await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); // applying groupby/custom groupby will update pivot groupby dropdown while reverse is not true - assert.containsN(pivot, '.o_pivot_field_menu .dropdown-item', 3, + assert.containsN(pivot, '.o_pivot_field_menu .o_menu_item', 3, "should have 3 dropdown items same as searchview groupby"); // add a custom group in pivot groupby - await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_toggler')); + await testUtils.dom.triggerEvent(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-toggle'), "mouseenter"); await testUtils.fields.editSelect(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu select'), 'date'); - await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_menu button')); + await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-menu button')); // click on closed header to open groupby selection dropdown await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); assert.containsN(pivot, '.o_pivot_field_menu .o_menu_item', 4, @@ -852,7 +855,7 @@ QUnit.module('Views', { // applying custom groupby in pivot groupby dropdown will not update search dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 3, + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 3, "should have 3 dropdown items in searchview groupby dropdown"); pivot.destroy(); @@ -882,11 +885,11 @@ QUnit.module('Views', { // open group by dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 2, + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 2, "should have 2 dropdown items in searchview groupby"); await cpHelpers.toggleAddCustomGroup(pivot.el); await cpHelpers.applyGroup(pivot.el); - assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', 3, + assert.containsN(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', 3, "should have 3 dropdown items in searchview groupby now"); // click on closed header to open dropdown @@ -895,7 +898,7 @@ QUnit.module('Views', { assert.deepEqual([...items].map((el) => el.innerText), ["bar", "product", "Company Type"]); assert.containsN( pivot, - "tbody .o_dropdown_menu .dropdown-divider", 2, + "tbody .dropdown-menu .dropdown-divider", 2, "pivot groupby menu should have two separators" ); assert.hasClass( @@ -940,7 +943,7 @@ QUnit.module('Views', { // click on closed header to open dropdown and apply groupby on date field await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_toggler')); + await testUtils.dom.triggerEvent(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-toggle'), "mouseenter"); await testUtils.fields.editSelect(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu select'), 'date'); checkReadGroup = true; await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .btn-primary')); @@ -967,7 +970,7 @@ QUnit.module('Views', { // open group by dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsNone(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', + assert.containsNone(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', "should not have any dropdown item in searchview groupby"); // click on closed header to open dropdown await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); @@ -1013,9 +1016,9 @@ QUnit.module('Views', { // open group by dropdown await cpHelpers.toggleGroupByMenu(pivot.el); - assert.containsOnce(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item', + assert.containsOnce(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item', "should have 1 dropdown item in searchview groupby"); - assert.containsNone(pivot, '.o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_add_custom_group_menu', + assert.containsNone(pivot, '.o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu', "should not have custom group generator in searchview groupby"); // click on closed header to open dropdown @@ -1051,7 +1054,7 @@ QUnit.module('Views', { // click on closed header to open dropdown and apply groupby on date field await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .o_dropdown_toggler')); + await testUtils.dom.triggerEvent(pivot.$('.o_pivot_field_menu .o_add_custom_group_menu .dropdown-toggle'), "mouseenter"); assert.containsOnce(pivot, '.o_pivot_field_menu .o_add_custom_group_menu', "should have custom group generator in groupby dropdown"); @@ -1203,7 +1206,7 @@ QUnit.module('Views', { // tries to open a field selection menu, to make sure it was not // removed from the dom. await testUtils.dom.clickFirst(pivot.$('.o_pivot_header_cell_closed')); - assert.containsOnce(pivot, '.o_dropdown_menu', + assert.containsOnce(pivot, '.o_legacy_pivot .dropdown-menu', "the field selector menu exists"); pivot.destroy(); }); @@ -1488,7 +1491,7 @@ QUnit.module('Views', { // expand header on field customer await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed:nth(1)')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); assert.deepEqual(pivot.getOwnedQueryParams(), { context: { pivot_column_groupby: ['date:day', 'customer'], @@ -1499,7 +1502,7 @@ QUnit.module('Views', { // expand row on field product_id await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); assert.deepEqual(pivot.getOwnedQueryParams(), { context: { pivot_column_groupby: ['date:day', 'customer'], @@ -1571,7 +1574,7 @@ QUnit.module('Views', { }, "context should be correct"); await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.$('.o_dropdown_menu li:nth-child(5)')); + await testUtils.dom.click(pivot.$('.dropdown-menu span:nth-child(5)')); assert.deepEqual(pivot.getOwnedQueryParams(), { context: { @@ -1582,7 +1585,7 @@ QUnit.module('Views', { }, "context should be correct"); await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.$('.o_dropdown_menu li:nth-child(2)')); + await testUtils.dom.click(pivot.$('.dropdown-menu span:nth-child(2)')); assert.deepEqual(pivot.getOwnedQueryParams(), { context: { @@ -1696,7 +1699,7 @@ QUnit.module('Views', { // Set a column groupby await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); // Set a domain await pivot.update({domain: [['product_id', '=', 37]], groupBy: [], context: {}}); @@ -1711,7 +1714,7 @@ QUnit.module('Views', { // Set a column groupby await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); // Set a domain await pivot.update({domain: [['product_id', '=', 41]], groupBy: [], context: {}}); @@ -1749,7 +1752,7 @@ QUnit.module('Views', { // expand a col group await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed:nth(1)')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); values = [ "29", "1", "2", "32", @@ -1760,7 +1763,7 @@ QUnit.module('Views', { // expand a row group await testUtils.dom.click(pivot.el.querySelector('tbody tr:last-child .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[3]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[3]); values = [ "29", "1", "2", "32", @@ -1803,7 +1806,7 @@ QUnit.module('Views', { // Set a column groupby await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); // Set a domain for empty results await pivot.update({domain: [['id', '=', false]]}); @@ -1877,21 +1880,21 @@ QUnit.module('Views', { }); await testUtils.dom.click(pivot.el.querySelector('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelector('thead .o_dropdown_menu .o_dropdown_toggler')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_menu .o_dropdown_item")[3]); + await testUtils.dom.triggerEvent(pivot.el.querySelector('thead .dropdown-menu .dropdown-toggle'), "mouseenter"); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-menu .dropdown-item")[3]); // close and reopen row groupings after changing value this.data.partner.records.find(r => r.product_id === 37).date = '2016-10-27'; await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_opened')); await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); assert.strictEqual(pivot.el.querySelectorAll('.o_pivot_cell_value')[4].innerText, ''); // xphone December 2016 // invert axis, and reopen column groupings await testUtils.dom.click(pivot.el.querySelector('.o_cp_buttons .o_pivot_flip_button')); await testUtils.dom.click(pivot.el.querySelector('thead .o_pivot_header_cell_opened')); await testUtils.dom.click(pivot.el.querySelector('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); assert.strictEqual(pivot.el.querySelectorAll('.o_pivot_cell_value')[3].innerText, ''); // December 2016 xphone pivot.destroy(); @@ -2380,9 +2383,9 @@ QUnit.module('Views', { }); await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); // click on date by month - await testUtils.dom.click(pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_toggler")); + await testUtils.dom.triggerEvent(pivot.el.querySelector("tbody .dropdown-menu .dropdown-toggle"), "mouseenter"); await testUtils.dom.click( - pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_menu .o_dropdown_item")[3] + pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-menu .dropdown-item")[3] ); assert.strictEqual(pivot.$('.o_pivot_cell_value').text(), '2211', @@ -2426,7 +2429,7 @@ QUnit.module('Views', { await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-item")[4]); assert.strictEqual(pivot.$('.o_pivot_cell_value').text(), '211', 'should have loaded the proper data'); @@ -2447,11 +2450,11 @@ QUnit.module('Views', { // Set a column groupby await testUtils.dom.click(pivot.$('thead .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_item")[1]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-item")[1]); // Set a Row groupby await testUtils.dom.click(pivot.el.querySelector('tbody .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-item")[4]); // Set a domain await testUtils.pivot.reload(pivot, {domain: [['product_id', '=', 41]]}); @@ -2681,7 +2684,7 @@ QUnit.module('Views', { // with data, with row groupby await testUtils.dom.click(pivot.$('.o_legacy_pivot .o_pivot_header_cell_closed').eq(2)); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); values = [ "19", "0", "-100%", "0", "13", "100%", "19", "13", "-31.58%", "19", "0", "-100%", "0", "1" , "100%", "19", "1", "-94.74%", @@ -3309,7 +3312,7 @@ QUnit.module('Views', { // Set a Row groupby await testUtils.dom.click(pivot.el.querySelector('tbody tr:nth-child(2) .o_pivot_header_cell_closed')); - await testUtils.dom.click(pivot.el.querySelectorAll("tbody .o_dropdown_item")[4]); + await testUtils.dom.click(pivot.el.querySelectorAll("tbody .dropdown-item")[4]); assert.strictEqual( pivot.$('th').slice(0, 2).text(), @@ -3374,13 +3377,13 @@ QUnit.module('Views', { }, }); await testUtils.dom.click(pivot.el.querySelector("thead th.o_pivot_header_cell_closed")); - await testUtils.dom.click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[5]); + await testUtils.dom.click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[5]); // Click on the two dropdown await testUtils.dom.click(pivot.el.querySelectorAll("thead th.o_pivot_header_cell_closed")[0]); await testUtils.dom.click(pivot.el.querySelectorAll("thead th.o_pivot_header_cell_closed")[1]); - assert.containsOnce(pivot, 'thead .o_dropdown_menu', 'Only one dropdown should be displayed at a time'); + assert.containsOnce(pivot, 'thead .dropdown-menu', 'Only one dropdown should be displayed at a time'); pivot.destroy(); }); diff --git a/addons/web/static/tests/legacy/views/state_mapping_tests.js b/addons/web/static/tests/legacy/views/state_mapping_tests.js index 04189dd873d..b6a2e522443 100644 --- a/addons/web/static/tests/legacy/views/state_mapping_tests.js +++ b/addons/web/static/tests/legacy/views/state_mapping_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { legacyExtraNextTick } from "@web/../tests/helpers/utils"; +import { legacyExtraNextTick, patchWithCleanup } from "@web/../tests/helpers/utils"; import { getFacetTexts, removeFacet, @@ -23,6 +23,7 @@ import AbstractView from "web.AbstractView"; import ActionModel from "web.ActionModel"; import { mock } from "web.test_utils"; import legacyViewRegistry from "web.view_registry"; +import { browser } from "@web/core/browser/browser"; const serviceRegistry = registry.category("services"); const viewRegistry = registry.category("views"); @@ -258,6 +259,7 @@ QUnit.module("Views", (hooks) => { async function (assert) { assert.expect(5); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const webClient = await createWebClient({ serverData, mockRPC(_, args) { diff --git a/addons/web/static/tests/legacy/views/view_dialogs_tests.js b/addons/web/static/tests/legacy/views/view_dialogs_tests.js index b5c3aa4915c..ce7da1b86a7 100644 --- a/addons/web/static/tests/legacy/views/view_dialogs_tests.js +++ b/addons/web/static/tests/legacy/views/view_dialogs_tests.js @@ -7,6 +7,8 @@ var testUtils = require('web.test_utils'); var Widget = require('web.Widget'); var FormView = require('web.FormView'); +const { browser } = require('@web/core/browser/browser'); +const { patchWithCleanup } = require('@web/../tests/helpers/utils'); const cpHelpers = require('@web/../tests/search/helpers'); var createView = testUtils.createView; @@ -526,6 +528,11 @@ QUnit.module('Views', { }, }); + // save favorite needs this + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + }); + var parent = await createParent({ data: this.data, archs: { diff --git a/addons/web/static/tests/search/comparison_menu_tests.js b/addons/web/static/tests/search/comparison_menu_tests.js index 8b518524cb0..ccde0a117b8 100644 --- a/addons/web/static/tests/search/comparison_menu_tests.js +++ b/addons/web/static/tests/search/comparison_menu_tests.js @@ -1,6 +1,7 @@ /** @odoo-module **/ -import { patchDate } from "@web/../tests/helpers/utils"; +import { 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, @@ -35,6 +36,10 @@ QUnit.module("Search", (hooks) => { }, }; setupControlPanelServiceRegistry(); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("Comparison"); @@ -49,8 +54,8 @@ QUnit.module("Search", (hooks) => { searchMenuTypes: ["filter", "comparison"], searchViewId: false, }); - assert.containsOnce(controlPanel, ".o_dropdown.o_filter_menu"); - assert.containsNone(controlPanel, ".o_dropdown.o_comparison_menu"); + assert.containsOnce(controlPanel, ".dropdown.o_filter_menu"); + assert.containsNone(controlPanel, ".dropdown.o_comparison_menu"); await toggleFilterMenu(controlPanel); await toggleMenuItem(controlPanel, "Birthday"); await toggleMenuItemOption(controlPanel, "Birthday", "January"); @@ -63,7 +68,9 @@ QUnit.module("Search", (hooks) => { "COMPARISON" ); await toggleComparisonMenu(controlPanel); - const comparisonOptions = [...controlPanel.el.querySelectorAll(".o_comparison_menu li")]; + const comparisonOptions = [ + ...controlPanel.el.querySelectorAll(".o_comparison_menu .dropdown-item"), + ]; assert.strictEqual(comparisonOptions.length, 2); assert.deepEqual( comparisonOptions.map((e) => e.innerText.trim()), diff --git a/addons/web/static/tests/search/custom_favorite_item_tests.js b/addons/web/static/tests/search/custom_favorite_item_tests.js index a63dc326a2b..9dfa9bfbea1 100644 --- a/addons/web/static/tests/search/custom_favorite_item_tests.js +++ b/addons/web/static/tests/search/custom_favorite_item_tests.js @@ -1,6 +1,7 @@ /** @odoo-module **/ -import { triggerEvent } from "@web/../tests/helpers/utils"; +import { patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils"; +import { browser } from "@web/core/browser/browser"; import { dialogService } from "@web/core/dialog/dialog_service"; import { registry } from "@web/core/registry"; import { ControlPanel } from "@web/search/control_panel/control_panel"; @@ -62,6 +63,10 @@ QUnit.module("Search", (hooks) => { setupControlPanelFavoriteMenuRegistry(); setupControlPanelServiceRegistry(); serviceRegistry.add("dialog", dialogService); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("CustomFavoriteItem"); diff --git a/addons/web/static/tests/search/custom_filter_item_tests.js b/addons/web/static/tests/search/custom_filter_item_tests.js index 918f5115eff..5ba239852a3 100644 --- a/addons/web/static/tests/search/custom_filter_item_tests.js +++ b/addons/web/static/tests/search/custom_filter_item_tests.js @@ -4,6 +4,7 @@ import { registerCleanup } from "@web/../tests/helpers/cleanup"; import { click, patchDate, patchWithCleanup } from "@web/../tests/helpers/utils"; import { localization } from "@web/core/l10n/localization"; import { ControlPanel } from "@web/search/control_panel/control_panel"; +import { browser } from "@web/core/browser/browser"; import { addCondition, applyFilter, @@ -84,6 +85,10 @@ QUnit.module("Search", (hooks) => { }, }; setupControlPanelServiceRegistry(); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("CustomFilterItem"); @@ -305,13 +310,13 @@ QUnit.module("Search", (hooks) => { assert.deepEqual(getDomain(controlPanel), []); assert.containsNone(controlPanel, ".o_menu_item"); - assert.containsOnce(controlPanel, ".o_add_custom_filter_menu button.o_dropdown_toggler"); + assert.containsOnce(controlPanel, ".o_add_custom_filter_menu button.dropdown-toggle"); // the 'Add Custom Filter' menu should be closed; - assert.containsNone(controlPanel, ".o_add_custom_filter_menu ul.o_dropdown_menu"); + assert.containsNone(controlPanel, ".o_add_custom_filter_menu .dropdown-menu"); await toggleAddCustomFilter(controlPanel); // the 'Add Custom Filter' menu should be open; - assert.containsOnce(controlPanel, ".o_add_custom_filter_menu ul.o_dropdown_menu"); + assert.containsOnce(controlPanel, ".o_add_custom_filter_menu .dropdown-menu"); await applyFilter(controlPanel); @@ -319,9 +324,9 @@ QUnit.module("Search", (hooks) => { assert.deepEqual(getDomain(controlPanel), [["boolean_field", "=", true]]); assert.containsOnce(controlPanel, ".o_menu_item"); - assert.containsOnce(controlPanel, ".o_add_custom_filter_menu button.o_dropdown_toggler"); - // the 'Add Custom Filter' menu should be closed; - assert.containsNone(controlPanel, ".o_add_custom_filter_menu ul.o_dropdown_menu"); + assert.containsOnce(controlPanel, ".o_add_custom_filter_menu button.dropdown-toggle"); + // the 'Add Custom Filter' menu should still be opened; + assert.containsOnce(controlPanel, ".o_add_custom_filter_menu .dropdown-menu"); }); QUnit.test("selection field: default and updated value", async function (assert) { diff --git a/addons/web/static/tests/search/custom_group_by_item_tests.js b/addons/web/static/tests/search/custom_group_by_item_tests.js index 896972959f9..e6da6ff60a9 100644 --- a/addons/web/static/tests/search/custom_group_by_item_tests.js +++ b/addons/web/static/tests/search/custom_group_by_item_tests.js @@ -1,6 +1,8 @@ /** @odoo-module **/ +import { browser } from "@web/core/browser/browser"; import { ControlPanel } from "@web/search/control_panel/control_panel"; +import { patchWithCleanup } from "../helpers/utils"; import { applyGroup, getFacetTexts, @@ -34,6 +36,10 @@ QUnit.module("Search", (hooks) => { }, }; setupControlPanelServiceRegistry(); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("CustomGroupByItem"); @@ -54,12 +60,12 @@ QUnit.module("Search", (hooks) => { const customGroupByItem = controlPanel.el.querySelector(".o_add_custom_group_menu"); assert.strictEqual(customGroupByItem.innerText.trim(), "Add Custom Group"); - assert.containsOnce(customGroupByItem, "button.o_dropdown_toggler"); - assert.containsNone(customGroupByItem, "ul.o_dropdown_menu"); + assert.containsOnce(customGroupByItem, "button.dropdown-toggle"); + assert.containsNone(customGroupByItem, ".dropdown-menu"); await toggleAddCustomGroup(controlPanel); - assert.containsOnce(customGroupByItem, "ul.o_dropdown_menu"); + assert.containsOnce(customGroupByItem, ".dropdown-menu"); assert.deepEqual( [...controlPanel.el.querySelectorAll(".o_add_custom_group_menu select option")].map( @@ -92,7 +98,7 @@ QUnit.module("Search", (hooks) => { assert.deepEqual( [ ...controlPanel.el.querySelectorAll( - ".o_add_custom_group_menu .o_dropdown_menu select option" + ".o_add_custom_group_menu .dropdown-menu select option" ), ].map((el) => el.innerText), ["Foo"] @@ -156,16 +162,16 @@ QUnit.module("Search", (hooks) => { await toggleAddCustomGroup(controlPanel); // Single select node with a single option - assert.containsOnce(controlPanel, ".o_add_custom_group_menu .o_dropdown_menu select"); + assert.containsOnce(controlPanel, ".o_add_custom_group_menu .dropdown-menu select"); assert.strictEqual( controlPanel.el - .querySelector(".o_add_custom_group_menu .o_dropdown_menu select option") + .querySelector(".o_add_custom_group_menu .dropdown-menu select option") .innerText.trim(), "Super Date" ); // Button apply - assert.containsOnce(controlPanel, ".o_add_custom_group_menu .o_dropdown_menu .btn"); + assert.containsOnce(controlPanel, ".o_add_custom_group_menu .dropdown-menu .btn"); }); QUnit.test( @@ -192,8 +198,8 @@ QUnit.module("Search", (hooks) => { await applyGroup(controlPanel); assert.containsOnce(controlPanel, ".o_group_by_menu .o_menu_item"); - assert.containsOnce(controlPanel, ".o_add_custom_group_menu .o_dropdown_toggler"); - assert.containsNone(controlPanel, ".o_add_custom_group_menu .o_dropdown_menu"); + assert.containsOnce(controlPanel, ".o_add_custom_group_menu .dropdown-toggle"); + assert.containsOnce(controlPanel, ".o_add_custom_group_menu .dropdown-menu"); assert.deepEqual(getFacetTexts(controlPanel), ["Candlelight"]); } ); diff --git a/addons/web/static/tests/search/favorite_menu_tests.js b/addons/web/static/tests/search/favorite_menu_tests.js index 0851aded1f7..a6d86a61432 100644 --- a/addons/web/static/tests/search/favorite_menu_tests.js +++ b/addons/web/static/tests/search/favorite_menu_tests.js @@ -84,10 +84,10 @@ QUnit.module("Search", (hooks) => { await toggleFavoriteMenu(controlPanel); assert.containsOnce( controlPanel, - "div.o_favorite_menu > .o_dropdown_menu", + "div.o_favorite_menu > .dropdown-menu", "the menu should be opened" ); - assert.containsNone(controlPanel, ".o_dropdown_menu *", "the menu should be empty"); + assert.containsNone(controlPanel, ".dropdown-menu *", "the menu should be empty"); } ); @@ -117,11 +117,11 @@ QUnit.module("Search", (hooks) => { await toggleFavoriteMenu(controlPanel); assert.containsOnce( controlPanel, - "div.o_favorite_menu > .o_dropdown_menu", + "div.o_favorite_menu > .dropdown-menu", "the menu should be opened" ); - assert.containsNone(controlPanel, ".o_dropdown_menu .dropdown-divider"); - assert.containsOnce(controlPanel, ".o_dropdown_menu .o_add_favorite"); + assert.containsNone(controlPanel, ".dropdown-menu .dropdown-divider"); + assert.containsOnce(controlPanel, ".dropdown-menu .o_add_favorite"); }); QUnit.test( @@ -182,7 +182,7 @@ QUnit.module("Search", (hooks) => { assert.deepEqual(getFacetTexts(webClient), ["My favorite"]); assert.hasClass( - webClient.el.querySelector(".o_favorite_menu li.o_menu_item"), + webClient.el.querySelector(".o_favorite_menu .o_menu_item"), "selected" ); diff --git a/addons/web/static/tests/search/filter_menu_tests.js b/addons/web/static/tests/search/filter_menu_tests.js index d4738266870..b3948c278d3 100644 --- a/addons/web/static/tests/search/filter_menu_tests.js +++ b/addons/web/static/tests/search/filter_menu_tests.js @@ -1,6 +1,7 @@ /** @odoo-module **/ -import { patchDate } from "@web/../tests/helpers/utils"; +import { 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, @@ -45,6 +46,10 @@ QUnit.module("Search", (hooks) => { }, }; setupControlPanelServiceRegistry(); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("FilterMenu"); @@ -147,7 +152,7 @@ QUnit.module("Search", (hooks) => { await toggleFilterMenu(controlPanel); await toggleMenuItem(controlPanel, "Date"); - const optionEls = controlPanel.el.querySelectorAll(".o_dropdown .o_item_option"); + const optionEls = controlPanel.el.querySelectorAll(".dropdown .o_item_option"); // default filter should be activated with the global default period 'this_month' assert.deepEqual(getDomain(controlPanel), [ diff --git a/addons/web/static/tests/search/group_by_menu_tests.js b/addons/web/static/tests/search/group_by_menu_tests.js index 728a5dd87ed..d9b9c1da368 100644 --- a/addons/web/static/tests/search/group_by_menu_tests.js +++ b/addons/web/static/tests/search/group_by_menu_tests.js @@ -1,6 +1,8 @@ /** @odoo-module **/ +import { browser } from "@web/core/browser/browser"; import { ControlPanel } from "@web/search/control_panel/control_panel"; +import { patchWithCleanup } from "../helpers/utils"; import { getFacetTexts, isItemSelected, @@ -34,6 +36,10 @@ QUnit.module("Search", (hooks) => { }, }; setupControlPanelServiceRegistry(); + patchWithCleanup(browser, { + setTimeout: (fn) => fn(), + clearTimeout: () => {}, + }); }); QUnit.module("GroupByMenu"); diff --git a/addons/web/static/tests/search/helpers.js b/addons/web/static/tests/search/helpers.js index 6d9ba334435..fa5a39825a4 100644 --- a/addons/web/static/tests/search/helpers.js +++ b/addons/web/static/tests/search/helpers.js @@ -10,7 +10,7 @@ import { viewService } from "@web/views/view_service"; import { actionService } from "@web/webclient/actions/action_service"; import { registerCleanup } from "../helpers/cleanup"; import { makeTestEnv } from "../helpers/mock_env"; -import { click, getFixture, triggerEvent } from "../helpers/utils"; +import { click, getFixture, mouseEnter, triggerEvent } from "../helpers/utils"; const serviceRegistry = registry.category("services"); const favoriteMenuRegistry = registry.category("favoriteMenu"); @@ -72,18 +72,26 @@ const findItem = (target, selector, finder = 0) => { /** Menu (generic) */ export const toggleMenu = async (el, menuFinder) => { - const menu = findItem(el, `.o_dropdown button.o_dropdown_toggler`, menuFinder); + const menu = findItem(el, `.dropdown button.dropdown-toggle`, menuFinder); await click(menu); }; export const toggleMenuItem = async (el, itemFinder) => { const item = findItem(el, `.o_menu_item`, itemFinder); - await click(item); + if (item.classList.contains("dropdown-toggle")) { + await mouseEnter(item); + } else { + await click(item); + } }; export const toggleMenuItemOption = async (el, itemFinder, optionFinder) => { const item = findItem(el, `.o_menu_item`, itemFinder); const option = findItem(item.parentNode, ".o_item_option", optionFinder); - await click(option); + if (option.classList.contains("dropdown-toggle")) { + await mouseEnter(option); + } else { + await click(option); + } }; export const isItemSelected = (el, itemFinder) => { const item = findItem(el, `.o_menu_item`, itemFinder); @@ -96,17 +104,17 @@ export const isOptionSelected = (el, itemFinder, optionFinder) => { }; export const getMenuItemTexts = (target) => { const el = getNode(target); - return [...el.querySelectorAll(`.o_dropdown ul .o_menu_item`)].map((e) => e.innerText.trim()); + return [...el.querySelectorAll(`.dropdown ul .o_menu_item`)].map((e) => e.innerText.trim()); }; /** Filter menu */ export const toggleFilterMenu = async (el) => { - await click(findItem(el, `.o_filter_menu button.o_dropdown_toggler`)); + await click(findItem(el, `.o_filter_menu button.dropdown-toggle`)); }; export const toggleAddCustomFilter = async (el) => { - await click(findItem(el, `.o_add_custom_filter_menu .o_dropdown_toggler`)); + await mouseEnter(findItem(el, `.o_add_custom_filter_menu .dropdown-toggle`)); }; export const editConditionField = async (el, index, fieldName) => { @@ -135,11 +143,11 @@ export const editConditionValue = async (el, index, value, valueIndex = 0) => { }; export const applyFilter = async (el) => { - await click(findItem(el, `.o_add_custom_filter_menu .o_dropdown_menu button.o_apply_filter`)); + await click(findItem(el, `.o_add_custom_filter_menu .dropdown-menu button.o_apply_filter`)); }; export const addCondition = async (el) => { - await click(findItem(el, `.o_add_custom_filter_menu .o_dropdown_menu button.o_add_condition`)); + await click(findItem(el, `.o_add_custom_filter_menu .dropdown-menu button.o_add_condition`)); }; export async function removeCondition(el, index) { @@ -150,27 +158,27 @@ export async function removeCondition(el, index) { /** Group by menu */ export const toggleGroupByMenu = async (el) => { - await click(findItem(el, `.o_group_by_menu .o_dropdown_toggler`)); + await click(findItem(el, `.o_group_by_menu .dropdown-toggle`)); }; export const toggleAddCustomGroup = async (el) => { - await click(findItem(el, `.o_add_custom_group_menu .o_dropdown_toggler`)); + await mouseEnter(findItem(el, `.o_add_custom_group_menu .dropdown-toggle`)); }; export const selectGroup = async (el, fieldName) => { - const select = findItem(el, `.o_add_custom_group_menu .o_dropdown_menu select`); + const select = findItem(el, `.o_add_custom_group_menu .dropdown-menu select`); select.value = fieldName; await triggerEvent(select, null, "change"); }; export const applyGroup = async (el) => { - await click(findItem(el, `.o_add_custom_group_menu .o_dropdown_menu .btn`)); + await click(findItem(el, `.o_add_custom_group_menu .dropdown-menu .btn`)); }; /** Favorite menu */ export const toggleFavoriteMenu = async (el) => { - await click(findItem(el, `.o_favorite_menu .o_dropdown_toggler`)); + await click(findItem(el, `.o_favorite_menu .dropdown-toggle`)); }; export const deleteFavorite = async (el, favoriteFinder) => { @@ -179,26 +187,26 @@ export const deleteFavorite = async (el, favoriteFinder) => { }; export const toggleSaveFavorite = async (el) => { - await click(findItem(el, `.o_favorite_menu .o_add_favorite .o_dropdown_toggler`)); + await mouseEnter(findItem(el, `.o_favorite_menu .o_add_favorite .dropdown-toggle`)); }; export const editFavoriteName = async (el, name) => { const input = findItem( el, - `.o_favorite_menu .o_add_favorite .o_dropdown_menu input[type="text"]` + `.o_favorite_menu .o_add_favorite .dropdown-menu input[type="text"]` ); input.value = name; await triggerEvent(input, null, "input"); }; export const saveFavorite = async (el) => { - await click(findItem(el, `.o_favorite_menu .o_add_favorite .o_dropdown_menu button`)); + await click(findItem(el, `.o_favorite_menu .o_add_favorite .dropdown-menu button`)); }; /** Comparison menu */ export const toggleComparisonMenu = async (el) => { - await click(findItem(el, `.o_comparison_menu button.o_dropdown_toggler`)); + await click(findItem(el, `.o_comparison_menu button.dropdown-toggle`)); }; /** Search bar */ diff --git a/addons/web/static/tests/views/graph_view_tests.js b/addons/web/static/tests/views/graph_view_tests.js index 1670d9c6c74..3d5f7584ace 100644 --- a/addons/web/static/tests/views/graph_view_tests.js +++ b/addons/web/static/tests/views/graph_view_tests.js @@ -22,6 +22,8 @@ import { dialogService } from "@web/core/dialog/dialog_service"; import { registry } from "@web/core/registry"; import { BORDER_WHITE, DEFAULT_BG } from "@web/views/graph/colors"; import { GraphArchParser } from "@web/views/graph/graph_arch_parser"; +import { browser } from "@web/core/browser/browser"; +import { patchWithCleanup } from "../helpers/utils"; const serviceRegistry = registry.category("services"); @@ -277,6 +279,7 @@ QUnit.module("Views", (hooks) => { setupControlPanelServiceRegistry(); setupControlPanelFavoriteMenuRegistry(); serviceRegistry.add("dialog", dialogService); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); }); QUnit.module("GraphView"); @@ -2478,7 +2481,7 @@ QUnit.module("Views", (hooks) => { }); await toggleMenu(graph, "Measures"); assert.deepEqual( - [...graph.el.querySelectorAll(".o_cp_bottom_left li.o_menu_item")].map( + [...graph.el.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map( (el) => el.innerText ), ["Foo", "Revenue", "Count"] @@ -2523,7 +2526,7 @@ QUnit.module("Views", (hooks) => { }); await toggleMenu(graph, "Measures"); assert.deepEqual( - [...graph.el.querySelectorAll(".o_cp_bottom_left li.o_menu_item")].map( + [...graph.el.querySelectorAll(".o_cp_bottom_left .o_menu_item")].map( (el) => el.innerText ), ["Bouh", "Foo", "Revenue", "Count"] @@ -2900,13 +2903,13 @@ QUnit.module("Views", (hooks) => { await toggleMenu(graph, "Measures"); assert.containsN( graph, - "li.o_menu_item", + ".o_menu_item", 3, "there should be three menu item in the measures dropdown (count, revenue and foo)" ); - assert.containsOnce(graph, 'li.o_menu_item:contains("Revenue")'); - assert.containsOnce(graph, 'li.o_menu_item:contains("Foo")'); - assert.containsOnce(graph, 'li.o_menu_item:contains("Count")'); + assert.containsOnce(graph, '.o_menu_item:contains("Revenue")'); + assert.containsOnce(graph, '.o_menu_item:contains("Foo")'); + assert.containsOnce(graph, '.o_menu_item:contains("Count")'); }); QUnit.test("graph view with invisible attribute on field", async function (assert) { @@ -2924,11 +2927,11 @@ QUnit.module("Views", (hooks) => { await toggleMenu(graph, "Measures"); assert.containsN( graph, - "li.o_menu_item", + ".o_menu_item", 2, "there should be only two menu item in the measures dropdown (count and foo)" ); - assert.containsNone(graph, 'li.o_menu_item:contains("Revenue")'); + assert.containsNone(graph, '.o_menu_item:contains("Revenue")'); }); QUnit.test("graph view sort by measure", async function (assert) { diff --git a/addons/web/static/tests/views/pivot_view_tests.js b/addons/web/static/tests/views/pivot_view_tests.js index d511b682fa8..f08ce150816 100644 --- a/addons/web/static/tests/views/pivot_view_tests.js +++ b/addons/web/static/tests/views/pivot_view_tests.js @@ -14,6 +14,7 @@ import { patchWithCleanup, triggerEvent, triggerEvents, + mouseEnter, } from "../helpers/utils"; import { applyGroup, @@ -35,6 +36,7 @@ import { } from "../search/helpers"; import { createWebClient, doAction } from "../webclient/helpers"; import { makeView } from "./helpers"; +import { browser } from "@web/core/browser/browser"; const serviceRegistry = registry.category("services"); @@ -189,6 +191,7 @@ QUnit.module("Views", (hooks) => { serviceRegistry.add("dialog", dialogService); serviceRegistry.add("localization", makeFakeLocalizationService()); serviceRegistry.add("user", makeFakeUserService()); + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); }); QUnit.module("PivotView"); @@ -257,9 +260,9 @@ QUnit.module("Views", (hooks) => { `, }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); assert.strictEqual( - pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item").innerText, + pivot.el.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item").innerText, "BAR" ); assert.strictEqual( @@ -316,12 +319,12 @@ QUnit.module("Views", (hooks) => { // there should be only one displayed measure as the other one is invisible assert.containsOnce(pivot, ".o_pivot_measure_row"); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); // there should be only one measure besides count, as the other one is invisible - assert.containsN(pivot, ".o_cp_bottom_left .o_dropdown_menu .dropdown-item", 2); + assert.containsN(pivot, ".o_cp_bottom_left .dropdown-menu .dropdown-item", 2); // the invisible field souldn't be in the groupable fields neither await click(pivot.el.querySelector(".o_pivot_header_cell_closed")); - assert.containsNone(pivot, '.o_dropdown_menu a[data-field="foo2"]'); + assert.containsNone(pivot, '.dropdown-menu a[data-field="foo2"]'); }); QUnit.test('pivot view without "string" attribute', async function (assert) { @@ -382,10 +385,10 @@ QUnit.module("Views", (hooks) => { `, }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); assert.containsOnce( pivot, - ".o_cp_bottom_left .o_dropdown_menu .dropdown-item:contains(Computed and not stored)" + ".o_cp_bottom_left .dropdown-menu .dropdown-item:contains(Computed and not stored)" ); assert.strictEqual( pivot.el.querySelector(".o_pivot_measure_row").innerText, @@ -772,11 +775,9 @@ QUnit.module("Views", (hooks) => { }, }); - await click(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_toggler")); - assert.containsOnce(pivot.el, ".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item"); - const measure = pivot.el.querySelector( - ".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item" - ); + await click(pivot.el.querySelector(".o_cp_bottom_left .dropdown-toggle")); + assert.containsOnce(pivot.el, ".o_cp_bottom_left .dropdown-menu .dropdown-item"); + const measure = pivot.el.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-item"); assert.strictEqual(measure.innerText, "Count"); assert.hasClass(measure, "selected", "The count measure should be selected"); }); @@ -873,25 +874,23 @@ QUnit.module("Views", (hooks) => { // click on closed header to open dropdown await click(pivot.el, "tbody .o_pivot_header_cell_closed"); - assert.containsOnce(pivot, ".o_pivot .o_dropdown_menu"); + assert.containsOnce(pivot, ".o_pivot .dropdown-menu"); assert.strictEqual( - pivot.el.querySelector(".o_pivot .o_dropdown_menu").innerText.replace(/\s/g, ""), + pivot.el.querySelector(".o_pivot .dropdown-menu").innerText.replace(/\s/g, ""), "CompanyTypeCustomerDateOtherProductProductbarAddCustomGroup" ); // open the Date sub dropdown - await click(pivot.el, ".o_pivot .o_dropdown_menu .o_dropdown_toggler.o_menu_item"); + await mouseEnter(pivot.el, ".o_pivot .dropdown-menu .dropdown-toggle.o_menu_item"); assert.strictEqual( pivot.el - .querySelector(".o_pivot .o_dropdown_menu .o_dropdown_menu") + .querySelector(".o_pivot .dropdown-menu .dropdown-menu") .innerText.replace(/\s/g, ""), "YearQuarterMonthWeekDay" ); await click( - pivot.el.querySelectorAll( - ".o_pivot .o_dropdown_menu .o_dropdown_menu .o_dropdown_item" - )[2] + pivot.el.querySelectorAll(".o_pivot .dropdown-menu .dropdown-menu .dropdown-item")[2] ); assert.containsN(pivot, "tbody tr", 4, "should have 4 rows: one for header, 3 for data"); @@ -919,9 +918,9 @@ QUnit.module("Views", (hooks) => { // open dropdown to zoom into first row await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); // click on date by day - await click(pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_toggler")); + await mouseEnter(pivot.el.querySelector("tbody .dropdown-menu .dropdown-toggle")); await click( - pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_menu li:nth-child(5)") + pivot.el.querySelector("tbody .dropdown-menu .dropdown-menu span:nth-child(5)") ); // open dropdown to zoom into second row @@ -957,7 +956,7 @@ QUnit.module("Views", (hooks) => { // unfold it await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelector(".o_dropdown_menu li:nth-child(5)")); + await click(pivot.el.querySelector(".dropdown-menu span:nth-child(5)")); assert.containsN(pivot, "thead tr", 3); }); @@ -981,7 +980,7 @@ QUnit.module("Views", (hooks) => { // unfold it await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed:last-child")); - await click(pivot.el.querySelector(".o_dropdown_menu li:nth-child(1)")); + await click(pivot.el.querySelector(".dropdown-menu span:nth-child(1)")); assert.containsN(pivot, "thead tr", 4); values = ["12", "3", "17", "32"]; assert.strictEqual(getCurrentValues(pivot), values.join(",")); @@ -1015,13 +1014,13 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 3, "should have 3 dropdown items in searchview groupby" ); assert.containsOnce( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_add_custom_group_menu", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", "should have custom group generator in searchview groupby" ); @@ -1029,26 +1028,26 @@ QUnit.module("Views", (hooks) => { await click(pivot.el, "tbody tr:last-child .o_pivot_header_cell_closed"); assert.containsN( pivot, - ".o_dropdown_menu > .dropdown-item", + ".dropdown-menu > .dropdown-item", 3, "should have 3 dropdown items same as searchview groupby" ); assert.containsOnce( pivot, - ".o_dropdown_menu .o_add_custom_group_menu", + ".dropdown-menu .o_add_custom_group_menu", "should have custom group generator same as searchview groupby" ); // check custom groupby selection has groupable fields only - await click(pivot.el, ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_toggler"); + await mouseEnter(pivot.el, ".dropdown-menu .o_add_custom_group_menu .dropdown-toggle"); assert.containsN( pivot, - ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu option", + ".dropdown-menu .o_add_custom_group_menu .dropdown-menu option", 6, "should have 6 fields in custom groupby" ); const optionDescriptions = [ ...pivot.el.querySelectorAll( - ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu option" + ".dropdown-menu .o_add_custom_group_menu .dropdown-menu option" ), ].map((option) => option.innerText.trim()); assert.deepEqual( @@ -1080,7 +1079,7 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 2, "should have 2 dropdown items in searchview groupby" ); @@ -1089,7 +1088,7 @@ QUnit.module("Views", (hooks) => { await click(pivot.el, "tbody tr:last-child .o_pivot_header_cell_closed"); assert.containsN( pivot, - ".o_dropdown_menu .o_menu_item", + ".dropdown-menu .o_menu_item", 2, "should have 2 dropdown items in pivot groupby" ); @@ -1100,28 +1099,28 @@ QUnit.module("Views", (hooks) => { await applyGroup(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 3, "should have 3 dropdown items in searchview groupby now" ); await click(pivot.el, "tbody tr:last-child .o_pivot_header_cell_closed"); assert.containsN( pivot, - ".o_dropdown_menu .o_menu_item", + ".dropdown-menu .o_menu_item", 2, "should still have 2 dropdown items in pivot groupby" ); // add a custom group in pivot groupby - await click(pivot.el, ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_toggler"); - pivot.el.querySelector(".o_dropdown_menu .o_add_custom_group_menu select").value = "date"; - await triggerEvent(pivot.el, ".o_dropdown_menu .o_add_custom_group_menu select", "change"); - await click(pivot.el, ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu .btn"); + await mouseEnter(pivot.el, ".dropdown-menu .o_add_custom_group_menu .dropdown-toggle"); + pivot.el.querySelector(".dropdown-menu .o_add_custom_group_menu select").value = "date"; + await triggerEvent(pivot.el, ".dropdown-menu .o_add_custom_group_menu select", "change"); + await click(pivot.el, ".dropdown-menu .o_add_custom_group_menu .dropdown-menu .btn"); // click on closed header to open groupby selection dropdown await click(pivot.el, "tbody tr:last-child .o_pivot_header_cell_closed"); assert.containsN( pivot, - ".o_dropdown_menu .o_menu_item", + ".dropdown-menu .o_menu_item", 3, "should have 3 dropdown items in pivot groupby dropdown" ); @@ -1130,7 +1129,7 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 3, "should still have 3 dropdown items in searchview groupby dropdown" ); @@ -1159,7 +1158,7 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 2, "should have 2 dropdown items in searchview groupby" ); @@ -1167,7 +1166,7 @@ QUnit.module("Views", (hooks) => { await applyGroup(pivot); assert.containsN( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", 3, "should have 3 dropdown items in searchview groupby now" ); @@ -1181,7 +1180,7 @@ QUnit.module("Views", (hooks) => { ); assert.containsOnce( pivot, - "tbody .o_dropdown_menu .dropdown-divider", + "tbody .dropdown-menu .dropdown-divider", "pivot groupby menu should only have one separator" ); assert.hasClass( @@ -1191,17 +1190,14 @@ QUnit.module("Views", (hooks) => { ); // add a custom group in pivot groupby - await click(pivot.el, ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_toggler"); + await mouseEnter(pivot.el, ".dropdown-menu .o_add_custom_group_menu .dropdown-toggle"); pivot.el.querySelector(".o_add_custom_group_menu select").value = "customer"; await triggerEvent( pivot.el, - ".o_dropdown_menu .o_add_custom_group_menu select", + ".dropdown-menu .o_add_custom_group_menu select", "change" ); - await click( - pivot.el, - ".o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu .btn" - ); + await click(pivot.el, ".dropdown-menu .o_add_custom_group_menu .dropdown-menu .btn"); await click(pivot.el.querySelectorAll("tbody .o_pivot_header_cell_closed")[1]); items = pivot.el.querySelectorAll(".o_menu_item"); @@ -1211,7 +1207,7 @@ QUnit.module("Views", (hooks) => { ); assert.containsN( pivot, - "tbody .o_dropdown_menu .dropdown-divider", + "tbody .dropdown-menu .dropdown-divider", 2, "pivot groupby menu should now have two separators" ); @@ -1261,9 +1257,9 @@ QUnit.module("Views", (hooks) => { // click on closed header to open dropdown and apply groupby on date field await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click( + await mouseEnter( pivot.el.querySelector( - "thead .o_dropdown_menu .o_add_custom_group_menu .o_dropdown_toggler " + "thead .dropdown-menu .o_add_custom_group_menu .dropdown-toggle " ) ); @@ -1291,25 +1287,25 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsNone( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", "should not have any dropdown item in searchview groupby" ); assert.containsOnce( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_add_custom_group_menu", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", "should have add custom group item in searchview groupby" ); // click on closed header to open dropdown await click(pivot.el.querySelectorAll("tbody .o_pivot_header_cell_closed")[1]); assert.containsN( pivot, - "tbody .o_dropdown_menu .o_menu_item", + "tbody .dropdown-menu .o_menu_item", 6, "should have 6 dropdown items i.e. all groupable fields available" ); assert.containsOnce( pivot, - ".o_dropdown_menu .o_add_custom_group_menu", + ".dropdown-menu .o_add_custom_group_menu", "should have custom group generator in groupby dropdown" ); }); @@ -1361,12 +1357,12 @@ QUnit.module("Views", (hooks) => { await toggleGroupByMenu(pivot); assert.containsOnce( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_menu_item", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_menu_item", "should have 1 dropdown item in searchview groupby" ); assert.containsNone( pivot, - ".o_control_panel .o_cp_bottom_right .o_dropdown_menu .o_add_custom_group_menu", + ".o_control_panel .o_cp_bottom_right .dropdown-menu .o_add_custom_group_menu", "should not have custom group generator in searchview groupby" ); @@ -1374,12 +1370,12 @@ QUnit.module("Views", (hooks) => { await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); assert.containsOnce( pivot, - "tbody .o_dropdown_menu .o_dropdown_item", + "tbody .dropdown-menu .dropdown-item", "should have 1 dropdown items" ); assert.containsNone( pivot, - ".o_dropdown_menu .o_add_custom_group_menu", + ".dropdown-menu .o_add_custom_group_menu", "should not have custom group generator in groupby dropdown" ); } @@ -1407,24 +1403,24 @@ QUnit.module("Views", (hooks) => { // click on closed header to open dropdown await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - assert.containsOnce(pivot, "thead .o_dropdown_menu .o_add_custom_group_menu"); - await click( + assert.containsOnce(pivot, "thead .dropdown-menu .o_add_custom_group_menu"); + await mouseEnter( pivot.el.querySelector( - "thead .o_dropdown_menu .o_add_custom_group_menu .o_dropdown_toggler" + "thead .dropdown-menu .o_add_custom_group_menu .dropdown-toggle" ) ); assert.containsOnce( pivot, - "thead .o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu" + "thead .dropdown-menu .o_add_custom_group_menu .dropdown-menu" ); // click on apply button should close dropdown await click( pivot.el.querySelector( - "thead .o_dropdown_menu .o_add_custom_group_menu .o_dropdown_menu .btn-primary" + "thead .dropdown-menu .o_add_custom_group_menu .dropdown-menu .btn-primary" ) ); - assert.containsNone(pivot, "thead .o_dropdown_menu"); + assert.containsNone(pivot, "thead .dropdown-menu"); } ); @@ -1452,16 +1448,16 @@ QUnit.module("Views", (hooks) => { "should have 3 cells: 1 for the open header, and 2 for data" ); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); assert.doesNotHaveClass( - $(pivot.el).find(".o_dropdown_item:contains(Count)"), + $(pivot.el).find(".dropdown-item:contains(Count)"), "selected", "the __count measure should not be selected" ); - await click($(pivot.el).find(".o_cp_bottom_left .o_dropdown_item:contains(Count)")[0]); + await click($(pivot.el).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); assert.hasClass( - $(pivot.el).find(".o_cp_bottom_left .o_dropdown_item:contains(Count)"), + $(pivot.el).find(".o_cp_bottom_left .dropdown-item:contains(Count)"), "selected", "the __count measure should be selected" ); @@ -1473,10 +1469,10 @@ QUnit.module("Views", (hooks) => { ); assert.strictEqual(rpcCount, 2, "should have done 2 rpcs to reload data"); - await click($(pivot.el).find(".o_cp_bottom_left .o_dropdown_item:contains(Count)")[0]); + await click($(pivot.el).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); assert.doesNotHaveClass( - $(pivot.el).find(".o_dropdown_item:contains(Count)")[0], + $(pivot.el).find(".dropdown-item:contains(Count)")[0], "selected", "the __count measure should not be selected" ); @@ -1500,8 +1496,8 @@ QUnit.module("Views", (hooks) => { assert.containsNone(pivot, ".o_view_nocontent"); assert.containsOnce(pivot, "table"); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); - await click($(pivot.el).find(".o_cp_bottom_left .o_dropdown_item:contains(Count)")[0]); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); + await click($(pivot.el).find(".o_cp_bottom_left .dropdown-item:contains(Count)")[0]); assert.containsOnce(pivot, ".o_view_nocontent"); assert.containsNone(pivot, "table"); @@ -1577,7 +1573,7 @@ QUnit.module("Views", (hooks) => { // tries to open a field selection menu, to make sure it was not // removed from the dom. await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - assert.containsOnce(pivot, "tbody .o_dropdown_menu"); + assert.containsOnce(pivot, "tbody .dropdown-menu"); }); QUnit.test("tries to restore previous state after domain change", async function (assert) { @@ -1927,7 +1923,7 @@ QUnit.module("Views", (hooks) => { // expand header on field customer await click(pivot.el.querySelectorAll("thead .o_pivot_header_cell_closed")[1]); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); expectedContext = { group_by: [], pivot_column_groupby: ["date:day", "customer"], @@ -1941,7 +1937,7 @@ QUnit.module("Views", (hooks) => { // expand row on field product_id await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); expectedContext = { group_by: [], pivot_column_groupby: ["date:day", "customer"], @@ -2042,7 +2038,7 @@ QUnit.module("Views", (hooks) => { // Group row by product_id await click(pivot.el, "tbody .o_pivot_header_cell_closed"); - await click(pivot.el, ".o_dropdown_menu li:nth-child(5)"); + await click(pivot.el, ".dropdown-menu span:nth-child(5)"); expectedContext = { group_by: [], pivot_column_groupby: [], @@ -2056,7 +2052,7 @@ QUnit.module("Views", (hooks) => { // Group column by customer await click(pivot.el, "thead .o_pivot_header_cell_closed"); - await click(pivot.el, ".o_dropdown_menu li:nth-child(2)"); + await click(pivot.el, ".dropdown-menu span:nth-child(2)"); expectedContext = { group_by: [], pivot_column_groupby: ["customer"], @@ -2214,7 +2210,7 @@ QUnit.module("Views", (hooks) => { // Group row by product_id await click(webClient.el, "tbody .o_pivot_header_cell_closed"); - await click(webClient.el, ".o_dropdown_menu li:nth-child(5)"); + await click(webClient.el, ".dropdown-menu span:nth-child(5)"); assert.strictEqual( webClient.el.querySelector("tbody .o_pivot_header_cell_closed").textContent, @@ -2507,7 +2503,7 @@ QUnit.module("Views", (hooks) => { // Set a column groupby await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_item")[1]); + await click(pivot.el.querySelectorAll("thead .dropdown-item")[1]); // Set a domain await toggleFilterMenu(pivot); @@ -2528,7 +2524,7 @@ QUnit.module("Views", (hooks) => { // Set a column groupby await removeFacet(pivot); // remove previously saved favorite await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); // Set a domain await toggleFilterMenu(pivot); @@ -2570,14 +2566,14 @@ QUnit.module("Views", (hooks) => { // expand a col group await click(pivot.el.querySelectorAll("thead .o_pivot_header_cell_closed")[1]); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); values = ["29", "1", "2", "32", "12", "12", "17", "1", "2", "20"]; assert.strictEqual(getCurrentValues(pivot), values.join(",")); // expand a row group await click(pivot.el.querySelectorAll("tbody .o_pivot_header_cell_closed")[1]); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[3]); + await click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[3]); values = ["29", "1", "2", "32", "12", "12", "17", "1", "2", "20", "17", "1", "2", "20"]; assert.strictEqual(getCurrentValues(pivot), values.join(",")); @@ -2644,7 +2640,7 @@ QUnit.module("Views", (hooks) => { // Set a column groupby await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[1]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[1]); assert.containsOnce(pivot, "table"); @@ -2750,9 +2746,9 @@ QUnit.module("Views", (hooks) => { }); await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelector("thead .o_dropdown_menu .o_dropdown_toggler")); + await mouseEnter(pivot.el.querySelector("thead .dropdown-menu .dropdown-toggle")); await click( - pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_menu .o_dropdown_item")[3] + pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-menu .dropdown-item")[3] ); // close and reopen row groupings after changing value @@ -2760,14 +2756,14 @@ QUnit.module("Views", (hooks) => { await click(pivot.el.querySelector("tbody .o_pivot_header_cell_opened")); await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); assert.strictEqual(pivot.el.querySelectorAll(".o_pivot_cell_value")[4].innerText, ""); // xphone December 2016 // invert axis, and reopen column groupings await click(pivot.el.querySelector(".o_cp_bottom_left .o_pivot_flip_button")); await click(pivot.el.querySelector("thead .o_pivot_header_cell_opened")); await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[4]); assert.strictEqual(pivot.el.querySelectorAll(".o_pivot_cell_value")[3].innerText, ""); // December 2016 xphone }); @@ -3103,13 +3099,13 @@ QUnit.module("Views", (hooks) => { }, }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); - assert.containsOnce(pivot, ".o_cp_bottom_left .o_dropdown_item"); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); + assert.containsOnce(pivot, ".o_cp_bottom_left .dropdown-item"); assert.strictEqual( - pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item").innerText, + pivot.el.querySelector(".o_cp_bottom_left .dropdown-item").innerText, "Count" ); - assert.hasClass(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item"), "selected"); + assert.hasClass(pivot.el.querySelector(".o_cp_bottom_left .dropdown-item"), "selected"); }); QUnit.test("not use a many2one as a measure by default", async function (assert) { @@ -3125,13 +3121,13 @@ QUnit.module("Views", (hooks) => { `, }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); - assert.containsOnce(pivot, ".o_cp_bottom_left .o_dropdown_item"); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); + assert.containsOnce(pivot, ".o_cp_bottom_left .dropdown-item"); assert.strictEqual( - pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item").innerText, + pivot.el.querySelector(".o_cp_bottom_left .dropdown-item").innerText, "Count" ); - assert.hasClass(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item"), "selected"); + assert.hasClass(pivot.el.querySelector(".o_cp_bottom_left .dropdown-item"), "selected"); }); QUnit.test( @@ -3150,14 +3146,14 @@ QUnit.module("Views", (hooks) => { `, additionalMeasures: ["product_id"], }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); - assert.containsN(pivot, ".o_cp_bottom_left .o_dropdown_item", 2); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); + assert.containsN(pivot, ".o_cp_bottom_left .dropdown-item", 2); assert.strictEqual( - pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item").innerText, + pivot.el.querySelector(".o_cp_bottom_left .dropdown-item").innerText, "Product" ); assert.doesNotHaveClass( - pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item"), + pivot.el.querySelector(".o_cp_bottom_left .dropdown-item"), "selected" ); } @@ -3198,9 +3194,9 @@ QUnit.module("Views", (hooks) => { }); await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); // click on date by month - await click(pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_toggler")); + await mouseEnter(pivot.el.querySelector("tbody .dropdown-menu .dropdown-toggle")); await click( - pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_menu .o_dropdown_item")[3] + pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-menu .dropdown-item")[3] ); assert.strictEqual( @@ -3226,8 +3222,8 @@ QUnit.module("Views", (hooks) => { additionalMeasures: ["product_id"], }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); - await click(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_item")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); + await click(pivot.el.querySelector(".o_cp_bottom_left .dropdown-item")); assert.strictEqual( [...pivot.el.querySelectorAll(".o_pivot_cell_value")] .map((c) => c.innerText) @@ -3254,7 +3250,7 @@ QUnit.module("Views", (hooks) => { }); await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("tbody .dropdown-item")[4]); assert.strictEqual( [...pivot.el.querySelectorAll(".o_pivot_cell_value")] @@ -3297,11 +3293,11 @@ QUnit.module("Views", (hooks) => { // Set a column groupby await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_item")[1]); + await click(pivot.el.querySelectorAll("thead .dropdown-item")[1]); // Set a Row groupby await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("tbody .dropdown-item")[4]); // Add a filter await toggleFilterMenu(pivot); @@ -3404,9 +3400,9 @@ QUnit.module("Views", (hooks) => { `, }); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); assert.strictEqual( - [...pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_item")] + [...pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-item")] .map((i) => i.innerText) .join(""), "bouhFoomoddZipCount" @@ -3547,7 +3543,7 @@ QUnit.module("Views", (hooks) => { // with data, with row groupby await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("tbody .o_dropdown_menu .o_dropdown_item")[4]); + await click(pivot.el.querySelectorAll("tbody .dropdown-menu .dropdown-item")[4]); values = [ "19", "0", @@ -3576,12 +3572,12 @@ QUnit.module("Views", (hooks) => { ]; assert.strictEqual(getCurrentValues(pivot), values.join()); - await click(pivot.el.querySelector(".o_cp_bottom_left button.o_dropdown_toggler")); + await click(pivot.el.querySelector(".o_cp_bottom_left button.dropdown-toggle")); await click( - pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item")[0] + pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[0] ); await click( - pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item")[1] + pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[1] ); values = [ "1", @@ -3612,10 +3608,10 @@ QUnit.module("Views", (hooks) => { assert.strictEqual(getCurrentValues(pivot), values.join()); await click( - pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item")[2] + pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[2] ); await click( - pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_menu .o_dropdown_item")[1] + pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-menu .dropdown-item")[1] ); values = [ "2", @@ -4085,21 +4081,21 @@ QUnit.module("Views", (hooks) => { arch: ``, }); - assert.containsNone(pivot, ".o_cp_bottom_left .o_dropdown_menu"); + assert.containsNone(pivot, ".o_cp_bottom_left .dropdown-menu"); // open the "Measures" menu - await click(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_toggler")); - assert.containsOnce(pivot, ".o_cp_bottom_left .o_dropdown_menu"); + await click(pivot.el.querySelector(".o_cp_bottom_left .dropdown-toggle")); + assert.containsOnce(pivot, ".o_cp_bottom_left .dropdown-menu"); // click on the divider in the "Measures" menu does not crash - await click(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_menu .dropdown-divider")); + await click(pivot.el.querySelector(".o_cp_bottom_left .dropdown-menu .dropdown-divider")); // the menu should still be open - assert.containsOnce(pivot, ".o_cp_bottom_left .o_dropdown_menu"); + assert.containsOnce(pivot, ".o_cp_bottom_left .dropdown-menu"); // click on the measure list but not on a menu item or the separator - await click(pivot.el.querySelector(".o_cp_bottom_left .o_dropdown_menu")); + await click(pivot.el.querySelector(".o_cp_bottom_left .dropdown-menu")); // the menu should still be open - assert.containsOnce(pivot, ".o_cp_bottom_left .o_dropdown_menu"); + assert.containsOnce(pivot, ".o_cp_bottom_left .dropdown-menu"); }); QUnit.test( @@ -4523,7 +4519,7 @@ QUnit.module("Views", (hooks) => { // Set a Row groupby await click(pivot.el, "tbody tr:nth-child(2) .o_pivot_header_cell_closed"); - await click(pivot.el, "tbody .o_dropdown_menu .o_menu_item:nth-child(5)"); + await click(pivot.el, "tbody .dropdown-menu .o_menu_item:nth-child(5)"); assert.deepEqual( [...pivot.el.querySelectorAll("thead th")].map((th) => th.innerText), @@ -4571,7 +4567,7 @@ QUnit.module("Views", (hooks) => { // add a col groupby on Product await click(pivot.el.querySelector("thead th.o_pivot_header_cell_closed")); - await click(pivot.el.querySelectorAll("thead .o_dropdown_menu .o_dropdown_item")[5]); + await click(pivot.el.querySelectorAll("thead .dropdown-menu .dropdown-item")[5]); // Click on the two header dropdown togglers await click(pivot.el.querySelectorAll("thead th.o_pivot_header_cell_closed")[0]); @@ -4579,7 +4575,7 @@ QUnit.module("Views", (hooks) => { assert.containsOnce( pivot, - "thead .o_dropdown_menu", + "thead .dropdown-menu", "Only one dropdown should be displayed at a time" ); }); @@ -4848,7 +4844,7 @@ QUnit.module("Views", (hooks) => { // drill down first row group (group by company_type) await click(webClient.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(webClient.el.querySelector(".o_pivot .o_dropdown_menu .o_dropdown_item")); + await click(webClient.el.querySelector(".o_pivot .dropdown-menu .dropdown-item")); assert.strictEqual(getCurrentValues(webClient), ["4", "2", "1", "1", "2"].join(",")); @@ -4947,7 +4943,7 @@ QUnit.module("Views", (hooks) => { // drill down first row group (group by company_type) await click(webClient.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(webClient.el.querySelector(".o_pivot .o_dropdown_menu .o_dropdown_item")); + await click(webClient.el.querySelector(".o_pivot .dropdown-menu .dropdown-item")); assert.strictEqual(getCurrentValues(webClient), ["32", "12", "12", "20"].join(",")); @@ -5156,7 +5152,7 @@ QUnit.module("Views", (hooks) => { // Add a groupby (this operation should be ignored as it concerns the old // table, which will be replaced soon) await click(pivot.el.querySelector("thead .o_pivot_header_cell_closed")); - await click(pivot.el.querySelector("thead .o_dropdown_menu .o_dropdown_item")); + await click(pivot.el.querySelector("thead .dropdown-menu .dropdown-item")); assert.strictEqual(getCurrentValues(pivot), ["32", "12", "20"].join(",")); def.resolve(); @@ -5189,7 +5185,7 @@ QUnit.module("Views", (hooks) => { // Add a groupby, to have a group to expand afterwards await click(pivot.el.querySelector("tbody .o_pivot_header_cell_closed")); - await click(pivot.el.querySelector("tbody .o_dropdown_menu .o_dropdown_item")); + await click(pivot.el.querySelector("tbody .dropdown-menu .dropdown-item")); assert.strictEqual(getCurrentValues(pivot), ["32", "12", "12", "20"].join(",")); @@ -5331,12 +5327,12 @@ QUnit.module("Views", (hooks) => { // "Count" is the only measure available assert.deepEqual( - [...pivot.el.querySelectorAll(".o_cp_bottom_left .o_dropdown_menu li")].map( + [...pivot.el.querySelectorAll(".o_cp_bottom_left .dropdown-menu .o_menu_item")].map( (e) => e.innerText ), ["Count"] ); // No separator should be displayed in the menu "Measures" - assert.containsNone(pivot, ".o_cp_bottom_left .o_dropdown_menu div.dropdown-divider"); + assert.containsNone(pivot, ".o_cp_bottom_left .dropdown-menu div.dropdown-divider"); }); }); diff --git a/addons/web/static/tests/webclient/actions/load_state_tests.js b/addons/web/static/tests/webclient/actions/load_state_tests.js index c93e1aec3c8..f9cd51b5cb2 100644 --- a/addons/web/static/tests/webclient/actions/load_state_tests.js +++ b/addons/web/static/tests/webclient/actions/load_state_tests.js @@ -967,8 +967,8 @@ QUnit.module("ActionManager", (hooks) => { assert.containsOnce(webClient, ".o_dialog_error"); await click(webClient.el, ".modal-header .close"); assert.containsNone(webClient, ".o_dialog_error"); - await click(webClient.el, "nav .o_navbar_apps_menu .o_dropdown_toggler "); - assert.containsN(webClient, ".o_dropdown_item.o_app", 3); + await click(webClient.el, "nav .o_navbar_apps_menu .dropdown-toggle "); + assert.containsN(webClient, ".dropdown-item.o_app", 3); assert.containsNone(webClient, ".o_menu_brand"); assert.strictEqual(webClient.el.querySelector(".o_action_manager").innerHTML, ""); assert.deepEqual(webClient.env.services.router.current.hash, { diff --git a/addons/web/static/tests/webclient/actions/push_state_tests.js b/addons/web/static/tests/webclient/actions/push_state_tests.js index e9176dc6cb5..1ebddc0244d 100644 --- a/addons/web/static/tests/webclient/actions/push_state_tests.js +++ b/addons/web/static/tests/webclient/actions/push_state_tests.js @@ -25,7 +25,7 @@ QUnit.module("ActionManager", (hooks) => { let urlState = webClient.env.services.router.current; assert.deepEqual(urlState.hash, {}); await click(webClient.el, ".o_navbar_apps_menu button"); - await click(webClient.el, ".o_navbar_apps_menu .o_dropdown_item:nth-child(3)"); + await click(webClient.el, ".o_navbar_apps_menu .dropdown-item:nth-child(3)"); await nextTick(); await nextTick(); urlState = webClient.env.services.router.current; @@ -44,7 +44,7 @@ QUnit.module("ActionManager", (hooks) => { let urlState = webClient.env.services.router.current; assert.deepEqual(urlState.hash, {}); await click(webClient.el, ".o_navbar_apps_menu button"); - await click(webClient.el, ".o_navbar_apps_menu .o_dropdown_item:nth-child(3)"); + await click(webClient.el, ".o_navbar_apps_menu .dropdown-item:nth-child(3)"); await nextTick(); await nextTick(); urlState = webClient.env.services.router.current; @@ -147,7 +147,7 @@ QUnit.module("ActionManager", (hooks) => { await doAction(webClient, "client_action_pushes"); await click(webClient.el, ".test_client_action"); await click(webClient.el, ".o_navbar_apps_menu button"); - await click(webClient.el, ".o_navbar_apps_menu .o_dropdown_item:nth-child(3)"); + await click(webClient.el, ".o_navbar_apps_menu .dropdown-item:nth-child(3)"); await nextTick(); await nextTick(); urlState = webClient.env.services.router.current; diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js index baa33cae188..563541b3716 100644 --- a/addons/web/static/tests/webclient/actions/window_action_tests.js +++ b/addons/web/static/tests/webclient/actions/window_action_tests.js @@ -75,14 +75,10 @@ QUnit.module("ActionManager", (hooks) => { assert.containsNone(webClient, ".o_cp_action_menus"); await testUtils.dom.clickFirst($(webClient.el).find("input.custom-control-input")); assert.isVisible( - $(webClient.el).find( - '.o_cp_action_menus button.o_dropdown_toggler:contains("Print")' - )[0] + $(webClient.el).find('.o_cp_action_menus button.dropdown-toggle:contains("Print")')[0] ); assert.isVisible( - $(webClient.el).find( - '.o_cp_action_menus button.o_dropdown_toggler:contains("Action")' - )[0] + $(webClient.el).find('.o_cp_action_menus button.dropdown-toggle:contains("Action")')[0] ); }); @@ -1356,7 +1352,7 @@ QUnit.module("ActionManager", (hooks) => { $(webClient.el).find(".o_control_panel .o_cp_bottom_right button:contains(Group By)") ); await testUtils.dom.click( - $(webClient.el).find(".o_control_panel .o_group_by_menu li:first") + $(webClient.el).find(".o_control_panel .o_group_by_menu .o_menu_item:first") ); await legacyExtraNextTick(); assert.containsN( @@ -1485,6 +1481,7 @@ QUnit.module("ActionManager", (hooks) => { }, }, }; + patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const webClient = await createWebClient({ serverData, legacyParams }); await doAction(webClient, 33); assert.containsN(webClient, ".o_data_row", 5, "should contain 5 records"); @@ -1575,19 +1572,19 @@ QUnit.module("ActionManager", (hooks) => { const webClient = await createWebClient({ serverData }); await doAction(webClient, 1); assert.isVisible( - webClient.el.querySelector(".o_search_options .o_dropdown.o_filter_menu"), + webClient.el.querySelector(".o_search_options .dropdown.o_filter_menu"), "the search options should be available" ); await doAction(webClient, 3); assert.isVisible( - webClient.el.querySelector(".o_search_options .o_dropdown.o_filter_menu"), + webClient.el.querySelector(".o_search_options .dropdown.o_filter_menu"), "the search options should be available" ); // go back using the breadcrumbs await testUtils.dom.click($(webClient.el).find(".o_control_panel .breadcrumb a:first")); await legacyExtraNextTick(); assert.isVisible( - webClient.el.querySelector(".o_search_options .o_dropdown.o_filter_menu"), + webClient.el.querySelector(".o_search_options .dropdown.o_filter_menu"), "the search options should be available" ); } @@ -2278,12 +2275,12 @@ QUnit.module("ActionManager", (hooks) => { await doAction(webClient, 1); assert.containsNone( webClient.el, - ".o_debug_manager .o_dropdown_item:contains('Edit View: Kanban')" + ".o_debug_manager .dropdown-item:contains('Edit View: Kanban')" ); - await click(webClient.el.querySelector(".o_debug_manager .o_dropdown_toggler")); + await click(webClient.el.querySelector(".o_debug_manager .dropdown-toggle")); assert.containsOnce( webClient.el, - ".o_debug_manager .o_dropdown_item:contains('Edit View: Kanban')" + ".o_debug_manager .dropdown-item:contains('Edit View: Kanban')" ); }); diff --git a/addons/web/static/tests/webclient/navbar_tests.js b/addons/web/static/tests/webclient/navbar_tests.js index b34c948ae4d..3d1ab59a4f7 100644 --- a/addons/web/static/tests/webclient/navbar_tests.js +++ b/addons/web/static/tests/webclient/navbar_tests.js @@ -47,7 +47,7 @@ QUnit.test("can be rendered", async (assert) => { const navbar = await mount(NavBar, { env, target }); assert.containsOnce( navbar.el, - ".o_navbar_apps_menu button.o_dropdown_toggler", + ".o_navbar_apps_menu button.dropdown-toggle", "1 apps menu toggler present" ); navbar.destroy(); @@ -58,10 +58,10 @@ QUnit.test("dropdown menu can be toggled", async (assert) => { const target = getFixture(); const navbar = await mount(NavBar, { env, target }); const dropdown = navbar.el.querySelector(".o_navbar_apps_menu"); - await click(dropdown, "button.o_dropdown_toggler"); - assert.containsOnce(dropdown, "ul.o_dropdown_menu"); - await click(dropdown, "button.o_dropdown_toggler"); - assert.containsNone(dropdown, "ul.o_dropdown_menu"); + await click(dropdown, "button.dropdown-toggle"); + assert.containsOnce(dropdown, ".dropdown-menu"); + await click(dropdown, "button.dropdown-toggle"); + assert.containsNone(dropdown, ".dropdown-menu"); navbar.destroy(); }); @@ -80,8 +80,8 @@ QUnit.test("data-menu-xmlid attribute on AppsMenu items", async (assert) => { // check apps const appsMenu = navbar.el.querySelector(".o_navbar_apps_menu"); - await click(appsMenu, "button.o_dropdown_toggler"); - const menuItems = appsMenu.querySelectorAll("li"); + await click(appsMenu, "button.dropdown-toggle"); + const menuItems = appsMenu.querySelectorAll("a"); assert.strictEqual( menuItems[0].dataset.menuXmlid, "wowl", @@ -96,17 +96,14 @@ QUnit.test("data-menu-xmlid attribute on AppsMenu items", async (assert) => { // check menus env.services.menu.setCurrentMenu(1); await nextTick(); - assert.containsOnce(navbar, ".o_menu_sections .o_dropdown_item[data-menu-xmlid=menu_3]"); + assert.containsOnce(navbar, ".o_menu_sections .dropdown-item[data-menu-xmlid=menu_3]"); // check sub menus toggler - assert.containsOnce( - navbar, - ".o_menu_sections button.o_dropdown_toggler[data-menu-xmlid=menu_4]" - ); + assert.containsOnce(navbar, ".o_menu_sections button.dropdown-toggle[data-menu-xmlid=menu_4]"); // check sub menus - await click(navbar.el.querySelector(".o_menu_sections .o_dropdown_toggler")); - assert.containsOnce(navbar, ".o_menu_sections .o_dropdown_item[data-menu-xmlid=menu_5]"); + await click(navbar.el.querySelector(".o_menu_sections .dropdown-toggle")); + assert.containsOnce(navbar, ".o_menu_sections .dropdown-item[data-menu-xmlid=menu_5]"); navbar.destroy(); }); @@ -117,10 +114,10 @@ QUnit.test("navbar can display current active app", async (assert) => { const navbar = await mount(NavBar, { env, target }); const dropdown = navbar.el.querySelector(".o_navbar_apps_menu"); // Open apps menu - await click(dropdown, "button.o_dropdown_toggler"); + await click(dropdown, "button.dropdown-toggle"); assert.containsOnce( dropdown, - "ul.o_dropdown_menu li.o_dropdown_item:not(.focus)", + ".dropdown-menu .dropdown-item:not(.focus)", "should not show the current active app as the menus service has not loaded an app yet" ); @@ -129,7 +126,7 @@ QUnit.test("navbar can display current active app", async (assert) => { await nextTick(); assert.containsOnce( dropdown, - "ul.o_dropdown_menu li.o_dropdown_item.focus", + ".dropdown-menu .dropdown-item.focus", "should show the current active app" ); navbar.destroy(); @@ -218,9 +215,9 @@ QUnit.test("can adapt with 'more' menu sections behavior", async (assert) => { "the displayed menu section should be the 'more' menu" ); // Open the more menu - await click(navbar.el, ".o_menu_sections_more .o_dropdown_toggler"); + await click(navbar.el, ".o_menu_sections_more .dropdown-toggle"); assert.deepEqual( - [...navbar.el.querySelectorAll(".o_dropdown_menu > *")].map((el) => el.textContent), + [...navbar.el.querySelectorAll(".dropdown-menu > *")].map((el) => el.textContent), ["Section 10", "Section 11", "Section 12", "Section 120", "Section 121", "Section 122"], "'more' menu should contain all hidden sections in correct order" ); @@ -401,23 +398,23 @@ QUnit.test("'more' menu sections properly updated on app change", async (assert) ); // Open the more menu - await click(navbar.el, ".o_menu_sections_more .o_dropdown_toggler"); + await click(navbar.el, ".o_menu_sections_more .dropdown-toggle"); assert.deepEqual( - [...navbar.el.querySelectorAll(".o_dropdown_menu > *")].map((el) => el.textContent), + [...navbar.el.querySelectorAll(".dropdown-menu > *")].map((el) => el.textContent), ["Section 10", "Section 11", "Section 12", "Section 120", "Section 121", "Section 122"], "'more' menu should contain App1 sections" ); // Close the more menu - await click(navbar.el, ".o_menu_sections_more .o_dropdown_toggler"); + await click(navbar.el, ".o_menu_sections_more .dropdown-toggle"); // Set App2 menu env.services.menu.setCurrentMenu(2); await nextTick(); // Open the more menu - await click(navbar.el, ".o_menu_sections_more .o_dropdown_toggler"); + await click(navbar.el, ".o_menu_sections_more .dropdown-toggle"); assert.deepEqual( - [...navbar.el.querySelectorAll(".o_dropdown_menu > *")].map((el) => el.textContent), + [...navbar.el.querySelectorAll(".dropdown-menu > *")].map((el) => el.textContent), ["Section 20", "Section 21", "Section 22", "Section 220", "Section 221", "Section 222"], "'more' menu should contain App2 sections" ); diff --git a/addons/web/static/tests/webclient/switch_company_menu_tests.js b/addons/web/static/tests/webclient/switch_company_menu_tests.js index 8901863c362..3b73626f60d 100644 --- a/addons/web/static/tests/webclient/switch_company_menu_tests.js +++ b/addons/web/static/tests/webclient/switch_company_menu_tests.js @@ -56,25 +56,25 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { const scMenu = await createSwitchCompanyMenu(); - assert.strictEqual(scMenu.el.tagName.toUpperCase(), "LI"); + assert.strictEqual(scMenu.el.tagName.toUpperCase(), "DIV"); assert.hasClass(scMenu.el, "o_switch_company_menu"); assert.strictEqual(scMenu.el.textContent, "Hermit"); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu, ".toggle_company", 3); assert.containsN(scMenu, ".log_into", 3); assert.containsOnce(scMenu.el, ".fa-check-square"); assert.containsN(scMenu.el, ".fa-square-o", 2); assert.strictEqual( - scMenu.el.querySelector(".fa-check-square").closest(".o_dropdown_item").textContent, + scMenu.el.querySelector(".fa-check-square").closest(".dropdown-item").textContent, "Hermit" ); assert.strictEqual( - scMenu.el.querySelector(".fa-square-o").closest(".o_dropdown_item").textContent, + scMenu.el.querySelector(".fa-square-o").closest(".dropdown-item").textContent, "Herman's" ); assert.strictEqual( - scMenu.el.querySelector(".o_dropdown_menu").textContent, + scMenu.el.querySelector(".dropdown-menu").textContent, "HermitHerman'sHeroes TM" ); }); @@ -96,7 +96,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 1); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 1); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 2); @@ -107,7 +107,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { * [ ] Company 3 */ await click(scMenu.el.querySelectorAll(".toggle_company")[1]); - assert.containsOnce(scMenu.el, ".o_dropdown_menu", "dropdown is still opened"); + assert.containsOnce(scMenu.el, ".dropdown-menu", "dropdown is still opened"); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 2); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 1); await prom; @@ -131,7 +131,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 1); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 1); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 2); @@ -144,7 +144,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { await click(scMenu.el.querySelectorAll(".toggle_company")[0]); await click(scMenu.el.querySelectorAll(".toggle_company")[1]); await click(scMenu.el.querySelectorAll(".toggle_company")[2]); - assert.containsOnce(scMenu.el, ".o_dropdown_menu", "dropdown is still opened"); + assert.containsOnce(scMenu.el, ".dropdown-menu", "dropdown is still opened"); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 2); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 1); @@ -170,7 +170,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 1); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 1); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 2); @@ -181,7 +181,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { * [ ] Company 3 */ await click(scMenu.el.querySelectorAll(".toggle_company")[0]); - assert.containsOnce(scMenu.el, ".o_dropdown_menu", "dropdown is still opened"); + assert.containsOnce(scMenu.el, ".dropdown-menu", "dropdown is still opened"); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 0); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 3); await prom; @@ -203,7 +203,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 1); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 1); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 2); @@ -214,7 +214,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { * [ ] Company 3 */ await click(scMenu.el.querySelectorAll(".log_into")[1]); - assert.containsNone(scMenu.el, ".o_dropdown_menu", "dropdown is directly closed"); + assert.containsNone(scMenu.el, ".dropdown-menu", "dropdown is directly closed"); assert.verifySteps(["cids=2"]); }); @@ -234,7 +234,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [3, 1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 3); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 2); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 1); @@ -245,7 +245,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { * [x] **Company 3** */ await click(scMenu.el.querySelectorAll(".log_into")[1]); - assert.containsNone(scMenu.el, ".o_dropdown_menu", "dropdown is directly closed"); + assert.containsNone(scMenu.el, ".dropdown-menu", "dropdown is directly closed"); assert.verifySteps(["cids=2%2C3%2C1"]); }); @@ -265,7 +265,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [2, 3]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 2); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 2); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 1); @@ -276,7 +276,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { * [x] Company 3 -> log into */ await click(scMenu.el.querySelectorAll(".log_into")[2]); - assert.containsNone(scMenu.el, ".o_dropdown_menu", "dropdown is directly closed"); + assert.containsNone(scMenu.el, ".dropdown-menu", "dropdown is directly closed"); assert.verifySteps(["cids=3%2C2"]); }); @@ -295,7 +295,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { */ assert.deepEqual(scMenu.env.services.company.allowedCompanyIds, [1]); assert.strictEqual(scMenu.env.services.company.currentCompany.id, 1); - await click(scMenu.el.querySelector(".o_dropdown_toggler")); + await click(scMenu.el.querySelector(".dropdown-toggle")); assert.containsN(scMenu.el, "[data-company-id]", 3); assert.containsN(scMenu.el, "[data-company-id] .fa-check-square", 1); assert.containsN(scMenu.el, "[data-company-id] .fa-square-o", 2); @@ -308,7 +308,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => { await click(scMenu.el.querySelectorAll(".toggle_company")[2]); await click(scMenu.el.querySelectorAll(".toggle_company")[0]); await click(scMenu.el.querySelectorAll(".log_into")[1]); - assert.containsNone(scMenu.el, ".o_dropdown_menu", "dropdown is directly closed"); + assert.containsNone(scMenu.el, ".dropdown-menu", "dropdown is directly closed"); assert.verifySteps(["cids=2"]); }); }); diff --git a/addons/web/static/tests/webclient/user_menu_tests.js b/addons/web/static/tests/webclient/user_menu_tests.js index 9824f46f98c..93e35a9ba8b 100644 --- a/addons/web/static/tests/webclient/user_menu_tests.js +++ b/addons/web/static/tests/webclient/user_menu_tests.js @@ -99,25 +99,23 @@ QUnit.test("can be rendered", async (assert) => { ); assert.containsOnce(userMenuEl, "span.oe_topbar_name"); assert.strictEqual(userMenuEl.querySelector(".oe_topbar_name").textContent, "Sauron"); - assert.containsNone(userMenuEl, "ul.o_dropdown_menu li.o_dropdown_item"); - await click(userMenu.el.querySelector("button.o_dropdown_toggler")); + assert.containsNone(userMenuEl, ".dropdown-menu .dropdown-item"); + await click(userMenu.el.querySelector("button.dropdown-toggle")); userMenuEl = userMenu.el; - assert.containsN(userMenuEl, "ul.o_dropdown_menu li.o_dropdown_item", 3); + assert.containsN(userMenuEl, ".dropdown-menu .dropdown-item", 3); assert.containsOnce(userMenuEl, "div.dropdown-divider"); - const children = [...(userMenuEl.querySelector("ul.o_dropdown_menu").children || [])]; + const children = [...(userMenuEl.querySelector(".dropdown-menu").children || [])]; assert.deepEqual( children.map((el) => el.tagName), - ["LI", "LI", "DIV", "LI"] + ["SPAN", "SPAN", "DIV", "SPAN"] ); - const items = [...userMenuEl.querySelectorAll("ul.o_dropdown_menu li.o_dropdown_item")] || []; + const items = [...userMenuEl.querySelectorAll(".dropdown-menu .dropdown-item")] || []; assert.deepEqual( items.map((el) => el.dataset.menu), ["ring", "bad", "eye"] ); - const spans = - [...userMenuEl.querySelectorAll("ul.o_dropdown_menu li.o_dropdown_item span")] || []; assert.deepEqual( - spans.map((el) => el.textContent), + items.map((el) => el.textContent), ["Ring", "Bad", "Eye"] ); for (const item of items) { @@ -165,9 +163,9 @@ QUnit.test("can execute the callback of settings", async (assert) => { env = await makeTestEnv(testConfig); userMenuRegistry.add("profile", preferencesItem); userMenu = await mount(UserMenu, { env, target }); - await click(userMenu.el.querySelector("button.o_dropdown_toggler")); - assert.containsOnce(userMenu.el, "ul.o_dropdown_menu li.o_dropdown_item"); - const item = userMenu.el.querySelector("ul.o_dropdown_menu li.o_dropdown_item"); + await click(userMenu.el.querySelector("button.dropdown-toggle")); + assert.containsOnce(userMenu.el, ".dropdown-menu .dropdown-item"); + const item = userMenu.el.querySelector(".dropdown-menu .dropdown-item"); assert.strictEqual(item.textContent, "Preferences"); await click(item); assert.verifySteps(["7", "Change My Preferences"]); diff --git a/addons/web_editor/static/lib/odoo-editor/src/style.css b/addons/web_editor/static/lib/odoo-editor/src/style.css index f54edeb88c0..f6b963a7a1a 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/style.css +++ b/addons/web_editor/static/lib/odoo-editor/src/style.css @@ -136,11 +136,11 @@ .oe-toolbar li > a.dropdown-item { color: white; } -.oe-toolbar .dropdown-item:hover, .dropdown-item:focus { +.oe-toolbar .dropdown-item:hover, .oe-toolbar .dropdown-item:focus { color: white; background: #868686; } -.oe-toolbar .dropdown-item.active, .dropdown-item:active { +.oe-toolbar .dropdown-item.active, .oe-toolbar .dropdown-item:active { color: white; background: #555555; } diff --git a/addons/web_editor/static/src/scss/wysiwyg.scss b/addons/web_editor/static/src/scss/wysiwyg.scss index 438f95a881d..37777350fc0 100644 --- a/addons/web_editor/static/src/scss/wysiwyg.scss +++ b/addons/web_editor/static/src/scss/wysiwyg.scss @@ -182,7 +182,7 @@ $o-we-toolbar-color-clickable-active: $o-we-bg-darkest; .dropdown-item { &.active, &.selected { - &:not(.o_dropdown_item_active_noarrow):before { + &:not(.dropdown-item_active_noarrow):before { transform: translate(-1.5em, 0); height: 100%; display: flex; diff --git a/addons/web_tour/static/tests/debug_manager_tests.js b/addons/web_tour/static/tests/debug_manager_tests.js index c32ddba283f..f7972737fe4 100644 --- a/addons/web_tour/static/tests/debug_manager_tests.js +++ b/addons/web_tour/static/tests/debug_manager_tests.js @@ -63,10 +63,10 @@ QUnit.module("Tours", (hooks) => { const debugManager = await mount(DebugMenuParent, { env, target }); registerCleanup(() => debugManager.destroy()); - await click(debugManager.el.querySelector("button.o_dropdown_toggler")); + await click(debugManager.el.querySelector("button.dropdown-toggle")); - assert.containsOnce(debugManager.el, ".o_dropdown_item"); - await click(debugManager.el.querySelector(".o_dropdown_item")); + assert.containsOnce(debugManager.el, ".dropdown-item"); + await click(debugManager.el.querySelector(".dropdown-item")); assert.verifySteps(["consume"]); }); }); diff --git a/addons/website/static/tests/tours/dashboard_tour.js b/addons/website/static/tests/tours/dashboard_tour.js index 610adb2e5eb..343e90bf846 100644 --- a/addons/website/static/tests/tours/dashboard_tour.js +++ b/addons/website/static/tests/tours/dashboard_tour.js @@ -18,7 +18,7 @@ odoo.define("website.tour.backend_dashboard", function (require) { trigger: 'button[data-menu-xmlid="website.menu_dashboard"]', }, { - trigger: 'li[data-menu-xmlid="website.menu_website_google_analytics"]', + trigger: '.dropdown-item[data-menu-xmlid="website.menu_website_google_analytics"]', }, { // Visits section should always be present even when empty / not hooked to anything diff --git a/addons/website/views/website_navbar_templates.xml b/addons/website/views/website_navbar_templates.xml index 38adf5d4ffb..4432ac7ab43 100644 --- a/addons/website/views/website_navbar_templates.xml +++ b/addons/website/views/website_navbar_templates.xml @@ -3,14 +3,14 @@ @@ -31,22 +31,22 @@

    diff --git a/addons/website_customer/views/website_customer_templates.xml b/addons/website_customer/views/website_customer_templates.xml index 38e737c0cc3..0274fc10525 100644 --- a/addons/website_customer/views/website_customer_templates.xml +++ b/addons/website_customer/views/website_customer_templates.xml @@ -143,7 +143,7 @@ diff --git a/addons/website_event/views/website_templates.xml b/addons/website_event/views/website_templates.xml index aaebd083f5b..ce4fdaaf7b6 100644 --- a/addons/website_event/views/website_templates.xml +++ b/addons/website_event/views/website_templates.xml @@ -13,7 +13,7 @@ diff --git a/addons/website_event_exhibitor/views/event_exhibitor_templates_page.xml b/addons/website_event_exhibitor/views/event_exhibitor_templates_page.xml index 38835381866..97d2172b07a 100644 --- a/addons/website_event_exhibitor/views/event_exhibitor_templates_page.xml +++ b/addons/website_event_exhibitor/views/event_exhibitor_templates_page.xml @@ -199,7 +199,7 @@