webdriverio-automation
Version:
WebdriverIO-Automation android ios project
260 lines (203 loc) • 8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getPrototype = getPrototype;
exports.findElement = findElement;
exports.findElements = findElements;
exports.sanitizeError = sanitizeError;
exports.transformExecuteArgs = transformExecuteArgs;
exports.transformExecuteResult = transformExecuteResult;
exports.getStaleElementError = getStaleElementError;
exports.getPages = getPages;
exports.sort = sort;
exports.uniq = uniq;
exports.findByWhich = findByWhich;
exports.patchDebug = patchDebug;
exports.validate = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _child_process = require("child_process");
var _logger = _interopRequireDefault(require("@wdio/logger"));
var _utils = require("@wdio/utils");
var _protocols = require("@wdio/protocols");
var _cleanUpSerializationSelector = _interopRequireDefault(require("./scripts/cleanUpSerializationSelector"));
var _constants = require("./constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const log = (0, _logger.default)('devtools');
const validate = function (command, parameters, variables, ref, args) {
const commandParams = [...variables.map(v => Object.assign(v, {
required: true,
type: 'string'
})), ...parameters];
const commandUsage = `${command}(${commandParams.map(p => p.name).join(', ')})`;
const moreInfo = `\n\nFor more info see ${ref}\n`;
const body = {};
const minAllowedParams = commandParams.filter(param => param.required).length;
if (args.length < minAllowedParams || args.length > commandParams.length) {
const parameterDescription = commandParams.length ? `\n\nProperty Description:\n${commandParams.map(p => ` "${p.name}" (${p.type}): ${p.description}`).join('\n')}` : '';
throw new Error(`Wrong parameters applied for ${command}\n` + `Usage: ${commandUsage}` + parameterDescription + moreInfo);
}
for (const [i, arg] of Object.entries(args)) {
const commandParam = commandParams[i];
if (!(0, _utils.isValidParameter)(arg, commandParam.type)) {
if (typeof arg === 'undefined' && !commandParam.required) {
continue;
}
throw new Error(`Malformed type for "${commandParam.name}" parameter of command ${command}\n` + `Expected: ${commandParam.type}\n` + `Actual: ${(0, _utils.getArgumentType)(arg)}` + moreInfo);
}
body[commandParams[i].name] = arg;
}
log.info('COMMAND', (0, _utils.commandCallStructure)(command, args));
return body;
};
exports.validate = validate;
function getPrototype(commandWrapper) {
const prototype = {};
for (const [endpoint, methods] of Object.entries(_protocols.WebDriverProtocol)) {
for (const [method, commandData] of Object.entries(methods)) {
prototype[commandData.command] = {
value: commandWrapper(method, endpoint, commandData)
};
}
}
return prototype;
}
async function findElement(context, using, value) {
const implicitTimeout = this.timeouts.get('implicit');
const waitForFn = using === 'xpath' ? context.waitForXPath : context.waitForSelector;
if (implicitTimeout && waitForFn) {
await waitForFn.call(context, value, {
timeout: implicitTimeout
});
}
let element;
try {
element = using === 'xpath' ? (await context.$x(value))[0] : await context.$(value);
} catch (err) {
if (!err.message.includes('failed to find element')) {
throw err;
}
}
if (!element) {
return new Error(`Element with selector "${value}" not found`);
}
const elementId = this.elementStore.set(element);
return {
[_constants.ELEMENT_KEY]: elementId
};
}
async function findElements(context, using, value) {
const implicitTimeout = this.timeouts.get('implicit');
const waitForFn = using === 'xpath' ? context.waitForXPath : context.waitForSelector;
if (implicitTimeout && waitForFn) {
await waitForFn.call(context, value, {
timeout: implicitTimeout
});
}
const elements = using === 'xpath' ? await context.$x(value) : await context.$$(value);
if (elements.length === 0) {
return elements;
}
return elements.map(element => ({
[_constants.ELEMENT_KEY]: this.elementStore.set(element)
}));
}
function sanitizeError(err) {
let errorMessage = err.message;
if (err.message.includes('Node is detached from document')) {
err.name = _constants.ERROR_MESSAGES.staleElement.name;
errorMessage = _constants.ERROR_MESSAGES.staleElement.message;
}
const stack = err.stack.split('\n');
const asyncStack = stack.lastIndexOf(' -- ASYNC --');
err.stack = errorMessage + '\n' + stack.slice(asyncStack + 1).filter(line => !line.includes('devtools/node_modules/puppeteer-core')).join('\n');
return err;
}
function transformExecuteArgs(args = []) {
return args.map(arg => {
if (arg[_constants.ELEMENT_KEY]) {
const elementHandle = this.elementStore.get(arg[_constants.ELEMENT_KEY]);
if (!elementHandle) {
throw getStaleElementError(arg[_constants.ELEMENT_KEY]);
}
arg = elementHandle;
}
return arg;
});
}
async function transformExecuteResult(page, result) {
const isResultArray = Array.isArray(result);
let tmpResult = isResultArray ? result : [result];
if (tmpResult.find(r => typeof r === 'string' && r.startsWith(_constants.SERIALIZE_FLAG))) {
tmpResult = await Promise.all(tmpResult.map(async r => {
if (typeof r === 'string' && r.startsWith(_constants.SERIALIZE_FLAG)) {
return findElement.call(this, page, 'css selector', `[${_constants.SERIALIZE_PROPERTY}="${r}"]`);
}
return result;
}));
await page.$$eval(`[${_constants.SERIALIZE_PROPERTY}]`, _cleanUpSerializationSelector.default, _constants.SERIALIZE_PROPERTY);
}
return isResultArray ? tmpResult : tmpResult[0];
}
function getStaleElementError(elementId) {
const error = new Error(`stale element reference: The element with reference ${elementId} is stale; either the ` + 'element is no longer attached to the DOM, it is not in the current frame context, or the ' + 'document has been refreshed');
error.name = 'stale element reference';
return error;
}
async function getPages(browser, retryInterval = 100) {
const pages = await browser.pages();
if (pages.length === 0) {
log.info('no browser pages found, retrying...');
await new Promise(resolve => setTimeout(resolve, retryInterval));
return getPages(browser);
}
return pages;
}
function sort(installations, priorities) {
const defaultPriority = 10;
return installations.map(inst => {
for (const pair of priorities) {
if (pair.regex.test(inst)) {
return {
path: inst,
weight: pair.weight
};
}
}
return {
path: inst,
weight: defaultPriority
};
}).sort((a, b) => b.weight - a.weight).map(pair => pair.path);
}
function uniq(arr) {
return Array.from(new Set(arr));
}
function findByWhich(executables, priorities) {
const installations = [];
executables.forEach(executable => {
try {
const browserPath = (0, _child_process.execFileSync)('which', [executable], {
stdio: 'pipe'
}).toString().split(/\r?\n/)[0];
if ((0, _utils.canAccess)(browserPath)) {
installations.push(browserPath);
}
} catch (e) {}
});
return sort(uniq(installations.filter(Boolean)), priorities);
}
function patchDebug(scoppedLogger) {
let puppeteerDebugPkg = _path.default.resolve(_path.default.dirname(require.resolve('puppeteer-core')), 'node_modules', 'debug');
if (!_fs.default.existsSync(puppeteerDebugPkg)) {
const pkgName = 'debug';
puppeteerDebugPkg = require.resolve(pkgName);
}
require(puppeteerDebugPkg).log = msg => {
if (msg.includes('puppeteer:protocol')) {
msg = msg.slice(msg.indexOf(_constants.PPTR_LOG_PREFIX) + _constants.PPTR_LOG_PREFIX.length).trim();
}
scoppedLogger.debug(msg);
};
}