appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
175 lines • 7.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isStrictHostUtilityMode = isStrictHostUtilityMode;
exports.assertWdaHostSessionCapsSupported = assertWdaHostSessionCapsSupported;
exports.createWdaHostOps = createWdaHostOps;
exports.assertWdaHostPlatformSupported = assertWdaHostPlatformSupported;
const utils_1 = require("../utils");
const XCODE_ONLY_CAPS = [
'usePrebuiltWDA',
'useXctestrunFile',
'prebuildWDA',
'xcodeOrgId',
'xcodeSigningId',
'xcodeConfigFile',
'keychainPath',
'keychainPassword',
'allowProvisioningDeviceRegistration',
'resultBundlePath',
];
/**
* Whether the selected session strategy must avoid host-side Xcode/Simulator utilities.
*/
function isStrictHostUtilityMode(opts, platform = process.platform) {
return platform !== 'darwin' && Boolean(opts.webDriverAgentUrl || opts.usePreinstalledWDA);
}
/**
* Verifies host-only utility requirements that can be checked before device discovery.
*/
function assertWdaHostSessionCapsSupported(opts, platform = process.platform) {
if (platform === 'darwin') {
return;
}
if (!opts.webDriverAgentUrl && !opts.usePreinstalledWDA) {
throw new Error(`The selected XCUITest session strategy requires macOS with Xcode. ` +
`Use 'appium:usePreinstalledWDA' with a signed prebuilt WebDriverAgent or provide ` +
`'appium:webDriverAgentUrl' to run from '${platform}'.`);
}
if (!opts.udid || opts.udid.toLowerCase() === 'auto') {
throw new Error(`Running XCUITest from '${platform}' without macOS/Xcode requires an explicit real-device ` +
`'appium:udid'. Simulator discovery and automatic device selection require macOS.`);
}
if (opts.usePreinstalledWDA && !opts.webDriverAgentUrl && !opts.platformVersion) {
throw new Error(`Running preinstalled WebDriverAgent from '${platform}' requires 'appium:platformVersion' ` +
`so RemoteXPC eligibility can be checked without probing host Xcode or Simulator tools.`);
}
const xcodeOnlyCaps = XCODE_ONLY_CAPS.filter((capName) => Boolean(opts[capName]));
if (opts.usePreinstalledWDA && !opts.webDriverAgentUrl && xcodeOnlyCaps.length > 0) {
throw new Error(`The following capabilities require macOS/Xcode and cannot be used with the ` +
`RemoteXPC preinstalled WebDriverAgent strategy on '${platform}': ` +
xcodeOnlyCaps.join(', '));
}
}
/**
* Creates WebDriverAgent host operations provided by the XCUITest driver.
*/
function createWdaHostOps(driver) {
return {
simulator: createSimulatorHostOps(driver),
realDevicePreinstalled: createRealDevicePreinstalledHostOps(driver),
};
}
/**
* Verifies the selected WDA lifecycle can run on the current host platform.
*/
function assertWdaHostPlatformSupported(driver) {
if (process.platform === 'darwin') {
return;
}
assertWdaHostSessionCapsSupported(driver.opts);
if (driver.opts.webDriverAgentUrl) {
return;
}
if (!driver.isRealDevice()) {
throw new Error(`XCUITest simulator sessions require macOS with Xcode. ` +
`Use a real device with 'appium:usePreinstalledWDA' or provide 'appium:webDriverAgentUrl' ` +
`to run from '${process.platform}'.`);
}
if (!driver.opts.usePreinstalledWDA) {
throw new Error(`The default real-device WebDriverAgent startup strategy requires macOS with Xcode. ` +
`Use 'appium:usePreinstalledWDA' with a signed prebuilt WebDriverAgent or provide ` +
`'appium:webDriverAgentUrl' to run from '${process.platform}'.`);
}
if (driver.opts.platformVersion && !(0, utils_1.isIos18OrNewerPlatform)(driver.opts.platformVersion)) {
throw new Error(`Running preinstalled WebDriverAgent from '${process.platform}' requires a real device ` +
`with RemoteXPC tunnel support. The current platformVersion is ` +
`'${driver.opts.platformVersion}'; use iOS/tvOS 18.0 or newer, or provide ` +
`'appium:webDriverAgentUrl' for an externally managed WDA.`);
}
if (!driver.remoteXPCFacade.eligible) {
throw new Error(`RemoteXPC is required to launch preinstalled WebDriverAgent from '${process.platform}', ` +
`but this session is not eligible for RemoteXPC.`);
}
}
function stringifyLaunchEnvironment(env) {
return Object.entries(env).reduce((acc, [key, value]) => {
acc[key] = String(value);
return acc;
}, {});
}
function createSimulatorHostOps(driver) {
return {
async launchPreinstalled({ udid, bundleId, env }) {
await driver.device.simctl.exec('launch', {
args: ['--terminate-running-process', udid, bundleId],
env,
});
},
async terminate({ bundleId }) {
await driver.device.terminateApp(bundleId);
},
};
}
function createRealDevicePreinstalledHostOps(driver) {
return {
async launchPreinstalled({ udid, bundleId, env }) {
try {
const dvt = await driver.remoteXPCFacade.requireService('launch preinstalled WebDriverAgent', (Services) => Services.startDVTService(udid));
try {
await dvt.processControl.launch({
bundleId,
environment: stringifyLaunchEnvironment(env),
killExisting: true,
});
}
finally {
await dvt.dvtService.close();
}
}
catch (err) {
if (process.platform !== 'darwin') {
throw err;
}
driver.log.warn(`Failed to launch preinstalled WebDriverAgent via RemoteXPC. ` +
`Falling back to devicectl. Original error: ${err.message}`);
const { devicectl } = driver.device;
if (!devicectl) {
throw err;
}
await devicectl.launchApp(bundleId, {
env,
terminateExisting: true,
});
}
},
async terminate({ udid, bundleId }) {
try {
const dvt = await driver.remoteXPCFacade.requireService('terminate preinstalled WebDriverAgent', (Services) => Services.startDVTService(udid));
try {
const pid = await dvt.processControl.getPidForBundleIdentifier(bundleId);
if (!pid) {
driver.log.info(`The preinstalled WebDriverAgent process '${bundleId}' was not running`);
return;
}
await dvt.processControl.kill(pid);
}
finally {
await dvt.dvtService.close();
}
}
catch (err) {
if (process.platform !== 'darwin') {
throw err;
}
driver.log.warn(`Failed to terminate preinstalled WebDriverAgent via RemoteXPC. ` +
`Falling back to devicectl. Original error: ${err.message}`);
const { devicectl } = driver.device;
if (!devicectl) {
throw err;
}
await devicectl.terminateApp(bundleId);
}
},
};
}
//# sourceMappingURL=wda-host-ops.js.map