Skip to content

Commit

Permalink
chore: Make remote debugger typed (#2433)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach authored Jul 25, 2024
1 parent 3db3352 commit f643c16
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 94 deletions.
21 changes: 13 additions & 8 deletions lib/commands/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -435,6 +439,7 @@ const helpers = {
},
/**
* @this {XCUITestDriver}
* @returns {Promise<RemoteDebugger>}
*/
async getNewRemoteDebugger() {
let socketPath;
Expand Down Expand Up @@ -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;
Expand All @@ -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),
);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/commands/screenshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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();
Expand Down
30 changes: 18 additions & 12 deletions lib/commands/web.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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}
Expand All @@ -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}
Expand All @@ -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) => {
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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);
},
/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
},

Expand Down Expand Up @@ -1006,3 +1008,7 @@ export default {...helpers, ...extensions, ...commands};
* @template {string} [S=string]
* @typedef {import('@appium/types').Element<S>} Element
*/

/**
* @typedef {import('appium-remote-debugger').RemoteDebugger} RemoteDebugger
*/
4 changes: 4 additions & 0 deletions lib/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ export class XCUITestDriver extends BaseDriver {
/** @type {WebDriverAgent} */
wda;

/** @type {import('appium-remote-debugger').RemoteDebugger|null} */
remote;

/**
*
* @param {XCUITestDriverOpts} opts
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
68 changes: 0 additions & 68 deletions test/functional/basic/gesture-e2e-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down

0 comments on commit f643c16

Please sign in to comment.