UNPKG

@luminati-io/webdriverio8

Version:

Next-gen browser and mobile automation test framework for Node.js

119 lines 11.5 kB
/** * check if element is within the viewport or is overlapped by another element or disabled * @param {HTMLElement} elem element to check * @return {Boolean} false if element is not overlapped */ export default function isElementClickable(elem) { if (!elem.getBoundingClientRect || !elem.scrollIntoView || !elem.contains || !elem.getClientRects || !document.elementFromPoint) { return false; } // Edge before switching to Chromium const isOldEdge = !!window.StyleMedia; // returns true for Chrome and Firefox and false for Safari, Edge and IE const scrollIntoViewFullSupport = !(window.safari || isOldEdge); // get overlapping element function getOverlappingElement(elem, context) { context = 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); } // get overlapping element rects (currently only the first) // applicable if element's text is multiline. function getOverlappingRects(elem, context) { context = context || document; const elems = []; const rects = elem.getClientRects(); // webdriver clicks on center of the first element's rect (line of text), it might change in future const rect = rects[0]; const x = rect.left + (rect.width / 2); const y = rect.top + (rect.height / 2); elems.push(context.elementFromPoint(x, y)); return elems; } // get overlapping elements function getOverlappingElements(elem, context) { return [getOverlappingElement(elem, context)].concat(getOverlappingRects(elem, context)); } // is a node a descendant of a given node function nodeContains(elem, otherNode) { // Edge doesn't support neither Shadow Dom nor contains if ShadowRoot polyfill is used if (isOldEdge) { let tmpElement = otherNode; while (tmpElement) { if (tmpElement === elem) { return true; } tmpElement = tmpElement.parentNode; // DocumentFragment / ShadowRoot polyfill like ShadyRoot if (tmpElement && tmpElement.nodeType === 11 && tmpElement.host) { tmpElement = tmpElement.host; } } return false; } return elem.contains(otherNode); } // is one of overlapping elements the `elem` or one of its child function isOverlappingElementMatch(elementsFromPoint, elem) { if (elementsFromPoint.some(function (elementFromPoint) { return elementFromPoint === elem || nodeContains(elem, elementFromPoint); })) { return true; } // shadow root // filter unique elements with shadowRoot // @ts-ignore let elemsWithShadowRoot = [].concat(elementsFromPoint); elemsWithShadowRoot = elemsWithShadowRoot.filter(function (x) { return x && x.shadowRoot && x.shadowRoot.elementFromPoint; }); // getOverlappingElements of every element with shadowRoot let shadowElementsFromPoint = []; for (let i = 0; i < elemsWithShadowRoot.length; ++i) { const shadowElement = elemsWithShadowRoot[i]; shadowElementsFromPoint = shadowElementsFromPoint.concat(getOverlappingElements(elem, shadowElement.shadowRoot)); } // remove duplicates and parents // @ts-ignore shadowElementsFromPoint = [].concat(shadowElementsFromPoint); shadowElementsFromPoint = shadowElementsFromPoint.filter(function (x) { return !elementsFromPoint.includes(x); }); if (shadowElementsFromPoint.length === 0) { return false; } return isOverlappingElementMatch(shadowElementsFromPoint, elem); } // copied from `isElementInViewport.js` function isElementInViewport(elem) { if (!elem.getBoundingClientRect) { return false; } const rect = elem.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); } function isClickable(elem) { return (isElementInViewport(elem) && elem.disabled !== true && isOverlappingElementMatch(getOverlappingElements(elem), elem)); } // scroll to the element if it's not clickable if (!isClickable(elem)) { // works well in dialogs, but the element may be still overlapped by some sticky header/footer elem.scrollIntoView(scrollIntoViewFullSupport ? { block: 'nearest', inline: 'nearest' } : false); // if element is still not clickable take another scroll attempt if (!isClickable(elem)) { // scroll to element, try put it in the screen center. // Should definitely work even if element was covered with sticky header/footer elem.scrollIntoView(scrollIntoViewFullSupport ? { block: 'center', inline: 'center' } : true); return isClickable(elem); } } return true; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXNFbGVtZW50Q2xpY2thYmxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmlwdHMvaXNFbGVtZW50Q2xpY2thYmxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsT0FBTyxVQUFVLGtCQUFrQixDQUFFLElBQWlCO0lBQ3pELElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUM5SCxPQUFPLEtBQUssQ0FBQTtJQUNoQixDQUFDO0lBRUQsb0NBQW9DO0lBQ3BDLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBRSxNQUFjLENBQUMsVUFBVSxDQUFBO0lBQzlDLHdFQUF3RTtJQUN4RSxNQUFNLHlCQUF5QixHQUFHLENBQUMsQ0FBRSxNQUFjLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxDQUFBO0lBRXhFLDBCQUEwQjtJQUMxQixTQUFTLHFCQUFxQixDQUFFLElBQWlCLEVBQUUsT0FBa0I7UUFDakUsT0FBTyxHQUFHLE9BQU8sSUFBSSxRQUFRLENBQUE7UUFDN0IsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUE7UUFDbEQsTUFBTSxDQUFDLEdBQUcsYUFBYSxDQUFDLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDckQsTUFBTSxDQUFDLEdBQUcsYUFBYSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDckQsT0FBTyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3pDLENBQUM7SUFFRCwyREFBMkQ7SUFDM0Qs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