@serenity-js/web
Version:
Serenity/JS Screenplay Pattern library offering a flexible, web driver-agnostic approach for interacting with web-based user interfaces and components, suitable for various testing contexts
96 lines • 4.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isVisible = isVisible;
/* eslint-disable unicorn/no-for-loop,unicorn/consistent-function-scoping */
/* c8 ignore start */
function isVisible(domNode) {
const style = window.getComputedStyle(domNode);
if (style.opacity === '0') {
return false;
}
if (style.visibility === 'hidden') {
return false;
}
if (style.display === 'none') {
return false;
}
if (!domNode.getBoundingClientRect || !domNode.scrollIntoView || !domNode.contains || !domNode.getClientRects || !document.elementFromPoint) {
return false;
}
// Edge before switching to Chromium
const isOldEdge = !!window['StyleMedia'];
// get overlapping element
function getOverlappingElement(element, context) {
context = context || document;
const dimensions = element.getBoundingClientRect();
const x = dimensions.left + (element.clientWidth / 2);
const y = dimensions.top + (element.clientHeight / 2);
return context.elementFromPoint(x, y);
}
// get overlapping element rects (currently only the first)
// applicable if element's text is multiline.
function getOverlappingRects(element, context) {
context = context || document;
const elements = [];
const rects = element.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);
elements.push(context.elementFromPoint(x, y));
return elements;
}
// get overlapping elements
function getOverlappingElements(element, context) {
return [getOverlappingElement(element, context)].concat(getOverlappingRects(element, context));
}
// is a node a descendant of a given node
function nodeContains(element, otherNode) {
// Edge doesn't support neither Shadow Dom nor contains if ShadowRoot polyfill is used
if (isOldEdge) {
let tempElement = otherNode;
while (tempElement) {
if (tempElement === element) {
return true;
}
tempElement = tempElement.parentNode;
// DocumentFragment / ShadowRoot polyfill like ShadyRoot
if (tempElement && tempElement.nodeType === 11 && tempElement.host) {
tempElement = tempElement.host;
}
}
return false;
}
return element.contains(otherNode);
}
// is one of overlapping elements the `elem` or one of its child
function isOverlappingElementMatch(elementsFromPoint, element) {
if (elementsFromPoint.some(function (elementFromPoint) {
return elementFromPoint === element || nodeContains(element, elementFromPoint);
})) {
return true;
}
// shadow root
// filter unique elements with shadowRoot
const elementsWithShadowRoot = [].concat(elementsFromPoint).filter(function (x) {
return x && x.shadowRoot && x.shadowRoot.elementFromPoint;
});
// getOverlappingElements of every element with shadowRoot
let shadowElementsFromPoint = [];
for (let i = 0; i < elementsWithShadowRoot.length; ++i) {
const shadowElement = elementsWithShadowRoot[i];
shadowElementsFromPoint = shadowElementsFromPoint.concat(getOverlappingElements(element, shadowElement.shadowRoot));
}
// remove duplicates and parents
shadowElementsFromPoint = [].concat(shadowElementsFromPoint).filter(function (x) {
return !elementsFromPoint.includes(x);
});
if (shadowElementsFromPoint.length === 0) {
return false;
}
return isOverlappingElementMatch(shadowElementsFromPoint, element);
}
return isOverlappingElementMatch(getOverlappingElements(domNode), domNode);
}
/* c8 ignore stop */
//# sourceMappingURL=isVisible.js.map