@applitools/spec-driver-selenium
Version:
423 lines (422 loc) • 18.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.build = exports.executeBrowserCommands = exports.switchWorld = exports.getWorlds = exports.getCurrentWorld = exports.takeScreenshot = exports.performAction = exports.visit = exports.getUrl = exports.getTitle = exports.getCookies = exports.getSystemBars = exports.setOrientation = exports.getOrientation = exports.setWindowSize = exports.getWindowSize = exports.getCapabilities = exports.getDriverInfo = exports.childContext = exports.parentContext = exports.mainContext = exports.click = exports.hover = exports.getElementText = exports.setElementText = exports.getElementAttribute = exports.getElementRegion = exports.waitForSelector = exports.findElements = exports.findElement = exports.executeScript = exports.toSimpleCommonSelector = exports.toSelector = exports.toDriver = exports.isStaleElementError = exports.isEqualElements = exports.isSelector = exports.isElement = exports.isDriver = void 0;
const command_1 = require("selenium-webdriver/lib/command");
const Selenium = __importStar(require("selenium-webdriver"));
const utils = __importStar(require("@applitools/utils"));
function extractElementId(element) {
return isElement(element) ? element.getId() : element['shadow-6066-11e4-a52e-4f735466cecf'];
}
function transformShadowRoot(driver, shadowRoot) {
return utils.types.has(shadowRoot, 'shadow-6066-11e4-a52e-4f735466cecf')
? new Selenium.WebElement(driver, shadowRoot['shadow-6066-11e4-a52e-4f735466cecf'])
: shadowRoot;
}
const byHash = ['className', 'css', 'id', 'js', 'linkText', 'name', 'partialLinkText', 'tagName', 'xpath'];
function isByHashSelector(selector) {
return byHash.includes(Object.keys(selector)[0]);
}
async function executeCustomCommand(driver, command) {
return process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3'
? driver.schedule(command)
: driver.execute(command);
}
function isDriver(driver) {
return utils.types.instanceOf(driver, 'WebDriver');
}
exports.isDriver = isDriver;
function isElement(element) {
return utils.types.instanceOf(element, 'WebElement');
}
exports.isElement = isElement;
function isSelector(selector) {
if (!selector)
return false;
return (utils.types.has(selector, ['using', 'value']) ||
isByHashSelector(selector) ||
utils.types.isFunction(selector) ||
utils.types.instanceOf(selector, 'RelativeBy'));
}
exports.isSelector = isSelector;
async function isEqualElements(_driver, element1, element2) {
if (!element1 || !element2)
return false;
const elementId1 = await extractElementId(element1);
const elementId2 = await extractElementId(element2);
return elementId1 === elementId2;
}
exports.isEqualElements = isEqualElements;
function isStaleElementError(error) {
if (!error)
return false;
error = error.originalError || error;
return error instanceof Error && error.name === 'StaleElementReferenceError';
}
exports.isStaleElementError = isStaleElementError;
function toDriver(driver) {
driver.getExecutor().defineCommand('getOrientation', 'GET', '/session/:sessionId/orientation');
driver.getExecutor().defineCommand('getSystemBars', 'GET', '/session/:sessionId/appium/device/system_bars');
driver.getExecutor().defineCommand('getWindowSize', 'GET', '/session/:sessionId/window/current/size');
driver.getExecutor().defineCommand('setWindowSize', 'POST', '/session/:sessionId/window/current/size');
driver.getExecutor().defineCommand('setWindowPosition', 'POST', '/session/:sessionId/window/current/position');
driver.getExecutor().defineCommand('performTouch', 'POST', '/session/:sessionId/touch/perform');
driver.getExecutor().defineCommand('executeCdp', 'POST', '/session/:sessionId/chromium/send_command_and_get_result');
driver.getExecutor().defineCommand('setOrientation', 'POST', '/session/:sessionId/orientation');
driver.getExecutor().defineCommand('getCurrentContext', 'GET', '/session/:sessionId/context');
driver.getExecutor().defineCommand('getContexts', 'GET', '/session/:sessionId/contexts');
driver.getExecutor().defineCommand('switchToContext', 'POST', '/session/:sessionId/context');
if (process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3') {
driver.getExecutor().defineCommand('switchToParentFrame', 'POST', '/session/:sessionId/frame/parent');
}
return driver;
}
exports.toDriver = toDriver;
function toSelector(selector) {
if (utils.types.isString(selector)) {
return { css: selector };
}
else if (utils.types.has(selector, 'selector')) {
if (!utils.types.isString(selector.selector))
return selector.selector;
if (!utils.types.has(selector, 'type') || !selector.type)
return { css: selector.selector };
if (selector.type === 'css')
return { css: selector.selector };
else
return { using: selector.type, value: selector.selector };
}
return selector;
}
exports.toSelector = toSelector;
function toSimpleCommonSelector(selector) {
if (utils.types.instanceOf(selector, 'RelativeBy') || utils.types.isFunction(selector)) {
return null;
}
else if (isByHashSelector(selector)) {
const [[how, what]] = Object.entries(selector);
if (how === 'js')
return null;
selector = Selenium.By[how](what);
}
if (utils.types.has(selector, ['using', 'value'])) {
return { type: selector.using === 'css selector' ? 'css' : selector.using, selector: selector.value };
}
return selector;
}
exports.toSimpleCommonSelector = toSimpleCommonSelector;
async function executeScript(driver, script, arg) {
return driver.executeScript(script, arg);
}
exports.executeScript = executeScript;
async function findElement(driver, selector, parent) {
try {
const root = parent ? transformShadowRoot(driver, parent) : driver;
return await root.findElement(selector);
}
catch (err) {
if (err.name === 'NoSuchElementError')
return null;
else
throw err;
}
}
exports.findElement = findElement;
async function findElements(driver, selector, parent) {
const root = parent ? transformShadowRoot(driver, parent) : driver;
return root.findElements(selector);
}
exports.findElements = findElements;
async function waitForSelector(driver, selector, _parent, options) {
if ((options === null || options === void 0 ? void 0 : options.state) === 'visible') {
const element = await driver.findElement(selector);
return driver.wait(Selenium.until.elementIsVisible(element), options === null || options === void 0 ? void 0 : options.timeout);
}
else {
return driver.wait(Selenium.until.elementLocated(selector), options === null || options === void 0 ? void 0 : options.timeout);
}
}
exports.waitForSelector = waitForSelector;
async function getElementRegion(_driver, element) {
if (utils.types.isFunction(element.getRect)) {
return element.getRect();
}
else {
const { x, y } = await element.getLocation();
const { width, height } = await element.getSize();
return { x, y, width, height };
}
}
exports.getElementRegion = getElementRegion;
async function getElementAttribute(_driver, element, attr) {
return element.getAttribute(attr);
}
exports.getElementAttribute = getElementAttribute;
async function setElementText(_driver, element, keys) {
await element.clear();
await element.sendKeys(keys);
}
exports.setElementText = setElementText;
async function getElementText(_driver, element) {
return element.getText();
}
exports.getElementText = getElementText;
async function hover(driver, element) {
if (process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3') {
let frameworkPath;
try {
frameworkPath = require.resolve('selenium-webdriver', { paths: [`${process.cwd()}/node_modules`] });
}
catch {
frameworkPath = 'selenium-webdriver';
}
const { ActionSequence } = require(frameworkPath);
const action = new ActionSequence(driver);
await action.mouseMove(element).perform();
}
else {
await driver.actions().move({ origin: element }).perform();
}
}
exports.hover = hover;
async function click(_driver, element) {
await element.click();
}
exports.click = click;
async function mainContext(driver) {
await driver.switchTo().defaultContent();
return driver;
}
exports.mainContext = mainContext;
async function parentContext(driver) {
if (process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3') {
await executeCustomCommand(driver, new command_1.Command('switchToParentFrame'));
return driver;
}
await driver.switchTo().parentFrame();
return driver;
}
exports.parentContext = parentContext;
async function childContext(driver, element) {
await driver.switchTo().frame(element);
return driver;
}
exports.childContext = childContext;
async function getDriverInfo(driver) {
const session = await driver.getSession();
return { sessionId: session.getId() };
}
exports.getDriverInfo = getDriverInfo;
async function getCapabilities(driver) {
return await driver
.getCapabilities()
.then(capabilities => Array.from(capabilities.keys()).reduce((obj, key) => Object.assign(obj, { [key]: capabilities.get(key) }), {}));
}
exports.getCapabilities = getCapabilities;
async function getWindowSize(driver) {
try {
const rect = await driver.manage().window().getRect();
return { width: rect.width, height: rect.height };
}
catch {
const size = driver.manage().window().getSize
? await driver.manage().window().getSize()
: await executeCustomCommand(driver, new command_1.Command('getWindowSize'));
return { width: size.width, height: size.height };
}
}
exports.getWindowSize = getWindowSize;
async function setWindowSize(driver, size) {
try {
await driver.manage().window().setRect({ x: 0, y: 0, width: size.width, height: size.height });
}
catch {
if (driver.manage().window().setPosition)
await driver.manage().window().setPosition(0, 0);
else
await executeCustomCommand(driver, new command_1.Command('setWindowPosition').setParameters({ x: 0, y: 0 }));
if (driver.manage().window().setSize)
await driver.manage().window().setSize(size.width, size.height);
else
await executeCustomCommand(driver, new command_1.Command('setWindowSize').setParameters({ ...size }));
}
}
exports.setWindowSize = setWindowSize;
async function getOrientation(driver) {
const orientation = await executeCustomCommand(driver, new command_1.Command('getOrientation'));
return orientation.toLowerCase();
}
exports.getOrientation = getOrientation;
async function setOrientation(driver, orientation) {
await executeCustomCommand(driver, new command_1.Command('setOrientation').setParameters({ orientation }));
}
exports.setOrientation = setOrientation;
async function getSystemBars(driver) {
return executeCustomCommand(driver, new command_1.Command('getSystemBars'));
}
exports.getSystemBars = getSystemBars;
async function getCookies(driver, context) {
if (context)
return driver.manage().getCookies();
let cookies;
if (utils.types.isFunction(driver, 'sendAndGetDevToolsCommand')) {
const response = await driver.sendAndGetDevToolsCommand('Network.getAllCookies');
cookies = response.cookies;
}
else {
const response = await executeCustomCommand(driver, new command_1.Command('executeCdp').setParameter('cmd', 'Network.getAllCookies').setParameter('params', {}));
cookies = response.cookies;
}
return cookies.map((cookie) => {
const copy = { ...cookie, expiry: cookie.expires };
delete copy.expires;
delete copy.size;
delete copy.priority;
delete copy.session;
delete copy.sameParty;
delete copy.sourceScheme;
delete copy.sourcePort;
return copy;
});
}
exports.getCookies = getCookies;
async function getTitle(driver) {
return driver.getTitle();
}
exports.getTitle = getTitle;
async function getUrl(driver) {
return driver.getCurrentUrl();
}
exports.getUrl = getUrl;
async function visit(driver, url) {
await driver.get(url);
}
exports.visit = visit;
async function performAction(driver, steps) {
await executeCustomCommand(driver, new command_1.Command('performTouch').setParameters({
actions: steps.map(({ action, ...options }) => ({ action, options })),
}));
}
exports.performAction = performAction;
async function takeScreenshot(driver) {
return driver.takeScreenshot();
}
exports.takeScreenshot = takeScreenshot;
async function getCurrentWorld(driver) {
return executeCustomCommand(driver, new command_1.Command('getCurrentContext'));
}
exports.getCurrentWorld = getCurrentWorld;
async function getWorlds(driver) {
return executeCustomCommand(driver, new command_1.Command('getContexts'));
}
exports.getWorlds = getWorlds;
async function switchWorld(driver, name) {
return executeCustomCommand(driver, new command_1.Command('switchToContext').setParameters({ name }));
}
exports.switchWorld = switchWorld;
async function executeBrowserCommands(driver, commands, logger) {
var _a;
let lastResponse;
driver.sendDevToolsCommand;
if (utils.types.isFunction(driver, 'sendAndGetDevToolsCommand')) {
for (const currentCommand of commands) {
lastResponse = await driver.sendAndGetDevToolsCommand(currentCommand.command.toString(), (_a = currentCommand.params) !== null && _a !== void 0 ? _a : {});
logger === null || logger === void 0 ? void 0 : logger.debug(`executeBrowserCommands ${currentCommand.command}, params: ${currentCommand.params}, response: ${JSON.stringify(lastResponse)}`);
}
}
else {
for (const currentCommand of commands) {
lastResponse = await executeCustomCommand(driver, new command_1.Command('executeCdp')
.setParameter('cmd', currentCommand.command)
.setParameter('params', currentCommand.params));
logger === null || logger === void 0 ? void 0 : logger.debug(`executeBrowserCommands ${currentCommand.command}, params: ${currentCommand.params}, response: ${JSON.stringify(lastResponse)}`);
}
}
return lastResponse;
}
exports.executeBrowserCommands = executeBrowserCommands;
const browserOptionsNames = {
chrome: 'goog:chromeOptions',
firefox: 'moz:firefoxOptions',
};
/*
* Spawn a browser with a given configuration (INTERNAL USE ONLY)
*
* NOTE:
* This function is intended for internal use only. As a result it relies on some dev dependencies.
* When wiring the spec-driver up to an SDK and calling this function, if you don't have the same dev deps
* installed in the SDK, then this function will error.
*/
async function build(env) {
var _a;
let frameworkPath;
try {
frameworkPath = require.resolve('selenium-webdriver', { paths: [`${process.cwd()}/node_modules`] });
}
catch {
frameworkPath = 'selenium-webdriver';
}
const { Builder } = require(frameworkPath);
const parseEnv = require('@applitools/test-utils/src/parse-env');
const { browser, capabilities, url, attach, proxy, configurable = true, appium = false, args = [], headless, } = parseEnv({ ...env, legacy: (_a = env.legacy) !== null && _a !== void 0 ? _a : process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3' });
const desiredCapabilities = { ...capabilities };
if (configurable) {
const browserOptionsName = browserOptionsNames[browser || desiredCapabilities.browserName];
if (browserOptionsName) {
const browserOptions = desiredCapabilities[browserOptionsName] || {};
browserOptions.args = [...(browserOptions.args || []), ...args];
if (headless)
browserOptions.args.push('headless');
if (attach) {
browserOptions.debuggerAddress = attach === true ? 'localhost:9222' : attach;
}
desiredCapabilities[browserOptionsName] = browserOptions;
}
}
if (browser === 'chrome') {
if (appium) {
desiredCapabilities['appium:chromeOptions'] = { w3c: false, ...desiredCapabilities['appium:chromeOptions'] };
}
else if (process.env.APPLITOOLS_FRAMEWORK_MAJOR_VERSION === '3') {
desiredCapabilities['goog:chromeOptions'] = { w3c: false, ...desiredCapabilities['goog:chromeOptions'] };
}
}
const builder = new Builder().withCapabilities(desiredCapabilities);
if (url && !attach)
builder.usingServer(url.href);
if (proxy) {
builder.setProxy({
proxyType: 'manual',
httpProxy: proxy.http || proxy.server,
sslProxy: proxy.https || proxy.server,
ftpProxy: proxy.ftp,
noProxy: proxy.bypass,
});
}
const driver = await builder.build();
driver.__serverUrl = url;
return [driver, () => driver.quit()];
}
exports.build = build;