UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

136 lines 4.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NotificationClient = void 0; const remotexpc_utils_1 = require("./remotexpc-utils"); const appium_ios_device_1 = require("appium-ios-device"); /** * Unified Notification Proxy Client * * Provides a unified interface for notification proxy operations on iOS devices, * automatically handling the differences between iOS < 18 (appium-ios-device) * and iOS 18 and above (appium-ios-remotexpc NotificationProxyService). */ class NotificationClient { service; remoteXPCConnection; log; constructor(service, log, remoteXPCConnection) { this.service = service; this.log = log; this.remoteXPCConnection = remoteXPCConnection; } /** * Check if this client is using RemoteXPC */ get isRemoteXPC() { return !!this.remoteXPCConnection; } /** * Get service as RemoteXPC NotificationProxyService */ get remoteXPCNotificationProxy() { return this.service; } /** * Get service as iOS Device NotificationProxy */ get iosDeviceNotificationProxy() { return this.service; } /** * Create a notification client for device * * @param udid - Device UDID * @param log - Appium logger instance * @param useRemoteXPC - Whether to use remotexpc (use isIos18OrNewer(opts) to determine) * @returns NotificationClient instance */ static async create(udid, log, useRemoteXPC) { if (useRemoteXPC) { const client = await NotificationClient.withRemoteXpcConnection(async () => { const Services = await (0, remotexpc_utils_1.getRemoteXPCServices)(); const { notificationProxyService, remoteXPC } = await Services.startNotificationProxyService(udid); return { service: notificationProxyService, connection: remoteXPC, }; }, log); if (client) { return client; } } // Fallback to appium-ios-device const notificationProxy = await appium_ios_device_1.services.startNotificationProxyService(udid); return new NotificationClient(notificationProxy, log); } /** * Helper to safely execute remoteXPC operations with connection cleanup * @param operation - Async operation that returns service and connection * @param log - Logger instance * @returns NotificationClient on success, null on failure */ static async withRemoteXpcConnection(operation, log) { let remoteXPCConnection; let succeeded = false; try { const { service, connection } = await operation(); remoteXPCConnection = connection; const client = new NotificationClient(service, log, remoteXPCConnection); succeeded = true; return client; } catch (err) { log.error(`Failed to create notification client via RemoteXPC: ${err.message}, falling back to appium-ios-device`); return null; } finally { // Only close connection if we failed (if succeeded, the client owns it) if (remoteXPCConnection && !succeeded) { try { await remoteXPCConnection.close(); } catch { // Ignore cleanup errors } } } } /** * Observe a specific notification and wait for it * * @param notificationName - Name of the notification to observe * @returns Promise that resolves when the notification is received */ async observeNotification(notificationName) { if (this.isRemoteXPC) { await this.remoteXPCNotificationProxy.observe(notificationName); } else { // iOS Device: Use callback-based observation wrapped in a promise return new Promise((resolve) => { this.iosDeviceNotificationProxy.observeNotification(notificationName, { notification: resolve, }); }); } } /** * Close the notification service connection and remoteXPC connection if present */ async close() { // Close the service first this.service.close(); // Then close RemoteXPC connection if present if (this.remoteXPCConnection) { try { this.log.debug(`Closing remoteXPC connection`); await this.remoteXPCConnection.close(); } catch (err) { this.log.debug(`Error closing remoteXPC connection: ${err.message}`); } } } } exports.NotificationClient = NotificationClient; //# sourceMappingURL=notification-client.js.map