From 39e71353c5d58f7af6b3270911a24d98b73cad4e Mon Sep 17 00:00:00 2001 From: Christophe Monniez Date: Thu, 21 Mar 2019 14:16:39 +0000 Subject: [PATCH] [FIX] web: focus on close button when before closing a modal During the clickEverywhere test, when a modal is opened, the hide method is called to bypass it. This is not realistic and does not work in some cases. For example in Point of sale, menu "Reporting/Sales Details", a modal is opened with a DateTimePicker (tempus dominus) already opened. When hiding or closing the modal, the DateTimePicker needs to perform some cleanup. If the modal is simply hidden, the DateTimePicker is not cleanly destroyed. With this commit, a modal is closed by clicking on its close button and before that, the focus is set on the close button to let the datepicker widget do its stuff on losing focus. Also, a more realistic click is done by trigerring more events (code adapted from tour helper). closes odoo/odoo#32038 Signed-off-by: Christophe Monniez (moc) --- addons/web/static/src/js/tools/test_menus.js | 38 +++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/addons/web/static/src/js/tools/test_menus.js b/addons/web/static/src/js/tools/test_menus.js index 52891357e5d..694d13d8682 100644 --- a/addons/web/static/src/js/tools/test_menus.js +++ b/addons/web/static/src/js/tools/test_menus.js @@ -100,7 +100,7 @@ }).then(function(){ // no effect in community var $homeMenu = $("nav.o_main_navbar > a.o_menu_toggle.fa-th"); - $homeMenu.click(); + _click($homeMenu); return new Promise(function(resolve){ setTimeout(function(){ resolve(); @@ -123,13 +123,16 @@ console.log("Testing menu", element.innerText.trim(), " ", element.dataset.menuXmlid); testedMenus.push(element.dataset.menuXmlid); var startActionCount = clientActionCount; - element.click(); + _click($(element)); var isModal = false; return waitForCondition(function() { // sometimes, the app is just a modal that needs to be closed var $modal = $('.modal[role="dialog"][open="open"]'); if ($modal.length > 0) { - $modal.modal('hide'); + var $closeButton = $('header > button.close'); + if ($closeButton.length > 0) { + _click($closeButton); + } else { $modal.modal('hide'); } isModal = true; return true; } @@ -178,7 +181,7 @@ setTimeout(function() { var $element = $("nav.o_cp_switch_buttons > button[data-view-type=" + viewType + "]"); console.log('Clicking on: ', $element[0].dataset.viewType, ' view switcher'); - $element.click(); + _click($element); },250); var waitViewSwitch = waitForCondition(function(){ return $('.o_action_manager> .o_action.o_view_controller').data('view-type') === viewType; @@ -198,7 +201,7 @@ var $filters = $('.o_filters_menu > .o_menu_item'); console.log("Testing " + $filters.length + " filters"); var filter_ids = _.compact(_.map($filters, function(f) { return f.dataset.id})); - _.each(filter_ids, function(filter_id){ + filter_ids.forEach(function(filter_id){ filterProm = filterProm.then(function(){ var currentViewCount = viewUpdateCount; var $filter = $('.o_menu_item[data-id="' + filter_id + '"] a'); @@ -208,16 +211,16 @@ return Promise.resolve(); } console.log('Clicking on filter "', $filter.text().trim(), '"'); - $filter[0].click(); + _click($filter); setTimeout(function() { var $filterOption = $('.o_menu_item .o_item_option[data-item_id="' + filter_id + '"]:not(.selected) a'); // In case the filter is a date filter, we need to click on the first filter option (like 'today','This week' ...) if ($filterOption.length > 0) { console.log('Clicking on filter option "', $filterOption[0], '"'); - $filterOption[0].click(); + _click($filterOption); console.log('And now on filter again'); $filter = $('.o_menu_item[data-id="' + filter_id + '"] a'); - $filter[0].click(); // To avoid that the next view fold the options + _click($filter); // To avoid that the next view fold the options } }, 250); return waitForCondition(function() { @@ -277,5 +280,24 @@ } + /* + * More realistic click action. + * @param {jQueryElement} $element the element on which to perform the click + */ + function _click($element) { + triggerMouseEvent($element, "mouseover"); + triggerMouseEvent($element, "mouseenter"); + triggerMouseEvent($element, "mousedown"); + triggerMouseEvent($element, "mouseup"); + triggerMouseEvent($element, "focus"); + triggerMouseEvent($element, "click"); + + function triggerMouseEvent($el, type, count) { + var e = document.createEvent("MouseEvents"); + e.initMouseEvent(type, true, true, window, count || 0, 0, 0, 0, 0, false, false, false, false, 0, $el[0]); + $el[0].dispatchEvent(e); + } + } + exports.clickEverywhere = clickEverywhere; })(window);