UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

201 lines (154 loc) 5.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _fs = _interopRequireDefault(require("fs")); var _path = _interopRequireDefault(require("path")); var _uuid = require("uuid"); var _logger = _interopRequireDefault(require("@wdio/logger")); var _utils = require("@wdio/utils"); var _elementstore = _interopRequireDefault(require("./elementstore")); var _utils2 = require("./utils"); var _constants = require("./constants"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const log = (0, _logger.default)('devtools'); class DevToolsDriver { constructor(browser, pages) { this.commands = {}; this.elementStore = new _elementstore.default(); this.windows = new Map(); this.timeouts = new Map(); this.activeDialog = null; this.browser = browser; const dir = _path.default.resolve(__dirname, 'commands'); const files = _fs.default.readdirSync(dir); for (let filename of files) { const commandName = _path.default.basename(filename, _path.default.extname(filename)); this.commands[commandName] = (0, _utils.safeRequire)(_path.default.join(dir, commandName)).default; } for (const page of pages) { const pageId = (0, _uuid.v4)(); this.windows.set(pageId, page); this.currentFrame = page; this.currentWindowHandle = pageId; } this.setTimeouts(_constants.DEFAULT_IMPLICIT_TIMEOUT, _constants.DEFAULT_PAGELOAD_TIMEOUT, _constants.DEFAULT_SCRIPT_TIMEOUT); const page = this.getPageHandle(); page.on('dialog', this.dialogHandler.bind(this)); page.on('framenavigated', this.framenavigatedHandler.bind(this)); } static requireCommand(filePath) { return require(filePath).default; } register(commandInfo) { const self = this; const { command, ref, parameters, variables = [] } = commandInfo; if (typeof this.commands[command] !== 'function') { return () => { throw new Error(`Command "${command}" is not yet implemented`); }; } let retries = 0; const wrappedCommand = async function (...args) { await self.checkPendingNavigations(); const params = (0, _utils2.validate)(command, parameters, variables, ref, args); let result; try { this.emit('command', { command, params, retries }); result = await self.commands[command].call(self, params); } catch (err) { if (err.message.includes('most likely because of a navigation')) { log.debug('Command failed due to unfinished page transition, retrying...'); const page = self.getPageHandle(); await new Promise((resolve, reject) => { const pageloadTimeout = setTimeout(() => reject(new Error('page load timeout')), self.timeouts.get('pageLoad')); page.once('load', () => { clearTimeout(pageloadTimeout); resolve(); }); }); ++retries; return wrappedCommand.apply(this, args); } throw (0, _utils2.sanitizeError)(err); } this.emit('result', { command, params, retries, result: { value: result } }); if (typeof result !== 'undefined') { const isScreenshot = command.toLowerCase().includes('screenshot') && typeof result === 'string' && result.length > 64; log.info('RESULT', isScreenshot ? `${result.substr(0, 61)}...` : result); } return result; }; return wrappedCommand; } dialogHandler(dialog) { this.activeDialog = dialog; } framenavigatedHandler(frame) { this.currentFrameUrl = frame.url(); this.elementStore.clear(); } setTimeouts(implicit, pageLoad, script) { if (typeof implicit === 'number') { this.timeouts.set('implicit', implicit); } if (typeof pageLoad === 'number') { this.timeouts.set('pageLoad', pageLoad); } if (typeof script === 'number') { this.timeouts.set('script', script); } const page = this.getPageHandle(); page.setDefaultTimeout(this.timeouts.get('pageLoad')); } getPageHandle(isInFrame = false) { if (isInFrame && this.currentFrame) { return this.currentFrame; } return this.windows.get(this.currentWindowHandle); } async checkPendingNavigations(pendingNavigationStart) { let page = this.getPageHandle(); if (this.activeDialog || !page) { return; } pendingNavigationStart = pendingNavigationStart || Date.now(); const pageloadTimeout = this.timeouts.get('pageLoad'); if (!page.mainFrame) { const pages = await this.browser.pages(); page = pages.find(browserPage => browserPage.frames().find(frame => page === frame)); } const pageloadTimeoutReached = Date.now() - pendingNavigationStart > pageloadTimeout; const executionContext = await page.mainFrame().executionContext(); try { await executionContext.evaluate('1'); const readyState = await executionContext.evaluate('document.readyState'); if (readyState !== 'complete' && !pageloadTimeoutReached) { return this.checkPendingNavigations(pendingNavigationStart); } } catch (err) { if (pageloadTimeoutReached) { throw err; } return this.checkPendingNavigations(pendingNavigationStart); } } } exports.default = DevToolsDriver;