cypress-real-events
Version:
Real native events for cypress. Dispatched via CDP.
127 lines (126 loc) • 5.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCypressElementCoordinates = getCypressElementCoordinates;
function getPositionedCoordinates(x0, y0, width, height, position, frameScale) {
if (typeof position === "object" && position !== null) {
const { x, y } = position;
// scale the position coordinates according to the viewport scale
return [x0 + x * frameScale, y0 + y * frameScale];
}
switch (position) {
case "topLeft":
return [x0, y0];
case "top":
return [x0 + width / 2, y0];
case "topRight":
return [x0 + width - 1, y0];
case "left":
return [x0, y0 + height / 2];
case "right":
return [x0 + width - 1, y0 + height / 2];
case "bottomLeft":
return [x0, y0 + height - 1];
case "bottom":
return [x0 + width / 2, y0 + height - 1];
case "bottomRight":
return [x0 + width - 1, y0 + height - 1];
// center by default
default:
return [x0 + width / 2, y0 + height / 2];
}
}
/**
* Scrolls the given htmlElement into view on the page.
* The position the element is scrolled to can be customized with scrollBehavior.
*/
function scrollIntoView(htmlElement, scrollBehavior = "center") {
let block;
if (scrollBehavior === "top") {
block = "start";
}
else if (scrollBehavior === "bottom") {
block = "end";
}
else {
block = scrollBehavior;
}
htmlElement.scrollIntoView({ block });
}
// for cross origin domains .frameElement returns null so query using parentWindow
// but when running using --disable-web-security it will return the frame element
function getFrameElement(currentWindow) {
if (currentWindow.frameElement) {
// accessible for same-origin iframes
// or when running with --disable-web-security
return currentWindow.frameElement;
}
// fallback to querying using the parent window, mainly to grab the AUT iframe
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return [...currentWindow.parent.document.querySelectorAll("iframe")].find((iframe) => iframe.contentWindow === currentWindow);
}
function getIframesPositionShift(element) {
let currentWindow = element.ownerDocument.defaultView;
const noPositionShift = {
frameScale: 1,
frameX: 0,
frameY: 0,
};
if (!currentWindow) {
return noPositionShift;
}
// eslint-disable-next-line prefer-const
const iframes = [];
while (currentWindow !== window.top) {
iframes.push(getFrameElement(currentWindow));
currentWindow = currentWindow.parent;
}
return iframes.reduceRight(({ frameX, frameY, frameScale }, frame) => {
const { x, y, width } = frame.getBoundingClientRect();
return {
frameX: frameX + x * frameScale,
frameY: frameY + y * frameScale,
frameScale: frameScale * (width / frame.offsetWidth),
};
}, noPositionShift);
}
/**
* Returns the coordinates and size of a given Element, relative to the Cypress app <iframe>.
* Accounts for any scaling on the iframes.
*/
function getElementPositionXY(htmlElement) {
const { x: elementX, y: elementY, width, height, } = htmlElement.getBoundingClientRect();
const { frameScale, frameX, frameY } = getIframesPositionShift(htmlElement);
return {
x: frameX + elementX * frameScale,
y: frameY + elementY * frameScale,
width: width * frameScale,
height: height * frameScale,
frameScale: frameScale,
};
}
/**
* Cypress Automation debugee is the whole tab.
* This function returns the element coordinates relative to the whole tab root that can be used in CDP request.
* @param jqueryEl the element to introspect
* @param position the position of the event interaction on the element
* @param scrollBehavior custom scroll behavior options
*/
function getCypressElementCoordinates(jqueryEl, position, scrollBehavior) {
var _a;
const htmlElement = jqueryEl.get(0);
const cypressAppFrame = window.parent.document.querySelector("iframe");
if (!cypressAppFrame) {
throw new Error("Can not find cypress application iframe, it looks like critical issue. Please rise an issue on GitHub.");
}
const effectiveScrollBehavior = ((_a = scrollBehavior !== null && scrollBehavior !== void 0 ? scrollBehavior : Cypress.config("scrollBehavior")) !== null && _a !== void 0 ? _a : "center");
if (effectiveScrollBehavior && typeof effectiveScrollBehavior !== "object") {
scrollIntoView(htmlElement, effectiveScrollBehavior);
}
const { x, y, width, height, frameScale } = getElementPositionXY(htmlElement);
const [posX, posY] = getPositionedCoordinates(x, y, width, height, position !== null && position !== void 0 ? position : "center", frameScale);
return {
x: posX,
y: posY,
frameScale: frameScale,
};
}