diff --git a/lib/commands/context.js b/lib/commands/context.js index 3bd707eb5..3d987a5ff 100644 --- a/lib/commands/context.js +++ b/lib/commands/context.js @@ -35,7 +35,7 @@ const extensions = { */ let ctxs = [{id: NATIVE_WIN, view: {}}]; this.contexts = [NATIVE_WIN]; - for (let view of webviews) { + for (const view of webviews) { ctxs.push({id: `${WEBVIEW_BASE}${view.id}`, view}); this.contexts.push(view.id.toString()); } @@ -75,7 +75,7 @@ const extensions = { if (contextId) { this.log.info(`Picking webview '${contextId}' after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`); await this.setContext(contextId); - await this.remote.cancelPageLoad(); + await (/** @type {RemoteDebugger} */ (this.remote)).cancelPageLoad(); return true; } @@ -112,13 +112,15 @@ const extensions = { if (!this.remote) { await this.connectToRemoteDebugger(); + // @ts-ignore TS does not understand property mutation if (!this.remote.appIdKey) { + // @ts-ignore TS does not understand property mutation await this.remote.setConnectionKey(); } } const getWebviewPages = async () => { try { - return await this.remote.selectApp( + return await (/** @type {RemoteDebugger} */ (this.remote)).selectApp( useUrl ? this.getCurrentUrl() : undefined, this.opts.webviewConnectRetries, this.opts.ignoreAboutBlankUrl, @@ -141,7 +143,9 @@ const extensions = { async connectToRemoteDebugger() { this.remote = await this.getNewRemoteDebugger(); + // @ts-ignore static is fine this.remote.on(RemoteDebugger.EVENT_PAGE_CHANGE, this.onPageChange.bind(this)); + // @ts-ignore static is fine this.remote.on(RemoteDebugger.EVENT_FRAMES_DETACHED, () => { if (isNonEmptyArray(this.curWebFrames)) { const curWebFrames = this.curWebFrames; @@ -333,7 +337,7 @@ const extensions = { if (needsPageLoad) { this.log.debug('Page load needed. Loading...'); - await this.remote.pageLoad(); + await this.remote.waitForDom(); } this.log.debug('New page listing is same as old, doing nothing'); @@ -371,7 +375,7 @@ const helpers = { */ async stopRemote(closeWindowBeforeDisconnecting = false) { if (!this.remote) { - this.log.errorAndThrow('Tried to leave a web frame but were not in one'); + throw this.log.errorWithException('Tried to leave a web frame but were not in one'); } if (closeWindowBeforeDisconnecting) { @@ -435,6 +439,7 @@ const helpers = { }, /** * @this {XCUITestDriver} + * @returns {Promise} */ async getNewRemoteDebugger() { let socketPath; @@ -547,7 +552,7 @@ const commands = { const [appIdKey, pageIdKey] = _.map(contextId.split('.'), (id) => parseInt(id, 10)); try { this.selectingNewPage = true; - await this.remote.selectPage(appIdKey, pageIdKey, skipReadyCheck); + await (/** @type {RemoteDebugger} */ (this.remote)).selectPage(appIdKey, pageIdKey, skipReadyCheck); } catch (err) { this.curContext = this.curWindowHandle = oldContext; throw err; @@ -568,12 +573,12 @@ const commands = { // start safari logging if the logs handlers are active if (name && name !== NATIVE_WIN && this.logs) { if (this.logs.safariConsole) { - await this.remote.startConsole( + (/** @type {RemoteDebugger} */ (this.remote)).startConsole( this.logs.safariConsole.onConsoleLogEvent.bind(this.logs.safariConsole), ); } if (this.logs.safariNetwork) { - await this.remote.startNetwork( + (/** @type {RemoteDebugger} */ (this.remote)).startNetwork( this.logs.safariNetwork.onNetworkEvent.bind(this.logs.safariNetwork), ); } diff --git a/lib/commands/execute.js b/lib/commands/execute.js index 25b1f9606..958c6d0f4 100644 --- a/lib/commands/execute.js +++ b/lib/commands/execute.js @@ -135,7 +135,7 @@ export default { args = this.convertElementsForAtoms(args); this.asyncWaitMs = this.asyncWaitMs || 0; - const promise = this.remote.executeAtomAsync( + const promise = (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).executeAtomAsync( 'execute_async_script', [script, args, this.asyncWaitMs], this.curWebFrames, diff --git a/lib/commands/general.js b/lib/commands/general.js index 44de9cd29..13cf35ad6 100644 --- a/lib/commands/general.js +++ b/lib/commands/general.js @@ -162,7 +162,7 @@ const commands = { this.setCurrentUrl(url); // make sure to clear out any leftover web frames this.curWebFrames = []; - await this.remote.navToUrl(url); + await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).navToUrl(url); return; } diff --git a/lib/commands/screenshots.js b/lib/commands/screenshots.js index 69ec9a253..fd2685c40 100644 --- a/lib/commands/screenshots.js +++ b/lib/commands/screenshots.js @@ -14,8 +14,8 @@ export default { switch (_.toLower(webScreenshotMode)) { case 'page': case 'viewport': - return await this.remote.captureScreenshot({ - coordinateSystem: _.capitalize(webScreenshotMode), + return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).captureScreenshot({ + coordinateSystem: /** @type {'Viewport'|'Page'} */ (_.capitalize(webScreenshotMode)), }); case 'native': case undefined: @@ -94,7 +94,7 @@ export default { */ async getViewportScreenshot() { if (this.isWebContext()) { - return await this.remote.captureScreenshot(); + return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).captureScreenshot(); } let statusBarHeight = await this.getStatusBarHeight(); diff --git a/lib/commands/web.js b/lib/commands/web.js index 8606cb3a5..28b0282ac 100644 --- a/lib/commands/web.js +++ b/lib/commands/web.js @@ -188,7 +188,7 @@ const commands = { throw new errors.NotImplementedError(); } - await this.remote.execute('window.location.reload()'); + await (/** @type {RemoteDebugger} */ (this.remote)).execute('window.location.reload()'); }, /** * @this {XCUITestDriver} @@ -199,7 +199,7 @@ const commands = { throw new errors.NotImplementedError(); } - return await this.remote.execute('window.location.href'); + return await (/** @type {RemoteDebugger} */ (this.remote)).execute('window.location.href'); }, /** * @this {XCUITestDriver} @@ -210,7 +210,7 @@ const commands = { throw new errors.NotImplementedError(); } - return await this.remote.execute('window.document.title'); + return await (/** @type {RemoteDebugger} */ (this.remote)).execute('window.document.title'); }, /** * @this {XCUITestDriver} @@ -222,7 +222,7 @@ const commands = { } // get the cookies from the remote debugger, or an empty object - const {cookies} = await this.remote.getCookies(); + const {cookies} = await (/** @type {RemoteDebugger} */ (this.remote)).getCookies(); // the value is URI encoded, so decode it safely return cookies.map((cookie) => { @@ -306,7 +306,7 @@ const helpers = { */ async _deleteCookie(cookie) { const url = `http${cookie.secure ? 's' : ''}://${cookie.domain}${cookie.path}`; - return await this.remote.deleteCookie(cookie.name, url); + return await (/** @type {RemoteDebugger} */ (this.remote)).deleteCookie(cookie.name, url); }, /** * @this {XCUITestDriver} @@ -351,18 +351,20 @@ const helpers = { */ async executeAtom(atom, args, alwaysDefaultFrame = false) { let frames = alwaysDefaultFrame === true ? [] : this.curWebFrames; - let promise = this.remote.executeAtom(atom, args, frames); + let promise = (/** @type {RemoteDebugger} */ (this.remote)).executeAtom(atom, args, frames); return await this.waitForAtom(promise); }, /** * @this {XCUITestDriver} + * @param {string} atom + * @param {any[]} args */ - async executeAtomAsync(atom, args, responseUrl) { + async executeAtomAsync(atom, args) { // save the resolve and reject methods of the promise to be waited for let promise = new B((resolve, reject) => { this.asyncPromise = {resolve, reject}; }); - await this.remote.executeAtomAsync(atom, args, this.curWebFrames, responseUrl); + await (/** @type {RemoteDebugger} */ (this.remote)).executeAtomAsync(atom, args, this.curWebFrames); return await this.waitForAtom(promise); }, /** @@ -673,7 +675,7 @@ const extensions = { const { offsetX, offsetY, pixelRatioX, pixelRatioY } = this.webviewCalibrationResult; const cmd = '(function () {return {innerWidth: window.innerWidth, innerHeight: window.innerHeight, ' + 'outerWidth: window.outerWidth, outerHeight: window.outerHeight}; })()'; - const wvDims = await this.remote.execute(cmd); + const wvDims = await (/** @type {RemoteDebugger} */ (this.remote)).execute(cmd); // https://tripleodeon.com/2011/12/first-understand-your-screen/ const shouldApplyPixelRatio = wvDims.innerWidth > wvDims.outerWidth || wvDims.innerHeight > wvDims.outerHeight; @@ -713,7 +715,7 @@ const extensions = { const realDims = {w: rect.width, h: rect.height}; const cmd = '(function () { return {w: window.innerWidth, h: window.innerHeight}; })()'; - const wvDims = await this.remote.execute(cmd); + const wvDims = await (/** @type {RemoteDebugger} */ (this.remote)).execute(cmd); // keep track of implicit wait, and set locally to 0 // https://github.com/appium/appium/issues/14988 @@ -854,11 +856,11 @@ const extensions = { * @this {XCUITestDriver} */ async mobileWebNav(navType) { - this.remote.allowNavigationWithoutReload = true; + (/** @type {RemoteDebugger} */ (this.remote)).allowNavigationWithoutReload = true; try { await this.executeAtom('execute_script', [`history.${navType}();`, null]); } finally { - this.remote.allowNavigationWithoutReload = false; + (/** @type {RemoteDebugger} */ (this.remote)).allowNavigationWithoutReload = false; } }, @@ -1006,3 +1008,7 @@ export default {...helpers, ...extensions, ...commands}; * @template {string} [S=string] * @typedef {import('@appium/types').Element} Element */ + +/** + * @typedef {import('appium-remote-debugger').RemoteDebugger} RemoteDebugger + */ \ No newline at end of file diff --git a/lib/driver.js b/lib/driver.js index 43a22ad94..705b2eb26 100644 --- a/lib/driver.js +++ b/lib/driver.js @@ -262,6 +262,9 @@ export class XCUITestDriver extends BaseDriver { /** @type {WebDriverAgent} */ wda; + /** @type {import('appium-remote-debugger').RemoteDebugger|null} */ + remote; + /** * * @param {XCUITestDriverOpts} opts @@ -310,6 +313,7 @@ export class XCUITestDriver extends BaseDriver { this.lifecycleData = {}; this._audioRecorder = null; this.appInfosCache = new AppInfosCache(this.log); + this.remote = null; } async onSettingsUpdate(key, value) { diff --git a/package.json b/package.json index f01fdb3f3..e44d800bb 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "appium-idb": "^1.6.13", "appium-ios-device": "^2.5.4", "appium-ios-simulator": "^6.1.7", - "appium-remote-debugger": "^11.3.0", + "appium-remote-debugger": "^11.5.3", "appium-webdriveragent": "^8.7.8", "appium-xcode": "^5.1.4", "async-lock": "^1.4.0", diff --git a/test/functional/basic/gesture-e2e-specs.js b/test/functional/basic/gesture-e2e-specs.js index 6a568b3bd..11973a88b 100644 --- a/test/functional/basic/gesture-e2e-specs.js +++ b/test/functional/basic/gesture-e2e-specs.js @@ -85,74 +85,6 @@ describe('XCUITestDriver - gestures', function () { await exitModal('OK'); }); }); - - describe('using touchAction', function () { - it('should tap on the element with touchAction', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - await driver.touchAction({ - action: 'tap', - element: el, - }); - await exitModal('OK'); - }); - it('should tap on arbitrary coordinates with action', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - const loc = await el.getLocation(); - const size = await el.getSize(); - - await driver.touchAction({ - action: 'tap', - x: loc.x + size.width / 2, - y: loc.y + size.height / 2, - }); - - await exitModal('OK'); - }); - - it('should long press on an element', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - await driver.touchAction([{action: 'longPress', element: el}, 'release']); - - await exitModal('Cancel'); - }); - it('should long press on an element with duration through press-wait-release', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - await driver.touchAction([ - {action: 'press', element: el}, - {action: 'wait', ms: 1200}, - 'release', - ]); - - await exitModal('Cancel'); - }); - it('should long press on an element with duration through longPress-wait-release', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - await driver.touchAction([ - {action: 'longPress', element: el}, - {action: 'wait', ms: 1200}, - 'release', - ]); - - await exitModal('Cancel'); - }); - it('should long press on arbitrary coordinates', async function () { - const el = await driver.$(`~${BTN_OK_CNCL}`); - const loc = await el.getLocation(); - const size = await el.getSize(); - - await driver.touchAction([ - { - action: 'longPress', - x: loc.x + size.width / 2, - y: loc.y + size.height / 2, - }, - {action: 'wait', ms: 500}, - 'release', - ]); - - await exitModal('OK'); - }); - }); }); // TODO: Need a scrollable screen. it.skip('should scroll using actions', async function () {