UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

260 lines (203 loc) 8 kB
"use strict"; 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); }; }