appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
119 lines • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGeoLocation = getGeoLocation;
exports.setGeoLocation = setGeoLocation;
exports.mobileResetLocationService = mobileResetLocationService;
const appium_ios_device_1 = require("appium-ios-device");
const driver_1 = require("appium/driver");
const support_1 = require("appium/support");
const enum_1 = require("./enum");
const utils_1 = require("../utils");
/**
* 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.
*
* For iOS 17, the return value could be the result of
* "mobile:getSimulatedLocation" if the simulated location has been previously set
* "mobile:setSimulatedLocation" already.
*
* @returns Location with altitude
* @throws {Error} If the device under test returns an error message.
* i.e.: tvOS returns unsupported error
*/
async function getGeoLocation() {
// Currently we proxy the setGeoLocation to mobile:setSimulatedLocation for iOS 17+.
// It would be helpful to address to use "mobile:getSimulatedLocation" for iOS 17+.
if ((0, utils_1.isIos17OrNewer)(this.opts)) {
const { latitude, longitude } = await this.mobileGetSimulatedLocation();
if (latitude && longitude) {
this.log.debug('Returning the geolocation that has been previously set by mobile:setSimulatedLocation. ' +
'mobile:resetSimulatedLocation can reset the location configuration.');
return { latitude, longitude, altitude: 0 };
}
this.log.warn(`No location was set by mobile:setSimulatedLocation. Trying to return the location from the device.`);
}
// Please do not change the way to get the location here with '/wda/simulatedLocation'
// endpoint because they could return different value before setting the simulated location.
// '/wda/device/location' returns current device location information,
// but '/wda/simulatedLocation' returns `null` values until the WDA process
// sets a simulated location. After setting the value, both returns the same values.
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 !== enum_1.AuthorizationStatus.authorizedAlways) {
throw this.log.errorWithException(`Location service must be set to 'Always' in order to ` +
`retrieve the current geolocation data. Please set it up manually via ` +
`'Settings > Privacy > Location Services -> WebDriverAgentRunner-Runner'. ` +
`Or please use 'mobile:getSimulatedLocation'/'mobile:setSimulatedLocation' commands ` +
`to simulate locations instead.`);
}
return { latitude, longitude, altitude };
}
/**
* Set location of the device under test.
*
* iOS 17+ real device environment will be via "mobile:setSimulatedLocation" as
* setting simulated location for XCTest session.
*
* @param location - Location with latitude and longitude
*/
async function setGeoLocation(location) {
const { latitude, longitude } = location;
if (!support_1.util.hasValue(latitude) || !support_1.util.hasValue(longitude)) {
throw new driver_1.errors.InvalidArgumentError(`Both latitude and longitude should be set`);
}
if (this.isSimulator()) {
await this.device.setGeolocation(`${latitude}`, `${longitude}`);
return { latitude, longitude, altitude: 0 };
}
if ((0, utils_1.isIos17OrNewer)(this.opts)) {
this.log.info(`Proxying to mobile:setSimulatedLocation method for iOS 17+`);
await this.mobileSetSimulatedLocation(latitude, longitude);
}
else {
const service = await appium_ios_device_1.services.startSimulateLocationService(this.opts.udid);
try {
service.setLocation(latitude, longitude);
}
catch (e) {
throw this.log.errorWithException(`Can't set the location on device '${this.opts.udid}'. Original error: ${e.message}`);
}
finally {
service.close();
}
}
return { latitude, longitude, altitude: 0 };
}
/**
* Reset the location service on real device.
*
* @throws {Error} If the device is simulator and iOS version is below 17,
* or 'resetLocation' raises an error.
*/
async function mobileResetLocationService() {
if ((0, utils_1.isIos17OrNewer)(this.opts)) {
this.log.info(`Proxying to mobile:resetSimulatedLocation method for iOS 17+`);
await this.mobileResetSimulatedLocation();
return;
}
if (this.isSimulator()) {
throw new driver_1.errors.NotImplementedError();
}
const service = await appium_ios_device_1.services.startSimulateLocationService(this.opts.udid);
try {
service.resetLocation();
}
catch (err) {
throw this.log.errorWithException(`Failed to reset the location on the device on device '${this.opts.udid}'. ` +
`Original error: ${err.message}`);
}
finally {
service.close();
}
}
//# sourceMappingURL=location.js.map