appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
108 lines • 4.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppTerminationClient = void 0;
const appium_ios_device_1 = require("appium-ios-device");
const utils_1 = require("../utils");
const installation_proxy_client_1 = require("./installation-proxy-client");
class AppTerminationClient {
udid;
platformVersion;
devicectl;
log;
remoteXPCFacade;
constructor(udid, platformVersion, devicectl, log, remoteXPCFacade = null) {
this.udid = udid;
this.platformVersion = platformVersion;
this.devicectl = devicectl;
this.log = log;
this.remoteXPCFacade = remoteXPCFacade;
}
async terminate(bundleId) {
let result = (await this.remoteXPCFacade?.attemptService(`terminate '${bundleId}'`, async (Services) => {
const dvt = await Services.startDVTService(this.udid);
try {
const pid = await dvt.processControl.getPidForBundleIdentifier(bundleId);
if (!pid) {
return { terminated: false, reason: 'not_running' };
}
await dvt.processControl.kill(pid);
return { terminated: true, pid };
}
finally {
await dvt.dvtService.close();
}
})) ?? null;
if (!result) {
result = await this.terminateLegacy(bundleId);
}
if (result.terminated) {
this.log.debug(`Killed process for '${bundleId}' app with PID ${result.pid}`);
return true;
}
switch (result.reason) {
case 'not_running':
this.log.info(`The process of '${bundleId}' app was not running`);
break;
case 'error':
this.log.warn(`Failed to kill '${bundleId}'. Original error: ${result.detail ?? 'unknown'}`);
break;
}
return false;
}
async terminateLegacy(bundleId) {
let instrumentService;
let installProxyClient;
try {
installProxyClient = await installation_proxy_client_1.InstallationProxyClient.create(this.udid);
const apps = await installProxyClient.listApplications({
returnAttributes: ['CFBundleIdentifier', 'CFBundleExecutable'],
});
if (!apps[bundleId]) {
return { terminated: false, reason: 'not_running' };
}
const executableName = apps[bundleId].CFBundleExecutable;
this.log.debug(`The executable name for the bundle id '${bundleId}' was '${executableName}'`);
if ((0, utils_1.isIos17OrNewerPlatform)(this.platformVersion)) {
if (process.platform !== 'darwin') {
return {
terminated: false,
reason: 'error',
detail: `devicectl is only available on macOS; cannot terminate '${bundleId}' via devicectl from '${process.platform}'`,
};
}
this.log.debug(`Calling devicectl to kill the process`);
const pids = (await this.devicectl.listProcesses())
.filter(({ executable }) => executable.endsWith(`/${executableName}`))
.map(({ processIdentifier }) => processIdentifier);
if ((0, utils_1.isEmpty)(pids)) {
return { terminated: false, reason: 'not_running' };
}
await this.devicectl.sendSignalToProcess(pids[0], 2);
return { terminated: true, pid: pids[0] };
}
// iOS < 17: use instrument service
instrumentService = await appium_ios_device_1.services.startInstrumentService(this.udid);
const processes = await instrumentService.callChannel(appium_ios_device_1.INSTRUMENT_CHANNEL.DEVICE_INFO, 'runningProcesses');
const matchingProcess = processes.selector.find((proc) => proc.name === executableName);
if (!matchingProcess) {
return { terminated: false, reason: 'not_running' };
}
await instrumentService.callChannel(appium_ios_device_1.INSTRUMENT_CHANNEL.PROCESS_CONTROL, 'killPid:', `${matchingProcess.pid}`);
return { terminated: true, pid: matchingProcess.pid };
}
catch (err) {
const detail = err.stderr ?? err.message;
return { terminated: false, reason: 'error', detail: String(detail) };
}
finally {
if (installProxyClient) {
await installProxyClient.close();
}
if (instrumentService) {
instrumentService.close();
}
}
}
}
exports.AppTerminationClient = AppTerminationClient;
//# sourceMappingURL=app-termination-client.js.map