eyes.selenium.v68patch
Version:
Applitools Eyes SDK For Selenium JavaScript WebDriver
325 lines (294 loc) • 13.4 kB
JavaScript
(function () {
'use strict';
var EyesUtils = require('eyes.utils'),
FrameChain = require('./FrameChain'),
ScrollPositionProvider = require('./ScrollPositionProvider'),
EyesRemoteWebElement = require('./EyesRemoteWebElement');
var ArgumentGuard = EyesUtils.ArgumentGuard,
GeneralUtils = EyesUtils.GeneralUtils;
/**
* @enum {number}
* @readonly
*/
EyesTargetLocator.TargetType = {
FRAME: 1,
PARENT_FRAME: 2,
DEFAULT_CONTENT: 3
};
//noinspection JSUnusedLocalSymbols
/**
* A wrapper for an action to be performed before the actual switch is made.
*/
function OnWillSwitch() {
/**
* Will be called before switching into a frame.
* @param {TargetType} targetType The type of frame we're about to switch into.
* @param {WebElement} targetFrame The element about to be switched to,
* if available. Otherwise, null.
*/
this.prototype.willSwitchToFrame = function (targetType, targetFrame) {
};
/**
* Will be called before switching into a window.
* @param {string} nameOrHandle The name/handle of the window to be switched to.
*/
this.prototype.willSwitchToWindow = function (nameOrHandle) {
};
}
/**
* @constructor
* Initialized a new EyesTargetLocator object.
* @param {Object} logger A Logger instance.
* @param {EyesWebDriver} driver The WebDriver from which the targetLocator was received.
* @param {TargetLocator} targetLocator The actual TargetLocator object.
* @param {OnWillSwitch} onWillSwitch A delegate to be called whenever a relevant switch
* @param {PromiseFactory} promiseFactory
* is about to be performed.
*/
function EyesTargetLocator(logger, driver, targetLocator, onWillSwitch, promiseFactory) {
ArgumentGuard.notNull(logger, "logger");
ArgumentGuard.notNull(driver, "driver");
ArgumentGuard.notNull(targetLocator, "targetLocator");
ArgumentGuard.notNull(onWillSwitch, "onWillSwitch");
this._logger = logger;
this._driver = driver;
this._targetLocator = targetLocator;
this._onWillSwitch = onWillSwitch;
this._promiseFactory = promiseFactory;
this._scrollPosition = new ScrollPositionProvider(this._logger, this._driver, this._promiseFactory);
GeneralUtils.mixin(this, targetLocator);
}
/**
* @param {int|string|EyesRemoteWebElement} obj
* @returns {Promise<void>}
*/
EyesTargetLocator.prototype.frame = function (obj) {
var that = this, frames;
if (typeof obj === 'string' || obj instanceof String) {
this._logger.verbose("EyesTargetLocator.frame('", obj, "')");
// Finding the target element so we can report it.
// We use find elements(plural) to avoid exception when the element
// is not found.
this._logger.verbose("Getting frames by name...");
return this._driver.findElementsByName(obj).then(function(elements) {
if (elements.length === 0) {
that._logger.verbose("No frames Found! Trying by id...");
// If there are no frames by that name, we'll try the id
return that._driver.findElementsById(obj);
}
return elements;
}).then(function(elements) {
if (elements.length === 0) {
// No such frame, bummer
throw new Error("No frame with name or id '" + obj + "' exists!");
}
return elements;
}).then(function (frames) {
if (frames.length === 0) {
that._logger.verbose("No frames Found! Trying by id...");
// If there are no frames by that name, we'll try the id
frames = that._driver.findElementsById(obj);
if (frames.length === 0) {
// No such frame, bummer
throw new Error("No frame with name or id '" + obj + "' exists!");
}
}
that._logger.verbose("Done! Making preparations..");
return that._onWillSwitch.willSwitchToFrame(EyesTargetLocator.TargetType.FRAME, frames[0]);
}).then(function () {
that._logger.verbose("Done! Switching to frame...");
return that._targetLocator.frame(obj)
}).then(function () {
that._logger.verbose("Done!");
});
} else if (obj instanceof EyesRemoteWebElement) {
that._logger.verbose("EyesTargetLocator.frame(element)");
that._logger.verbose("Making preparations..");
return that._onWillSwitch.willSwitchToFrame(EyesTargetLocator.TargetType.FRAME, obj).then(function () {
that._logger.verbose("Done! Switching to frame...");
return that._targetLocator.frame(obj.getRemoteWebElement())
}).then(function () {
that._logger.verbose("Done!");
});
} else {
that._logger.verbose("EyesTargetLocator.frame(", typeof obj, ")");
// Finding the target element so and reporting it using onWillSwitch.
that._logger.verbose("Getting frames list...");
return that._driver.findElementsByCssSelector("frame, iframe").then(function (elements) {
if (obj > elements.length) {
throw new Error("Frame index [" + obj + "] is invalid!");
}
return elements;
}).then(function (frames) {
that._logger.verbose("Done! getting the specific frame...");
var targetFrame = frames[obj];
that._logger.verbose("Done! Making preparations...");
return that._onWillSwitch.willSwitchToFrame(EyesTargetLocator.TargetType.FRAME, targetFrame);
}).then(function () {
that._logger.verbose("Done! Switching to frame...");
return that._targetLocator.frame(obj)
}).then(function () {
that._logger.verbose("Done!");
});
}
};
/**
* @returns {Promise.<void>}
*/
EyesTargetLocator.prototype.parentFrame = function () {
var that = this;
this._logger.verbose("EyesTargetLocator.parentFrame()");
return this._driver._promiseFactory.makePromise(function (resolve) {
if (that._driver.getFrameChain().size() != 0) {
that._logger.verbose("Making preparations..");
return that._onWillSwitch.willSwitchToFrame(EyesTargetLocator.TargetType.PARENT_FRAME, null).then(function () {
return that._targetLocator.defaultContent();
}).then(function () {
that._logger.verbose("Done! Switching to parent frame..");
return that.frames(that._driver.getFrameChain());
}).then(function () {
that._logger.verbose("Done!");
resolve();
});
}
resolve();
});
};
/**
* Switches into every frame in the frame chain. This is used as way to
* switch into nested frames (while considering scroll) in a single call.
* @param {FrameChain|string[]} obj The path to the frame to switch to.
* Or the path to the frame to check. This is a list of frame names/IDs
* (where each frame is nested in the previous frame).
* @return {Promise<void>} The WebDriver with the switched context.
*/
EyesTargetLocator.prototype.frames = function (obj) {
var that = this;
return this._driver._promiseFactory.makePromise(function (resolve) {
if (obj instanceof FrameChain) {
that._logger.verbose("EyesTargetLocator.frames(frameChain)");
if (obj.size() > 0) {
return _framesSetPosition(that, obj, obj.size() - 1, that._driver._promiseFactory).then(function () {
that._logger.verbose("Done switching into nested frames!");
resolve();
});
}
resolve();
} else if (Array.isArray(obj)) {
if (obj.length > 0) {
return _framesSetPositionFromArray(that, obj, obj.length - 1, that._driver._promiseFactory).then(function () {
that._logger.verbose("Done switching into nested frames!");
resolve();
});
}
resolve();
}
});
};
function _framesSetPosition(targetLocator, obj, retries, promiseFactory) {
return promiseFactory.makePromise(function (resolve) {
// TODO: check order, if it make sense
var frame = obj.getFrames()[retries];
targetLocator._scrollPosition.setPosition(frame.getParentScrollPosition()).then(function () {
targetLocator._logger.verbose("Done! Switching to frame...");
return targetLocator._driver.switchTo().frame(frame.getReference());
}).then(function () {
targetLocator._logger.verbose("Done!");
if (retries === 0) {
resolve();
return;
}
targetLocator.controlFlow().then(function () {
_framesSetPosition(targetLocator, obj, retries - 1, promiseFactory).then(function () {
resolve();
});
});
});
});
}
function _framesSetPositionFromArray(targetLocator, obj, retries, promiseFactory) {
return promiseFactory.makePromise(function (resolve) {
targetLocator._logger.verbose("Switching to frame...");
targetLocator._driver.switchTo().frame(obj[retries]).then(function () {
targetLocator._logger.verbose("Done!");
if (retries === 0) {
resolve();
return;
}
targetLocator.controlFlow().then(function () {
_framesSetPositionFromArray(targetLocator, obj, retries - 1, promiseFactory).then(function () {
resolve();
});
});
});
});
}
/**
* @param {string} nameOrHandle
* @returns {Promise.<void>}
*/
EyesTargetLocator.prototype.window = function (nameOrHandle) {
var that = this;
this._logger.verbose("EyesTargetLocator.window()");
return this._driver._promiseFactory.makePromise(function (resolve) {
that._logger.verbose("Making preparations..");
that._onWillSwitch.willSwitchToWindow(nameOrHandle).then(function () {
that._logger.verbose("Done! Switching to window..");
return that._targetLocator.window(nameOrHandle);
}).then(function () {
that._logger.verbose("Done!");
resolve();
});
});
};
/**
* @returns {Promise.<void>}
*/
EyesTargetLocator.prototype.defaultContent = function () {
var that = this;
return this._driver._promiseFactory.makePromise(function (resolve) {
that._logger.verbose("EyesTargetLocator.defaultContent()");
if (that._driver.getFrameChain().size() != 0) {
that._logger.verbose("Making preparations..");
that._onWillSwitch.willSwitchToFrame(EyesTargetLocator.TargetType.DEFAULT_CONTENT, null).then(function () {
that._logger.verbose("Done! Switching to default content..");
return that._targetLocator.defaultContent();
}).then(function () {
that._logger.verbose("Done!");
resolve();
});
}
resolve();
});
};
/**
* @returns {Promise.<EyesRemoteWebElement>}
*/
EyesTargetLocator.prototype.activeElement = function () {
var that = this;
this._logger.verbose("EyesTargetLocator.activeElement()");
return this._driver._promiseFactory.makePromise(function (resolve) {
that._logger.verbose("Switching to element..");
that._targetLocator.activeElement().then(function (element) {
var result = new EyesRemoteWebElement(element, that._driver, that._logger);
that._logger.verbose("Done!");
resolve(result);
})
});
};
/**
* @returns {Promise.<Alert>}
*/
EyesTargetLocator.prototype.alert = function () {
var that = this;
this._logger.verbose("EyesTargetLocator.alert()");
return this._driver._promiseFactory.makePromise(function (resolve) {
that._logger.verbose("Switching to alert..");
that._targetLocator.alert().then(function (alert) {
that._logger.verbose("Done!");
resolve(alert);
});
});
};
module.exports = EyesTargetLocator;
}());