diff --git a/lib/commands/location.js b/lib/commands/location.js index 3453b6ef5..1f01acb6d 100644 --- a/lib/commands/location.js +++ b/lib/commands/location.js @@ -4,6 +4,46 @@ import log from '../logger'; let commands = {}; +/** + * @typedef {Object} LocationObject + * + * @property {number} latitude - The latitude of the device under test + * @property {number} longitude - The longitude of the device under test + * @property {number} altitude - The altitude of the device under test + */ + +/** + * Returns location of the device under test. + * The device under test must allow the location services for WDA + * as 'Always' to get the location data correctly. + * + * The 'latitude', 'longitude' and 'altitude' could be zero even + * if the Location Services are set to 'Always', because the device + * needs some time to update the location data. + * + * @returns {LocationObject} + * @throws {Error} If the device under test returns an error message. + * i.e.: tvOS returns unsupported error + */ +commands.getGeoLocation = async function getGeoLocation () { + const { + authorizationStatus, + latitude, + longitude, + altitude + } = await this.proxyCommand('/wda/device/location', 'GET'); + + // '3' is 'Always' in the privacy + // https://developer.apple.com/documentation/corelocation/clauthorizationstatus + if (authorizationStatus !== 3) { + log.errorAndThrow(`Location service must be set to 'Always' in order to ` + + `retrive the current geolocation data. Please set it up manually via ` + + `'Settings > Privacy > Location Services -> WebDriverAgentRunner-Runner'`); + } + + return {latitude, longitude, altitude}; +}; + commands.setGeoLocation = async function setGeoLocation (location) { let {latitude, longitude} = location; diff --git a/package.json b/package.json index e9bb8466d..8b09992a9 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "appium-ios-simulator": "^3.25.1", "appium-remote-debugger": "^8.13.2", "appium-support": "^2.47.1", - "appium-webdriveragent": "^2.32.2", + "appium-webdriveragent": "^2.33.1", "appium-xcode": "^3.8.0", "async-lock": "^1.0.0", "asyncbox": "^2.3.1", diff --git a/test/functional/basic/basic-e2e-specs.js b/test/functional/basic/basic-e2e-specs.js index 51d76d5ca..1cec37571 100644 --- a/test/functional/basic/basic-e2e-specs.js +++ b/test/functional/basic/basic-e2e-specs.js @@ -261,6 +261,13 @@ describe('XCUITestDriver - basics -', function () { }); }); + describe('get geo location -', function () { + it('should fail because of preference error', async function () { + await driver.getGeoLocation() + .should.eventually.be.rejectedWith('Location service must be'); + }); + }); + describe('geo location -', function () { it('should work on Simulator', async function () { if (process.env.CI || process.env.REAL_DEVICE) { diff --git a/test/unit/commands/location-specs.js b/test/unit/commands/location-specs.js index ddf312c56..2b6d183c4 100644 --- a/test/unit/commands/location-specs.js +++ b/test/unit/commands/location-specs.js @@ -12,6 +12,36 @@ describe('location commands', function () { proxySpy.reset(); }); + describe('getGeoLocation', function () { + it('should be authorizationStatus !== 3', async function () { + proxySpy.withArgs( + '/wda/device/location', + 'GET').returns({authorizationStatus: 0, latitude: 0, longitude: 0}); + + await driver.getGeoLocation({}) + .should.eventually.be.rejectedWith('Location service must be'); + }); + + it('should be authorizationStatus === 3', async function () { + proxySpy.withArgs( + '/wda/device/location', + 'GET').returns( + { + authorizationStatus: 3, + latitude: -100.395050048828125, + longitude: 100.09922650538002, + altitude: 26.267269134521484 + }); + + await driver.getGeoLocation({}) + .should.eventually.eql({ + altitude: 26.267269134521484, + latitude: -100.395050048828125, + longitude: 100.09922650538002 + }); + }); + }); + describe('setLocation', function () { let startSimulateLocationServiceStub; let setLocationStub;