From 21f6811cd7a7d69debd87a46f380a34ff4f4f016 Mon Sep 17 00:00:00 2001 From: rdruzhinin Date: Wed, 11 Mar 2020 20:35:43 +0700 Subject: [PATCH 1/5] fix: change overlapping logic --- lib/helper/scripts/isElementClickable.js | 71 +++++++++++++++++++----- package.json | 1 + 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/lib/helper/scripts/isElementClickable.js b/lib/helper/scripts/isElementClickable.js index 49e5d3f44..e63442f89 100644 --- a/lib/helper/scripts/isElementClickable.js +++ b/lib/helper/scripts/isElementClickable.js @@ -1,24 +1,67 @@ -function isElementClickable(elem) { - if (!elem.getBoundingClientRect || !elem.scrollIntoView || !document.elementFromPoint) { +const flatten = require('lodash.flatten'); + +function isElementClickable(element) { + if (!element.getBoundingClientRect || !element.scrollIntoView || !element.contains || !element.getClientRects || !document.elementFromPoint) { return false; } - const isElementInViewport = (elem) => { - const rect = elem.getBoundingClientRect(); - const verticleInView = (rect.top <= window.innerHeight) && ((rect.top + rect.height) > 0); - const horizontalInView = (rect.left <= window.innerWidth) && ((rect.left + rect.width) > 0); - return horizontalInView && verticleInView; + const getOverlappingElement = (elem, context = document) => { + const elemDimension = elem.getBoundingClientRect(); + const x = elemDimension.left + (elem.clientWidth / 2); + const y = elemDimension.top + (elem.clientHeight / 2); + + return context.elementFromPoint(x, y); + }; + + const getOverlappingRects = (element, context = document) => { + const rects = element.getClientRects(); + const rect = rects[0]; + const x = rect.left + (rect.width / 2); + const y = rect.top + (rect.height / 2); + + return context.elementFromPoint(x, y); }; - const getOverlappingElement = (elem) => { - const rect = elem.getBoundingClientRect(); - const x = rect.left + (elem.clientWidth / 2); - const y = rect.top + (elem.clientHeight / 2); - return document.elementFromPoint(x, y); + const getOverlappingElements = (element, context) => { + return [getOverlappingElement(element, context), getOverlappingRects(element, context)]; + }; + + const isOverlappingElementMatch = (elementsFromPoint, elem) => { + if (elementsFromPoint.some(elementFromPoint => elementFromPoint === elem || elem.contains(elementFromPoint))) { + return true; + } + + let elementsWithShadowRoot = [...new Set(elementsFromPoint)]; + elementsWithShadowRoot = elementsWithShadowRoot.filter(elem => elem && elem.shadowRoot && elem.shadowRoot.elementFromPoint); + + let shadowElementsFromPoint = elementsWithShadowRoot.map(shadowElement => flatten(getOverlappingElements(elem, shadowElement.shadowRoot))); + shadowElementsFromPoint = [...new Set(shadowElementsFromPoint)]; + shadowElementsFromPoint = shadowElementsFromPoint.filter(element => !elementsFromPoint.includes(element)); + + if (shadowElementsFromPoint.length === 0) { + return false; + } + + return isOverlappingElementMatch(shadowElementsFromPoint, elem); + }; + + const isElementInViewport = (element) => { + if (!element.getBoundingClientRect) { + return false; + } + + const rect = element.getBoundingClientRect(); + + const windowHeight = (window.innerHeight || document.documentElement.clientHeight); + const windowWidth = (window.innerWidth || document.documentElement.clientWidth); + + const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) > 0); + const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) > 0); + + return (vertInView && horInView); }; - const isClickable = elem => elem.disabled !== true && isElementInViewport(elem) && getOverlappingElement(elem) === elem; - return isClickable(elem); + return isElementInViewport(element) && element.disabled !== true && isOverlappingElementMatch(getOverlappingElements(element), element); } module.exports = isElementClickable; diff --git a/package.json b/package.json index bb3c725f9..9c6402df4 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "inquirer": "^6.5.2", "js-beautify": "^1.10.2", "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", "lodash.merge": "^4.6.2", "mkdirp": "^0.5.1", "mocha": "^6.2.2", From e7a182265386308c7ef71b117721eb731d610d16 Mon Sep 17 00:00:00 2001 From: rdruzhinin Date: Thu, 12 Mar 2020 11:45:55 +0700 Subject: [PATCH 2/5] test: added tests --- .../data/app/view/form/wait_for_clickable.php | 16 ++++ test/helper/Puppeteer_test.js | 16 ++++ test/helper/WebDriverIO_test.js | 91 +++++++++++++++++++ 3 files changed, 123 insertions(+) diff --git a/test/data/app/view/form/wait_for_clickable.php b/test/data/app/view/form/wait_for_clickable.php index 4ca55095a..1ae830fce 100644 --- a/test/data/app/view/form/wait_for_clickable.php +++ b/test/data/app/view/form/wait_for_clickable.php @@ -1,4 +1,12 @@ + + +