From e9ba620f38b2247c552e5d3fea3cc5c0c830dafc Mon Sep 17 00:00:00 2001 From: Andreas Fernandez <a.fernandez@scripting-base.de> Date: Sat, 14 Aug 2021 15:16:15 +0200 Subject: [PATCH] [BUGFIX] Fix various context menu visibility issues The context menu skeleton is partially visible for a very short time, before its items are rendered and event listeners are attached. This is revealed by some flaky acceptance tests and was previously workarounded by an additional ->wait() call in the tests. The context menu stays hidden now until everything is set up and the workaround in the AC tests is removed again. The context menu gets hidden after 500ms once the user moved the mouse out of its boundaries. However, that timeout was never reset which closed another context menu that might have opened within that 500ms time span. To circument this issue, such timeouts are now monitored and cleared again once a new context menu is requested. Resolves: #94891 Releases: master, 10.4 Change-Id: Ia0551d8c0b41edeca27cd0b15e4285a89ad2c171 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70592 Tested-by: core-ci <typo3@b13.com> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Alexander Nitsche <typo3@alexandernitsche.com> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Alexander Nitsche <typo3@alexandernitsche.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- .../Public/TypeScript/ContextMenu.ts | 48 ++++++++++++------- .../Public/JavaScript/ContextMenu.js | 2 +- .../Acceptance/Backend/Impexp/ExportCest.php | 8 ---- .../Acceptance/Backend/Impexp/ImportCest.php | 14 ------ .../Acceptance/Backend/Impexp/UsersCest.php | 18 ------- 5 files changed, 33 insertions(+), 57 deletions(-) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextMenu.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextMenu.ts index cd8a82381c6c..7018abc6b87a 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextMenu.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextMenu.ts @@ -46,9 +46,15 @@ interface MenuItems { */ class ContextMenu { private mousePos: MousePosition = {X: null, Y: null}; + + /** + * If this.delayContextMenuHide is set to true, any parent context menu will stay visibile even if the cursor is out + * of its boundaries. + */ private delayContextMenuHide: boolean = false; private record: ActiveRecord = {uid: null, table: null}; private eventSources: Element[] = []; + private closeMenuTimeout: { [key: string]: number } = {}; /** * @param {MenuItem} item @@ -88,8 +94,8 @@ class ContextMenu { */ private static initializeContextMenuContainer(): void { if ($('#contentMenu0').length === 0) { - const code = '<div id="contentMenu0" class="context-menu"></div>' - + '<div id="contentMenu1" class="context-menu" style="display: block;"></div>'; + const code = '<div id="contentMenu0" class="context-menu" style="display: none;"></div>' + + '<div id="contentMenu1" class="context-menu" style="display: none;"></div>'; $('body').append(code); } } @@ -128,6 +134,9 @@ class ContextMenu { * @param {Element} eventSource Source Element */ public show(table: string, uid: number|string, context: string, enDisItems: string, addParams: string, eventSource: Element = null): void { + this.hideAll(); + this.closeMenuTimeout = {}; + this.record = {table: table, uid: uid}; // fix: [tabindex=-1] is not focusable!!! const focusableSource = eventSource.matches('a, button, [tabindex]') ? eventSource : eventSource.closest('a, button, [tabindex]'); @@ -435,34 +444,41 @@ class ContextMenu { this.hide(obj); } else if ($element.length > 0 && $element.is(':visible')) { this.delayContextMenuHide = true; + window.clearTimeout(this.closeMenuTimeout[obj]); } } /** * @param {string} obj + * @param {boolean} withDelay */ - private hide(obj: string): void { + private hide(obj: string, withDelay: boolean = true): void { this.delayContextMenuHide = false; - window.setTimeout( - (): void => { - if (!this.delayContextMenuHide) { - $(obj).hide(); - const source = this.eventSources.pop(); - if (source) { - $(source).focus(); - } + window.clearTimeout(this.closeMenuTimeout[obj]); + + const delayHandler = () => { + if (!this.delayContextMenuHide) { + $(obj).hide(); + const source = this.eventSources.pop(); + if (source) { + $(source).focus(); } - }, - 500 - ); + } + }; + + if (withDelay) { + this.closeMenuTimeout[obj] = window.setTimeout(delayHandler, 500); + } else { + delayHandler(); + } } /** * Hides all context menus */ private hideAll(): void { - this.hide('#contentMenu0'); - this.hide('#contentMenu1'); + this.hide('#contentMenu0', false); + this.hide('#contentMenu1', false); } } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js index dd727110f8b6..23ad3c4bf102 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","./ContextMenuActions","TYPO3/CMS/Core/Event/ThrottleEvent"],(function(t,e,s,i,n,o){"use strict";s=__importDefault(s);class a{constructor(){this.mousePos={X:null,Y:null},this.delayContextMenuHide=!1,this.record={uid:null,table:null},this.eventSources=[],this.storeMousePositionEvent=t=>{this.mousePos={X:t.pageX,Y:t.pageY},this.mouseOutFromMenu("#contentMenu0"),this.mouseOutFromMenu("#contentMenu1")},s.default(document).on("click contextmenu",".t3js-contextmenutrigger",t=>{const e=s.default(t.currentTarget);e.prop("onclick")&&"click"===t.type||(t.preventDefault(),this.show(e.data("table"),e.data("uid"),e.data("context"),e.data("iteminfo"),e.data("parameters"),t.target))}),new o("mousemove",this.storeMousePositionEvent.bind(this),50).bindTo(document)}static drawActionItem(t){const e=t.additionalAttributes||{};let s="";for(const t of Object.entries(e)){const[e,i]=t;s+=" "+e+'="'+i+'"'}return'<li role="menuitem" class="list-group-item" tabindex="-1" data-callback-action="'+t.callbackAction+'"'+s+'><span class="list-group-item-icon">'+t.icon+"</span> "+t.label+"</li>"}static within(t,e,s){const i=t.offset();return s>=i.top&&s<i.top+t.height()&&e>=i.left&&e<i.left+t.width()}static initializeContextMenuContainer(){if(0===s.default("#contentMenu0").length){const t='<div id="contentMenu0" class="context-menu"></div><div id="contentMenu1" class="context-menu" style="display: block;"></div>';s.default("body").append(t)}}show(t,e,s,i,n,o=null){this.record={table:t,uid:e};const a=o.matches("a, button, [tabindex]")?o:o.closest("a, button, [tabindex]");this.eventSources.push(a);let l="";void 0!==t&&(l+="table="+encodeURIComponent(t)),void 0!==e&&(l+=(l.length>0?"&":"")+"uid="+e),void 0!==s&&(l+=(l.length>0?"&":"")+"context="+s),void 0!==i&&(l+=(l.length>0?"&":"")+"enDisItems="+i),void 0!==n&&(l+=(l.length>0?"&":"")+"addParams="+n),this.fetch(l)}fetch(t){const e=TYPO3.settings.ajaxUrls.contextmenu;new i(e).withQueryArguments(t).get().then(async t=>{const e=await t.resolve();void 0!==t&&Object.keys(t).length>0&&this.populateData(e,0)})}populateData(e,i){a.initializeContextMenuContainer();const o=s.default("#contentMenu"+i);if(o.length&&(0===i||s.default("#contentMenu"+(i-1)).is(":visible"))){const a=this.drawMenu(e,i);o.html('<ul class="list-group">'+a+"</ul>"),s.default("li.list-group-item",o).on("click",e=>{e.preventDefault();const o=s.default(e.currentTarget);if(o.hasClass("list-group-item-submenu"))return void this.openSubmenu(i,o,!1);const a=o.data("callback-action"),l=o.data("callback-module");o.data("callback-module")?t([l],t=>{t[a].bind(o)(this.record.table,this.record.uid)}):n&&"function"==typeof n[a]?n[a].bind(o)(this.record.table,this.record.uid):console.log("action: "+a+" not found"),this.hideAll()}),s.default("li.list-group-item",o).on("keydown",t=>{const e=s.default(t.currentTarget);switch(t.key){case"Down":case"ArrowDown":this.setFocusToNextItem(e.get(0));break;case"Up":case"ArrowUp":this.setFocusToPreviousItem(e.get(0));break;case"Right":case"ArrowRight":if(!e.hasClass("list-group-item-submenu"))return;this.openSubmenu(i,e,!0);break;case"Home":this.setFocusToFirstItem(e.get(0));break;case"End":this.setFocusToLastItem(e.get(0));break;case"Enter":case"Space":e.click();break;case"Esc":case"Escape":case"Left":case"ArrowLeft":this.hide("#"+e.parents(".context-menu").first().attr("id"));break;case"Tab":this.hideAll();break;default:return}t.preventDefault()}),o.css(this.getPosition(o,!1)).show(),s.default("li.list-group-item[tabindex=-1]",o).first().focus()}}setFocusToPreviousItem(t){let e=this.getItemBackward(t.previousElementSibling);e||(e=this.getLastItem(t)),e.focus()}setFocusToNextItem(t){let e=this.getItemForward(t.nextElementSibling);e||(e=this.getFirstItem(t)),e.focus()}setFocusToFirstItem(t){let e=this.getFirstItem(t);e&&e.focus()}setFocusToLastItem(t){let e=this.getLastItem(t);e&&e.focus()}getItemBackward(t){for(;t&&(!t.classList.contains("list-group-item")||"-1"!==t.getAttribute("tabindex"));)t=t.previousElementSibling;return t}getItemForward(t){for(;t&&(!t.classList.contains("list-group-item")||"-1"!==t.getAttribute("tabindex"));)t=t.nextElementSibling;return t}getFirstItem(t){return this.getItemForward(t.parentElement.firstElementChild)}getLastItem(t){return this.getItemBackward(t.parentElement.lastElementChild)}openSubmenu(t,e,i){this.eventSources.push(e[0]);const n=s.default("#contentMenu"+(t+1)).html("");e.next().find(".list-group").clone(!0).appendTo(n),n.css(this.getPosition(n,i)).show(),s.default(".list-group-item[tabindex=-1]",n).first().focus()}getPosition(t,e){let i=0,n=0;if(this.eventSources.length&&(null===this.mousePos.X||e)){const t=this.eventSources[this.eventSources.length-1].getBoundingClientRect();i=this.eventSources.length>1?t.right:t.x,n=t.y}else i=this.mousePos.X,n=this.mousePos.Y;const o=s.default(window).width()-20,a=s.default(window).height(),l=t.width(),u=t.height(),r=i-s.default(document).scrollLeft(),c=n-s.default(document).scrollTop();return a-u<c&&(c>u?n-=u-10:n+=a-u-c),o-l<r&&(r>l?i-=l-10:o-l-r<s.default(document).scrollLeft()?i=s.default(document).scrollLeft():i+=o-l-r),{left:i+"px",top:n+"px"}}drawMenu(t,e){let s="";for(const i of Object.values(t))if("item"===i.type)s+=a.drawActionItem(i);else if("divider"===i.type)s+='<li role="separator" class="list-group-item list-group-item-divider"></li>';else if("submenu"===i.type||i.childItems){s+='<li role="menuitem" aria-haspopup="true" class="list-group-item list-group-item-submenu" tabindex="-1"><span class="list-group-item-icon">'+i.icon+"</span> "+i.label+' <span class="fa fa-caret-right"></span></li>';s+='<div class="context-menu contentMenu'+(e+1)+'" style="display:none;"><ul role="menu" class="list-group">'+this.drawMenu(i.childItems,1)+"</ul></div>"}return s}mouseOutFromMenu(t){const e=s.default(t);e.length>0&&e.is(":visible")&&!a.within(e,this.mousePos.X,this.mousePos.Y)?this.hide(t):e.length>0&&e.is(":visible")&&(this.delayContextMenuHide=!0)}hide(t){this.delayContextMenuHide=!1,window.setTimeout(()=>{if(!this.delayContextMenuHide){s.default(t).hide();const e=this.eventSources.pop();e&&s.default(e).focus()}},500)}hideAll(){this.hide("#contentMenu0"),this.hide("#contentMenu1")}}return new a})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","./ContextMenuActions","TYPO3/CMS/Core/Event/ThrottleEvent"],(function(t,e,s,i,n,o){"use strict";s=__importDefault(s);class u{constructor(){this.mousePos={X:null,Y:null},this.delayContextMenuHide=!1,this.record={uid:null,table:null},this.eventSources=[],this.closeMenuTimeout={},this.storeMousePositionEvent=t=>{this.mousePos={X:t.pageX,Y:t.pageY},this.mouseOutFromMenu("#contentMenu0"),this.mouseOutFromMenu("#contentMenu1")},s.default(document).on("click contextmenu",".t3js-contextmenutrigger",t=>{const e=s.default(t.currentTarget);e.prop("onclick")&&"click"===t.type||(t.preventDefault(),this.show(e.data("table"),e.data("uid"),e.data("context"),e.data("iteminfo"),e.data("parameters"),t.target))}),new o("mousemove",this.storeMousePositionEvent.bind(this),50).bindTo(document)}static drawActionItem(t){const e=t.additionalAttributes||{};let s="";for(const t of Object.entries(e)){const[e,i]=t;s+=" "+e+'="'+i+'"'}return'<li role="menuitem" class="list-group-item" tabindex="-1" data-callback-action="'+t.callbackAction+'"'+s+'><span class="list-group-item-icon">'+t.icon+"</span> "+t.label+"</li>"}static within(t,e,s){const i=t.offset();return s>=i.top&&s<i.top+t.height()&&e>=i.left&&e<i.left+t.width()}static initializeContextMenuContainer(){if(0===s.default("#contentMenu0").length){const t='<div id="contentMenu0" class="context-menu" style="display: none;"></div><div id="contentMenu1" class="context-menu" style="display: none;"></div>';s.default("body").append(t)}}show(t,e,s,i,n,o=null){this.hideAll(),this.closeMenuTimeout={},this.record={table:t,uid:e};const u=o.matches("a, button, [tabindex]")?o:o.closest("a, button, [tabindex]");this.eventSources.push(u);let l="";void 0!==t&&(l+="table="+encodeURIComponent(t)),void 0!==e&&(l+=(l.length>0?"&":"")+"uid="+e),void 0!==s&&(l+=(l.length>0?"&":"")+"context="+s),void 0!==i&&(l+=(l.length>0?"&":"")+"enDisItems="+i),void 0!==n&&(l+=(l.length>0?"&":"")+"addParams="+n),this.fetch(l)}fetch(t){const e=TYPO3.settings.ajaxUrls.contextmenu;new i(e).withQueryArguments(t).get().then(async t=>{const e=await t.resolve();void 0!==t&&Object.keys(t).length>0&&this.populateData(e,0)})}populateData(e,i){u.initializeContextMenuContainer();const o=s.default("#contentMenu"+i);if(o.length&&(0===i||s.default("#contentMenu"+(i-1)).is(":visible"))){const u=this.drawMenu(e,i);o.html('<ul class="list-group">'+u+"</ul>"),s.default("li.list-group-item",o).on("click",e=>{e.preventDefault();const o=s.default(e.currentTarget);if(o.hasClass("list-group-item-submenu"))return void this.openSubmenu(i,o,!1);const u=o.data("callback-action"),l=o.data("callback-module");o.data("callback-module")?t([l],t=>{t[u].bind(o)(this.record.table,this.record.uid)}):n&&"function"==typeof n[u]?n[u].bind(o)(this.record.table,this.record.uid):console.log("action: "+u+" not found"),this.hideAll()}),s.default("li.list-group-item",o).on("keydown",t=>{const e=s.default(t.currentTarget);switch(t.key){case"Down":case"ArrowDown":this.setFocusToNextItem(e.get(0));break;case"Up":case"ArrowUp":this.setFocusToPreviousItem(e.get(0));break;case"Right":case"ArrowRight":if(!e.hasClass("list-group-item-submenu"))return;this.openSubmenu(i,e,!0);break;case"Home":this.setFocusToFirstItem(e.get(0));break;case"End":this.setFocusToLastItem(e.get(0));break;case"Enter":case"Space":e.click();break;case"Esc":case"Escape":case"Left":case"ArrowLeft":this.hide("#"+e.parents(".context-menu").first().attr("id"));break;case"Tab":this.hideAll();break;default:return}t.preventDefault()}),o.css(this.getPosition(o,!1)).show(),s.default("li.list-group-item[tabindex=-1]",o).first().focus()}}setFocusToPreviousItem(t){let e=this.getItemBackward(t.previousElementSibling);e||(e=this.getLastItem(t)),e.focus()}setFocusToNextItem(t){let e=this.getItemForward(t.nextElementSibling);e||(e=this.getFirstItem(t)),e.focus()}setFocusToFirstItem(t){let e=this.getFirstItem(t);e&&e.focus()}setFocusToLastItem(t){let e=this.getLastItem(t);e&&e.focus()}getItemBackward(t){for(;t&&(!t.classList.contains("list-group-item")||"-1"!==t.getAttribute("tabindex"));)t=t.previousElementSibling;return t}getItemForward(t){for(;t&&(!t.classList.contains("list-group-item")||"-1"!==t.getAttribute("tabindex"));)t=t.nextElementSibling;return t}getFirstItem(t){return this.getItemForward(t.parentElement.firstElementChild)}getLastItem(t){return this.getItemBackward(t.parentElement.lastElementChild)}openSubmenu(t,e,i){this.eventSources.push(e[0]);const n=s.default("#contentMenu"+(t+1)).html("");e.next().find(".list-group").clone(!0).appendTo(n),n.css(this.getPosition(n,i)).show(),s.default(".list-group-item[tabindex=-1]",n).first().focus()}getPosition(t,e){let i=0,n=0;if(this.eventSources.length&&(null===this.mousePos.X||e)){const t=this.eventSources[this.eventSources.length-1].getBoundingClientRect();i=this.eventSources.length>1?t.right:t.x,n=t.y}else i=this.mousePos.X,n=this.mousePos.Y;const o=s.default(window).width()-20,u=s.default(window).height(),l=t.width(),a=t.height(),c=i-s.default(document).scrollLeft(),r=n-s.default(document).scrollTop();return u-a<r&&(r>a?n-=a-10:n+=u-a-r),o-l<c&&(c>l?i-=l-10:o-l-c<s.default(document).scrollLeft()?i=s.default(document).scrollLeft():i+=o-l-c),{left:i+"px",top:n+"px"}}drawMenu(t,e){let s="";for(const i of Object.values(t))if("item"===i.type)s+=u.drawActionItem(i);else if("divider"===i.type)s+='<li role="separator" class="list-group-item list-group-item-divider"></li>';else if("submenu"===i.type||i.childItems){s+='<li role="menuitem" aria-haspopup="true" class="list-group-item list-group-item-submenu" tabindex="-1"><span class="list-group-item-icon">'+i.icon+"</span> "+i.label+' <span class="fa fa-caret-right"></span></li>';s+='<div class="context-menu contentMenu'+(e+1)+'" style="display:none;"><ul role="menu" class="list-group">'+this.drawMenu(i.childItems,1)+"</ul></div>"}return s}mouseOutFromMenu(t){const e=s.default(t);e.length>0&&e.is(":visible")&&!u.within(e,this.mousePos.X,this.mousePos.Y)?this.hide(t):e.length>0&&e.is(":visible")&&(this.delayContextMenuHide=!0,window.clearTimeout(this.closeMenuTimeout[t]))}hide(t,e=!0){this.delayContextMenuHide=!1,window.clearTimeout(this.closeMenuTimeout[t]);const i=()=>{if(!this.delayContextMenuHide){s.default(t).hide();const e=this.eventSources.pop();e&&s.default(e).focus()}};e?this.closeMenuTimeout[t]=window.setTimeout(i,500):i()}hideAll(){this.hide("#contentMenu0",!1),this.hide("#contentMenu1",!1)}}return new u})); \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ExportCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ExportCest.php index f3b2da3f10bc..dd9938f44fd8 100644 --- a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ExportCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ExportCest.php @@ -84,8 +84,6 @@ class ExportCest $I->click($selectedPageIcon); $I->waitForElementVisible($contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($contextMenuMore); $I->waitForElementVisible($contextMenuExport, 5); $I->click($contextMenuExport); @@ -155,8 +153,6 @@ class ExportCest $I->waitForElementNotVisible('#nprogress'); $I->click($recordIcon, $recordTable); $I->waitForElementVisible($contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($contextMenuMore); $I->waitForElementVisible($contextMenuExport, 5); $I->click($contextMenuExport); @@ -188,8 +184,6 @@ class ExportCest $I->click($pageIcon); $I->waitForElementVisible($contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($contextMenuMore); $I->waitForElementVisible($contextMenuExport, 5); $I->click($contextMenuExport); @@ -291,8 +285,6 @@ class ExportCest $I->waitForElementNotVisible('#nprogress'); $I->click($sysLanguageIcon, $sysLanguageTable); $I->waitForElementVisible($contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($contextMenuMore); $I->waitForText('Export'); $I->waitForElementVisible($contextMenuExport, 5); diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ImportCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ImportCest.php index 19507fdc4a3c..ab40303436b2 100644 --- a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ImportCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/ImportCest.php @@ -92,8 +92,6 @@ class ImportCest $pageInPageTreeIcon = '//*[text()=\'' . $pageInPageTreeTitle . '\']/../*[contains(@class, \'node-icon-container\')]'; $I->click($pageInPageTreeIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -112,8 +110,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -170,8 +166,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -212,8 +206,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -265,8 +257,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -321,8 +311,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -380,8 +368,6 @@ class ImportCest $I->click($page1Icon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/UsersCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/UsersCest.php index 887221813a55..0ce533febbd9 100644 --- a/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/UsersCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Backend/Impexp/UsersCest.php @@ -67,8 +67,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuExport, 5); $I->seeElement($this->contextMenuExport); @@ -92,8 +90,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuExport, 5); $I->seeElement($this->contextMenuExport); @@ -115,8 +111,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -127,8 +121,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -152,8 +144,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -165,8 +155,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuImport, 5); $I->click($this->contextMenuImport); @@ -195,8 +183,6 @@ class UsersCest extends AbstractCest $I->click($this->inPageTree . ' .node.identifier-0_0 .node-icon-container'); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuExport, 5); $I->click($this->contextMenuImport); @@ -209,8 +195,6 @@ class UsersCest extends AbstractCest $I->click('List'); $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuExport, 5); $I->click($this->contextMenuImport); @@ -224,8 +208,6 @@ class UsersCest extends AbstractCest $I->click($selectedPageIcon); $I->waitForElementVisible($this->contextMenuMore, 5); - // Give JS 2 seconds for event registration, so click on 'more' works - $I->wait(1); $I->click($this->contextMenuMore); $I->waitForElementVisible($this->contextMenuExport, 5); $I->click($this->contextMenuImport); -- GitLab