UNPKG

eyes.selenium.v68patch

Version:

Applitools Eyes SDK For Selenium JavaScript WebDriver

309 lines (263 loc) 10.8 kB
/* --- name: EyesRemoteWebElement description: Wraps a Remote Web Element. --- */ (function () { "use strict"; var EyesSDK = require('eyes.sdk'), EyesUtils = require('eyes.utils'); var MouseAction = EyesSDK.Triggers.MouseAction, GeneralUtils = EyesUtils.GeneralUtils, GeometryUtils = EyesUtils.GeometryUtils; var JS_GET_SCROLL_LEFT = "return arguments[0].scrollLeft;"; var JS_GET_SCROLL_TOP = "return arguments[0].scrollTop;"; var JS_GET_SCROLL_WIDTH = "return arguments[0].scrollWidth;"; var JS_GET_SCROLL_HEIGHT = "return arguments[0].scrollHeight;"; var JS_GET_OVERFLOW = "return arguments[0].style.overflow;"; var JS_GET_LOCATION = "var rect = arguments[0].getBoundingClientRect(); return [rect.left, rect.top]"; /** * @param {string} styleProp * @return {string} */ var JS_GET_COMPUTED_STYLE_FORMATTED_STR = function (styleProp) { return "var elem = arguments[0], styleProp = '"+ styleProp +"'; " + "if (window.getComputedStyle) { " + " return window.getComputedStyle(elem, null).getPropertyValue(styleProp);" + "} else if (elem.currentStyle) { " + " return elem.currentStyle[styleProp];" + "} else { " + " return null;" + "}"; }; /** * @param {int} scrollLeft * @param {int} scrollTop * @return {string} */ var JS_SCROLL_TO_FORMATTED_STR = function (scrollLeft, scrollTop) { return "arguments[0].scrollLeft = " + scrollLeft + "; " + "arguments[0].scrollTop = " + scrollTop + ";"; }; /** * @param {string} overflow * @return {string} */ var JS_SET_OVERFLOW_FORMATTED_STR = function (overflow) { return "arguments[0].style.overflow = '" + overflow + "'"; }; /** * * C'tor = initializes the module settings * * @constructor * @param {WebElement} remoteWebElement * @param {EyesWebDriver} eyesDriver * @param {Logger} logger * @augments WebElement **/ function EyesRemoteWebElement(remoteWebElement, eyesDriver, logger) { this._element = remoteWebElement; this._logger = logger; this._eyesDriver = eyesDriver; GeneralUtils.mixin(this, remoteWebElement); } function _getRectangle(location, size) { size = size || {height: 0, width: 0}; location = location || {x: 0, y: 0}; var left = location.x, top = location.y, width = size.width, height = size.height; if (left < 0) { width = Math.max(0, width + left); left = 0; } if (top < 0) { height = Math.max(0, height + top); top = 0; } return { top: top, left: left, width: width, height: height }; } function _getBounds (element) { return element.getLocation().then(function (location) { return element.getSize().then(function (size) { return _getRectangle(location, size); }, function () { return _getRectangle(location); }); }, function () { return _getRectangle(); }); } EyesRemoteWebElement.registerSendKeys = function (element, eyesDriver, logger, args) { var text = args.join(''); logger.verbose("registerSendKeys: text is", text); return _getBounds(element).then(function (rect) { eyesDriver.getEyes().addKeyboardTrigger(rect, text); }); }; EyesRemoteWebElement.prototype.sendKeys = function () { var that = this, args = Array.prototype.slice.call(arguments, 0); return EyesRemoteWebElement.registerSendKeys(that._element, that._eyesDriver, that._logger, args).then(function () { return that._element.sendKeys.call(that._element, args); }); }; EyesRemoteWebElement.registerClick = function (element, eyesDriver, logger) { logger.verbose("apply click on element"); return _getBounds(element).then(function (rect) { var offset = {x: rect.width / 2, y: rect.height / 2}; eyesDriver.getEyes().addMouseTrigger(MouseAction.Click, rect, offset); }); }; EyesRemoteWebElement.prototype.click = function () { var that = this; that._logger.verbose("click on element"); return EyesRemoteWebElement.registerClick(that._element, that._eyesDriver, that._logger).then(function () { return that._element.click(); }); }; EyesRemoteWebElement.prototype.findElement = function (locator) { var that = this; return this._element.findElement(locator).then(function (element) { return new EyesRemoteWebElement(element, that._eyesDriver, that._logger); }); }; EyesRemoteWebElement.prototype.findElements = function (locator) { var that = this; return this._element.findElements(locator).then(function (elements) { return elements.map(function (element) { return new EyesRemoteWebElement(element, that._eyesDriver, that._logger); }); }); }; /** * Returns the computed value of the style property for the current element. * @param {string} propStyle The style property which value we would like to extract. * @return {promise.Promise.<string>} The value of the style property of the element, or {@code null}. */ EyesRemoteWebElement.prototype.getComputedStyle = function (propStyle) { return this._eyesDriver.executeScript(JS_GET_COMPUTED_STYLE_FORMATTED_STR(propStyle), this._element); }; /** * @return {promise.Promise.<int>} The integer value of a computed style. */ EyesRemoteWebElement.prototype.getComputedStyleInteger = function (propStyle) { return this.getComputedStyle(propStyle).then(function (value) { return Math.round(parseFloat(value.trim().replace("px", ""))); }); }; /** * @return {promise.Promise.<int>} The value of the scrollLeft property of the element. */ EyesRemoteWebElement.prototype.getScrollLeft = function () { return this._eyesDriver.executeScript(JS_GET_SCROLL_LEFT, this._element).then(function (value) { return parseInt(value, 10); }); }; /** * @return {promise.Promise.<int>} The value of the scrollTop property of the element. */ EyesRemoteWebElement.prototype.getScrollTop = function () { return this._eyesDriver.executeScript(JS_GET_SCROLL_TOP, this._element).then(function (value) { return parseInt(value, 10); }); }; /** * @return {promise.Promise.<int>} The value of the scrollWidth property of the element. */ EyesRemoteWebElement.prototype.getScrollWidth = function () { return this._eyesDriver.executeScript(JS_GET_SCROLL_WIDTH, this._element).then(function (value) { return parseInt(value, 10); }); }; /** * @return {promise.Promise.<int>} The value of the scrollHeight property of the element. */ EyesRemoteWebElement.prototype.getScrollHeight = function () { return this._eyesDriver.executeScript(JS_GET_SCROLL_HEIGHT, this._element).then(function (value) { return parseInt(value, 10); }); }; /** * @return {promise.Promise.<int>} The width of the left border. */ EyesRemoteWebElement.prototype.getBorderLeftWidth = function () { return this.getComputedStyleInteger("border-left-width"); }; /** * @return {promise.Promise.<int>} The width of the right border. */ EyesRemoteWebElement.prototype.getBorderRightWidth = function () { return this.getComputedStyleInteger("border-right-width"); }; /** * @return {promise.Promise.<int>} The width of the top border. */ EyesRemoteWebElement.prototype.getBorderTopWidth = function () { return this.getComputedStyleInteger("border-top-width"); }; /** * @return {promise.Promise.<int>} The width of the bottom border. */ EyesRemoteWebElement.prototype.getBorderBottomWidth = function () { return this.getComputedStyleInteger("border-bottom-width"); }; /** * @return {!promise.Thenable<{width: number, height: number}>} element's size */ EyesRemoteWebElement.prototype.getSize = function () { return this._element.getSize().then(function (value) { return GeometryUtils.createSize(value.width, value.height); }); }; /** * @return {!promise.Thenable<{x: number, y: number}>} element's location */ EyesRemoteWebElement.prototype.getLocation = function () { // The workaround is similar to Java one, // https://github.com/applitools/eyes.sdk.java3/blob/master/eyes.selenium.java/src/main/java/com/applitools/eyes/selenium/EyesRemoteWebElement.java#L453 // but we can't get raw data (including decimal values) from remote Selenium webdriver // and therefore we should use our own client-side script for retrieving exact values and rounding up them // this._element.getLocation() return this._eyesDriver.executeScript(JS_GET_LOCATION, this._element).then(function (value) { var x = Math.ceil(value[0]) || 0; var y = Math.ceil(value[1]) || 0; return GeometryUtils.createLocation(x, y); }); }; /** * Scrolls to the specified location inside the element. * @param {{x: number, y: number}} location The location to scroll to. * @return {promise.Promise.<void>} */ EyesRemoteWebElement.prototype.scrollTo = function (location) { return this._eyesDriver.executeScript(JS_SCROLL_TO_FORMATTED_STR(location.x, location.y), this._element); }; /** * @return {promise.Promise.<string>} The overflow of the element. */ EyesRemoteWebElement.prototype.getOverflow = function () { return this._eyesDriver.executeScript(JS_GET_OVERFLOW, this._element); }; /** * @param {string} overflow The overflow to set * @return {promise.Promise.<void>} The overflow of the element. */ EyesRemoteWebElement.prototype.setOverflow = function (overflow) { return this._eyesDriver.executeScript(JS_SET_OVERFLOW_FORMATTED_STR(overflow), this._element); }; /** * @return {WebElement} The original element object */ EyesRemoteWebElement.prototype.getRemoteWebElement = function () { return this._element; }; module.exports = EyesRemoteWebElement; }());