diff --git a/lib/controllers.js b/lib/controllers.js index 9dfd8c3..b34fe0d 100644 --- a/lib/controllers.js +++ b/lib/controllers.js @@ -16,7 +16,7 @@ const implicitWaitForCondition = function(func) { }; const sendJSCommand = async function(atom, args, inDefaultFrame) { - const frames = !inDefaultFrame && this.frame ? [ this.frame ] : []; + const frames = !inDefaultFrame && this.pageIframe ? [ this.pageIframe ] : []; const atomScript = getAtom(atom); let script; if (frames.length) { @@ -60,24 +60,6 @@ const convertAtoms2Element = function(atoms) { }; }; -const convertElement2Atoms = function(elementId) { - if (!elementId) { - return null; - } - - let atomsId; - - try { - atomsId = this.atoms[parseInt(elementId, 10) - ELEMENT_OFFSET]; - } catch (e) { - return null; - } - - return { - ELEMENT: atomsId, - }; -}; - const findElementOrElements = async function(strategy, selector, ctx, many) { strategy = strategy.toLowerCase(); @@ -146,30 +128,22 @@ const controllers = {}; * Change focus to another frame on the page. * * @module setFrame - * @param {string} frame Identifier(id/name) for the frame to change focus to * @return {Promise} + * @param frameElementId */ -controllers.setFrame = async function(frame) { - if (!_.isNumber && !frame) { - this.frame = null; - logger.debug('Back to default content'); - return null; - } - - if (frame.ELEMENT) { - const atomsElement = convertElement2Atoms.call(this, frame.ELEMENT); - const result = await sendJSCommand.call(this, 'get_frame_window', [ atomsElement ]); - logger.debug(`Entering into web frame: '${result.WINDOW}'`); - this.frame = result.WINDOW; +controllers.setFrame = async function(frameElementId) { + let ele; + if (frameElementId) { + ele = await this.elements[frameElementId]; + } else { + // clear pageIframe + this.pageIframe = null; return null; } - const atom = _.isNumber(frame) ? 'frame_by_index' : 'frame_by_id_or_name'; - const result = await sendJSCommand.call(this, atom, [ frame ]); - if (!result || !result.WINDOW) { + this.pageIframe = await ele.contentFrame(); + if (!this.pageIframe) { throw new errors.NoSuchFrame(); } - logger.debug(`Entering into web frame: '${result.WINDOW}'`); - this.frame = result.WINDOW; return null; }; @@ -366,7 +340,7 @@ controllers.url = async function() { * @return {Promise.} */ controllers.get = async function(url) { - this.frame = null; + this.pageIframe = null; await this.page.goto(url, { waitUntil: 'load' || 'networkidle', }); @@ -380,7 +354,7 @@ controllers.get = async function(url) { * @return {Promise.} */ controllers.forward = async function() { - this.frame = null; + this.pageIframe = null; await this.page.goForward(); return null; }; @@ -392,7 +366,7 @@ controllers.forward = async function() { * @return {Promise.} */ controllers.back = async function() { - this.frame = null; + this.pageIframe = null; await this.page.goBack(); return null; }; @@ -486,7 +460,7 @@ controllers.maximize = async function(windowHandle) { * @return {Promise.} */ controllers.refresh = async function() { - this.frame = null; + this.pageIframe = null; return this.page.reload(); }; @@ -513,7 +487,7 @@ controllers.getScreenshot = async function(context, params = {}) { params.fullPage = params.fullPage === 'true'; } if (params.video) { - return this.page.video()?.path?.() || null; + return await this.page.video()?.path?.() || null; } const image = await this.page.screenshot(params); const base64 = image.toString('base64'); diff --git a/lib/macaca-playwright.ts b/lib/macaca-playwright.ts index dc05aa9..d4a426b 100644 --- a/lib/macaca-playwright.ts +++ b/lib/macaca-playwright.ts @@ -1,6 +1,6 @@ import path from 'path'; import { sync as mkdirp } from 'mkdirp'; -import playwright from 'playwright'; +import playwright, { Frame } from 'playwright'; import DriverBase from 'driver-base'; import _ from './helper'; @@ -48,9 +48,10 @@ class Playwright extends DriverBase { browser = null; browserContext = null; newContextOptions = {}; - frame = null; + pageIframes: Frame[] = []; page = null; pagePopup = null; + pageIframe: Frame = null; locator = null; // 当前选中的 element atoms = []; pages = []; @@ -162,8 +163,7 @@ class Playwright extends DriverBase { contextName = DEFAULT_CONTEXT; } const index = this.browserContexts.findIndex(it => it.name === contextName); - this.browserContext = this.browserContexts[index]; - this.page = this.pages[index]; + this._setContext(index); return index; } @@ -172,6 +172,25 @@ class Playwright extends DriverBase { this.page = this.pages[index]; } + /** + * 设置当前的page的Iframes + */ + _freshPageIframes() { + this.pageIframes = this.page.mainFrame().childFrames(); + } + + /** + * 设置当前操作的iframe + */ + _setPageIframeByIndex(index = 0) { + this._freshPageIframes(); + if (!this.pageIframes[index]) { + console.error('target iframe not found'); + return; + } + this.pageIframe = this.pageIframes[index]; + } + async stopDevice() { await this.browserContext.close(); await this.browser.close(); diff --git a/lib/next-actions.js b/lib/next-actions.js index 0edaf55..7ae8ad9 100644 --- a/lib/next-actions.js +++ b/lib/next-actions.js @@ -9,12 +9,14 @@ nextActions.fileChooser = async function(filePath) { }; nextActions.keyboard = async function({ type, args }) { - await this.page.keyboard[type].apply(this.page.keyboard, args); + const target = this.pageIframe || this.page; + await target.keyboard[type].apply(target.keyboard, args); return true; }; nextActions.mouse = async function({ type, args }) { - await this.page.mouse[type].apply(this.page.mouse, args); + const target = this.pageIframe || this.page; + await target.mouse[type].apply(target.mouse, args); return true; }; @@ -58,6 +60,25 @@ nextActions.pagePopup = async function({ func, args }) { logger.error('pagePopup or func is not found'); }; +/** + * 当前page中frame对象的方法调用 + * @param index 指定为当前page中第几个iframe + * @param func + * @param args + * @returns {Promise<*|string>} + */ +nextActions.pageIframe = async function({ index, func, args }) { + if (_.isNumber(index)) { + this._setPageIframeByIndex(index); + } + if (this.pageIframe && this.pageIframe[func]) { + await this.pageIframe.waitForLoadState(); + const result = await this.pageIframe[func].apply(this.pageIframe, args); + return result || ''; + } + logger.error('pageIframe or func is not found'); +}; + nextActions.elementStatus = async function(elementId) { const element = this.elements[elementId]; if (!element) { diff --git a/package.json b/package.json index b6671db..74ffc24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "macaca-playwright", - "version": "1.11.14", + "version": "1.11.15", "description": "Macaca Playwright driver", "keywords": [ "playwright",