diff --git a/percy/driver/driverWrapper.js b/percy/driver/driverWrapper.js index c05fcd4..127cde9 100644 --- a/percy/driver/driverWrapper.js +++ b/percy/driver/driverWrapper.js @@ -14,7 +14,7 @@ class AppiumDriver { // in real world when you get wd driver passed so need to ignore coverage on it // In typescript for wdio we get driver.constuctor.name as 'BoundBrowser' - if (driver.constructor.name.includes('Browser') && !Undefined(driver.getSession)) { + if (driver.constructor.name.includes('Browser') && !Undefined(driver.capabilities)) { this.type = 'wdio'; } else if ((driver.constructor.name === '' || driver.constructor.name === 'Object') && // Object check is only added for tests @@ -30,7 +30,7 @@ class AppiumDriver { return await TimeIt.run('getCapabilities', async () => { if (this.wd) return await this.driver.sessionCapabilities(); /* istanbul ignore next */ // not sure why its marking it when its covered - if (this.wdio) return await this.driver.getSession(); + if (this.wdio) return await this.driver.capabilities; }); }); } @@ -108,6 +108,12 @@ class AppiumDriver { }); } + async getWindowSize() { + return await TimeIt.run('getWindowSize', async () => { + return await this.driver.getWindowSize(); + }); + } + get commandExecutorUrl() { if (this.wd) return `${this.driver.configUrl.protocol}//${this.remoteHostname}${this.driver.configUrl.path}`; /* istanbul ignore next */ diff --git a/percy/metadata/iosMetadata.js b/percy/metadata/iosMetadata.js index 61c49a0..fcb426b 100644 --- a/percy/metadata/iosMetadata.js +++ b/percy/metadata/iosMetadata.js @@ -6,14 +6,18 @@ class IosMetadata extends Metadata { // We are rechecking this first as we dont want to apply pixelRatio if this given by user if (this._statusBarHeight) return this._statusBarHeight; - const caps = await this.caps(); if (await this.staticData()) { const data = await this.staticData(); return data.statusBarHeight * data.pixelRatio; } - // In Ios the height of statusBarHeight in caps needs to be multiplied by pixel ratio - return (caps.statBarHeight || 1) * (caps.pixelRatio || 1); + // For iOS method to fetch statusBarHeight for wdio & wd is different + if (this.driver.wdio) { + return (await this.viewportRect()).top; + } else { + const caps = await this.caps(); + return (caps.statBarHeight || 1) * (caps.pixelRatio || 1); + } } async navigationBarHeight() { @@ -26,16 +30,32 @@ class IosMetadata extends Metadata { async screenSize() { // We just add statusBarHeight and viewport rect // We do not use existing functions because user can override those - const caps = await this.caps(); if (await this.staticData()) { const data = await this.staticData(); return { width: data.screenWidth, height: data.screenHeight }; } - const height = caps.statBarHeight * caps.pixelRatio + caps.viewportRect?.height; - const width = caps.viewportRect?.width; + + let height, width; + // For iOS method to fetch screenSize for wdio & wd is different + if (this.driver.wdio) { + const viewportRect = await this.viewportRect(); + height = viewportRect.top + viewportRect.height; + width = viewportRect.width; + } else { + const caps = await this.caps(); + height = caps.statBarHeight * caps.pixelRatio + caps.viewportRect?.height; + width = caps.viewportRect?.width; + } return { width, height }; } + async viewportRect() { + if (this._viewportRect) return this._viewportRect; + + this._viewportRect = await this.driver.execute('mobile: viewportRect'); + return this._viewportRect; + } + // Need override because ios does not have desired in caps async deviceName() { if (this._deviceName) return this._deviceName; @@ -51,7 +71,16 @@ class IosMetadata extends Metadata { } async scaleFactor() { - return (await this.caps()).pixelRatio; + // For iOS method to fetch scaleFactor for wdio & wd is different + if (this.driver.wdio) { + const viewportRect = await this.viewportRect(); + const actualWidth = viewportRect.width; + const windowSize = await this.driver.getWindowSize(); + const width = windowSize.width; + return actualWidth / width; + } else { + return (await this.caps()).pixelRatio; + } } } diff --git a/percy/metadata/metadata.js b/percy/metadata/metadata.js index fa3655e..6a93ca1 100644 --- a/percy/metadata/metadata.js +++ b/percy/metadata/metadata.js @@ -16,6 +16,7 @@ class Metadata { this._orientation = orientation || 'caps'; this._statusBarHeight = statusBarHeight; this._navigationBarHeight = navigationBarHeight; + this._viewportRect = null; } // items that need caps are moved to getters as caps are not stored on wd driver object diff --git a/percy/util/cache.js b/percy/util/cache.js index 1b7d31e..45819e6 100644 --- a/percy/util/cache.js +++ b/percy/util/cache.js @@ -1,4 +1,3 @@ - const { Undefined } = require('./validations'); class Cache { diff --git a/test/mocks/appium/appium_driver.js b/test/mocks/appium/appium_driver.js index 6b7786f..977ad3d 100644 --- a/test/mocks/appium/appium_driver.js +++ b/test/mocks/appium/appium_driver.js @@ -4,7 +4,14 @@ module.exports = function() { return { sessionId: 'sessionId', remoteHostname: 'localhost', - execute: jasmine.createSpy().and.resolveTo(JSON.stringify({ success: true })), + // execute: jasmine.createSpy().and.resolveTo(JSON.stringify({ success: true })), + execute: jasmine.createSpy().and.callFake((str) => { + if (str.includes('viewportRect')) { + return { width: 100, height: 200 }; + } else { + return JSON.stringify({ success: true }); + } + }), takeScreenshot: jasmine.createSpy().and.resolveTo('abcd=') }; }; diff --git a/test/mocks/appium/wdio_driver.js b/test/mocks/appium/wdio_driver.js index fb4dda4..0f2345a 100644 --- a/test/mocks/appium/wdio_driver.js +++ b/test/mocks/appium/wdio_driver.js @@ -11,7 +11,7 @@ class Browser { appAutomate = appAutomate || false; const ios = platform === 'iOS' || false; const android = !ios; - deviceName = deviceName || android ? 'GenericAndroid' : 'iPhone 8 Plus'; // some device from static config + deviceName = deviceName || android ? 'GenericAndroid' : 'iPhone 14'; // some device from static config enabled = enabled === undefined ? true : enabled; ignoreErrors = ignoreErrors === undefined ? false : ignoreErrors; @@ -45,7 +45,7 @@ class Browser { }; this.capabilities = sessionCaps; - + this.getWindowSize = jasmine.createSpy().and.resolveTo({ width: 390, height: 844, x: 0, y: 0 }); this.getSession = jasmine.createSpy().and.returnValue(sessionCaps); this.takeScreenshot = jasmine.createSpy().and.resolveTo('some screenshot data'); this.getSystemBars = jasmine.createSpy().and.resolveTo({ @@ -77,6 +77,8 @@ class Browser { ]) }); } + } else if (str.includes('viewportRect')) { + return { width: 100, height: 200 }; } }); this.getOrientation = jasmine.createSpy().and.returnValue('PORTRAIT'); diff --git a/test/percy/metadata/iosMetadata.test.mjs b/test/percy/metadata/iosMetadata.test.mjs index 434c1f4..2c2bafc 100644 --- a/test/percy/metadata/iosMetadata.test.mjs +++ b/test/percy/metadata/iosMetadata.test.mjs @@ -124,4 +124,17 @@ describe('Metadata', () => { expect(await metadata.scaleFactor()).toEqual(expectedScaleFactor); }); }); + + describe('viewportRect', () => { + const expectedViewportRect = { width: 100, height: 200 }; + + it('returns viewportRect', async () => { + expect(await metadata.viewportRect()).toEqual(expectedViewportRect); + }); + + it('returns from viewportRect field', async () => { + await metadata.viewportRect(); + expect(await metadata.viewportRect()).toEqual(expectedViewportRect); + }); + }); });