appium-xcuitest-driver 10.8.3 → 10.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/lib/app-utils.d.ts +2 -2
- package/build/lib/app-utils.d.ts.map +1 -1
- package/build/lib/app-utils.js +4 -1
- package/build/lib/app-utils.js.map +1 -1
- package/build/lib/commands/app-management.js +2 -2
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/appearance.js +2 -2
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/biometric.js +3 -3
- package/build/lib/commands/biometric.js.map +1 -1
- package/build/lib/commands/certificate.d.ts.map +1 -1
- package/build/lib/commands/certificate.js +9 -3
- package/build/lib/commands/certificate.js.map +1 -1
- package/build/lib/commands/context.d.ts +5 -5
- package/build/lib/commands/context.d.ts.map +1 -1
- package/build/lib/commands/context.js +6 -6
- package/build/lib/commands/context.js.map +1 -1
- package/build/lib/commands/file-movement.d.ts.map +1 -1
- package/build/lib/commands/file-movement.js +7 -7
- package/build/lib/commands/file-movement.js.map +1 -1
- package/build/lib/commands/general.js +1 -1
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/gesture.js +1 -1
- package/build/lib/commands/gesture.js.map +1 -1
- package/build/lib/commands/keychains.js +1 -1
- package/build/lib/commands/keychains.js.map +1 -1
- package/build/lib/commands/localization.js +1 -1
- package/build/lib/commands/localization.js.map +1 -1
- package/build/lib/commands/location.js +1 -1
- package/build/lib/commands/location.js.map +1 -1
- package/build/lib/commands/log.js +7 -7
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/memory.js +1 -1
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/notifications.js +1 -1
- package/build/lib/commands/notifications.js.map +1 -1
- package/build/lib/commands/pasteboard.js +2 -2
- package/build/lib/commands/pasteboard.js.map +1 -1
- package/build/lib/commands/pcap.js +1 -1
- package/build/lib/commands/pcap.js.map +1 -1
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +13 -4
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.js +2 -2
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/proxy-helper.d.ts.map +1 -1
- package/build/lib/commands/proxy-helper.js +0 -3
- package/build/lib/commands/proxy-helper.js.map +1 -1
- package/build/lib/commands/screenshots.js +1 -1
- package/build/lib/commands/screenshots.js.map +1 -1
- package/build/lib/commands/simctl.d.ts +1 -1
- package/build/lib/commands/simctl.d.ts.map +1 -1
- package/build/lib/commands/simctl.js +1 -1
- package/build/lib/commands/simctl.js.map +1 -1
- package/build/lib/commands/web.js +1 -1
- package/build/lib/commands/web.js.map +1 -1
- package/build/lib/commands/xctest-record-screen.js +2 -2
- package/build/lib/commands/xctest-record-screen.js.map +1 -1
- package/build/lib/desired-caps.d.ts +383 -507
- package/build/lib/desired-caps.d.ts.map +1 -1
- package/build/lib/desired-caps.js +6 -10
- package/build/lib/desired-caps.js.map +1 -1
- package/build/lib/device/clients/base-device-client.d.ts.map +1 -0
- package/build/lib/device/clients/base-device-client.js.map +1 -0
- package/build/lib/{real-device-clients → device/clients}/py-ios-device-client.d.ts +1 -1
- package/build/lib/device/clients/py-ios-device-client.d.ts.map +1 -0
- package/build/lib/device/clients/py-ios-device-client.js.map +1 -0
- package/build/lib/device/device-connections-factory.d.ts +18 -0
- package/build/lib/device/device-connections-factory.d.ts.map +1 -0
- package/build/lib/{device-connections-factory.js → device/device-connections-factory.js} +57 -41
- package/build/lib/device/device-connections-factory.js.map +1 -0
- package/build/lib/{device-log → device/log}/helpers.d.ts +1 -1
- package/build/lib/device/log/helpers.d.ts.map +1 -0
- package/build/lib/device/log/helpers.js.map +1 -0
- package/build/lib/{device-log → device/log}/ios-crash-log.d.ts +1 -1
- package/build/lib/device/log/ios-crash-log.d.ts.map +1 -0
- package/build/lib/{device-log → device/log}/ios-crash-log.js +1 -1
- package/build/lib/device/log/ios-crash-log.js.map +1 -0
- package/build/lib/device/log/ios-device-log.d.ts.map +1 -0
- package/build/lib/device/log/ios-device-log.js.map +1 -0
- package/build/lib/{device-log → device/log}/ios-log.d.ts +1 -1
- package/build/lib/device/log/ios-log.d.ts.map +1 -0
- package/build/lib/device/log/ios-log.js.map +1 -0
- package/build/lib/device/log/ios-performance-log.d.ts.map +1 -0
- package/build/lib/device/log/ios-performance-log.js.map +1 -0
- package/build/lib/device/log/ios-simulator-log.d.ts.map +1 -0
- package/build/lib/device/log/ios-simulator-log.js.map +1 -0
- package/build/lib/{device-log → device/log}/line-consuming-log.d.ts +1 -1
- package/build/lib/device/log/line-consuming-log.d.ts.map +1 -0
- package/build/lib/device/log/line-consuming-log.js.map +1 -0
- package/build/lib/{device-log → device/log}/safari-console-log.d.ts +1 -1
- package/build/lib/device/log/safari-console-log.d.ts.map +1 -0
- package/build/lib/device/log/safari-console-log.js.map +1 -0
- package/build/lib/device/log/safari-network-log.d.ts.map +1 -0
- package/build/lib/device/log/safari-network-log.js.map +1 -0
- package/build/lib/device/real-device-management.d.ts +146 -0
- package/build/lib/device/real-device-management.d.ts.map +1 -0
- package/build/lib/device/real-device-management.js +728 -0
- package/build/lib/device/real-device-management.js.map +1 -0
- package/build/lib/device/simulator-management.d.ts +65 -0
- package/build/lib/device/simulator-management.d.ts.map +1 -0
- package/build/lib/{simulator-management.js → device/simulator-management.js} +24 -43
- package/build/lib/device/simulator-management.js.map +1 -0
- package/build/lib/driver.d.ts +129 -1385
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +476 -600
- package/build/lib/driver.js.map +1 -1
- package/build/lib/method-map.d.ts +1 -1
- package/build/lib/method-map.d.ts.map +1 -1
- package/build/lib/method-map.js +2 -2
- package/build/lib/method-map.js.map +1 -1
- package/lib/app-utils.js +5 -1
- package/lib/commands/app-management.js +2 -2
- package/lib/commands/appearance.js +2 -2
- package/lib/commands/biometric.js +3 -3
- package/lib/commands/certificate.js +9 -3
- package/lib/commands/context.js +6 -6
- package/lib/commands/file-movement.js +11 -7
- package/lib/commands/general.js +1 -1
- package/lib/commands/gesture.js +1 -1
- package/lib/commands/keychains.js +1 -1
- package/lib/commands/localization.js +1 -1
- package/lib/commands/location.js +1 -1
- package/lib/commands/log.js +7 -7
- package/lib/commands/memory.js +1 -1
- package/lib/commands/notifications.js +1 -1
- package/lib/commands/pasteboard.js +2 -2
- package/lib/commands/pcap.js +1 -1
- package/lib/commands/performance.js +12 -1
- package/lib/commands/permissions.js +2 -2
- package/lib/commands/proxy-helper.js +0 -3
- package/lib/commands/screenshots.js +1 -1
- package/lib/commands/simctl.js +1 -1
- package/lib/commands/web.js +1 -1
- package/lib/commands/xctest-record-screen.js +2 -2
- package/lib/{desired-caps.js → desired-caps.ts} +7 -6
- package/lib/{real-device-clients → device/clients}/py-ios-device-client.ts +1 -1
- package/lib/{device-connections-factory.js → device/device-connections-factory.ts} +96 -60
- package/lib/{device-log → device/log}/helpers.ts +1 -1
- package/lib/{device-log → device/log}/ios-crash-log.ts +3 -3
- package/lib/{device-log → device/log}/ios-log.ts +1 -1
- package/lib/{device-log → device/log}/line-consuming-log.ts +1 -1
- package/lib/{device-log → device/log}/safari-console-log.ts +1 -1
- package/lib/device/real-device-management.ts +819 -0
- package/lib/{simulator-management.js → device/simulator-management.ts} +69 -62
- package/lib/{driver.js → driver.ts} +619 -713
- package/lib/{method-map.js → method-map.ts} +5 -2
- package/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
- package/build/lib/device-connections-factory.d.ts +0 -13
- package/build/lib/device-connections-factory.d.ts.map +0 -1
- package/build/lib/device-connections-factory.js.map +0 -1
- package/build/lib/device-log/helpers.d.ts.map +0 -1
- package/build/lib/device-log/helpers.js.map +0 -1
- package/build/lib/device-log/ios-crash-log.d.ts.map +0 -1
- package/build/lib/device-log/ios-crash-log.js.map +0 -1
- package/build/lib/device-log/ios-device-log.d.ts.map +0 -1
- package/build/lib/device-log/ios-device-log.js.map +0 -1
- package/build/lib/device-log/ios-log.d.ts.map +0 -1
- package/build/lib/device-log/ios-log.js.map +0 -1
- package/build/lib/device-log/ios-performance-log.d.ts.map +0 -1
- package/build/lib/device-log/ios-performance-log.js.map +0 -1
- package/build/lib/device-log/ios-simulator-log.d.ts.map +0 -1
- package/build/lib/device-log/ios-simulator-log.js.map +0 -1
- package/build/lib/device-log/line-consuming-log.d.ts.map +0 -1
- package/build/lib/device-log/line-consuming-log.js.map +0 -1
- package/build/lib/device-log/safari-console-log.d.ts.map +0 -1
- package/build/lib/device-log/safari-console-log.js.map +0 -1
- package/build/lib/device-log/safari-network-log.d.ts.map +0 -1
- package/build/lib/device-log/safari-network-log.js.map +0 -1
- package/build/lib/ios-fs-helpers.d.ts +0 -75
- package/build/lib/ios-fs-helpers.d.ts.map +0 -1
- package/build/lib/ios-fs-helpers.js +0 -370
- package/build/lib/ios-fs-helpers.js.map +0 -1
- package/build/lib/real-device-clients/base-device-client.d.ts.map +0 -1
- package/build/lib/real-device-clients/base-device-client.js.map +0 -1
- package/build/lib/real-device-clients/py-ios-device-client.d.ts.map +0 -1
- package/build/lib/real-device-clients/py-ios-device-client.js.map +0 -1
- package/build/lib/real-device-management.d.ts +0 -53
- package/build/lib/real-device-management.d.ts.map +0 -1
- package/build/lib/real-device-management.js +0 -128
- package/build/lib/real-device-management.js.map +0 -1
- package/build/lib/real-device.d.ts +0 -112
- package/build/lib/real-device.d.ts.map +0 -1
- package/build/lib/real-device.js +0 -352
- package/build/lib/real-device.js.map +0 -1
- package/build/lib/simulator-management.d.ts +0 -96
- package/build/lib/simulator-management.d.ts.map +0 -1
- package/build/lib/simulator-management.js.map +0 -1
- package/build/lib/xcrun.d.ts +0 -3
- package/build/lib/xcrun.d.ts.map +0 -1
- package/build/lib/xcrun.js +0 -17
- package/build/lib/xcrun.js.map +0 -1
- package/lib/ios-fs-helpers.js +0 -355
- package/lib/real-device-management.js +0 -133
- package/lib/real-device.js +0 -347
- package/lib/xcrun.js +0 -16
- /package/build/lib/{real-device-clients → device/clients}/base-device-client.d.ts +0 -0
- /package/build/lib/{real-device-clients → device/clients}/base-device-client.js +0 -0
- /package/build/lib/{real-device-clients → device/clients}/py-ios-device-client.js +0 -0
- /package/build/lib/{device-log → device/log}/helpers.js +0 -0
- /package/build/lib/{device-log → device/log}/ios-device-log.d.ts +0 -0
- /package/build/lib/{device-log → device/log}/ios-device-log.js +0 -0
- /package/build/lib/{device-log → device/log}/ios-log.js +0 -0
- /package/build/lib/{device-log → device/log}/ios-performance-log.d.ts +0 -0
- /package/build/lib/{device-log → device/log}/ios-performance-log.js +0 -0
- /package/build/lib/{device-log → device/log}/ios-simulator-log.d.ts +0 -0
- /package/build/lib/{device-log → device/log}/ios-simulator-log.js +0 -0
- /package/build/lib/{device-log → device/log}/line-consuming-log.js +0 -0
- /package/build/lib/{device-log → device/log}/safari-console-log.js +0 -0
- /package/build/lib/{device-log → device/log}/safari-network-log.d.ts +0 -0
- /package/build/lib/{device-log → device/log}/safari-network-log.js +0 -0
- /package/lib/{real-device-clients → device/clients}/base-device-client.ts +0 -0
- /package/lib/{device-log → device/log}/ios-device-log.ts +0 -0
- /package/lib/{device-log → device/log}/ios-performance-log.ts +0 -0
- /package/lib/{device-log → device/log}/ios-simulator-log.ts +0 -0
- /package/lib/{device-log → device/log}/safari-network-log.ts +0 -0
package/build/lib/driver.js
CHANGED
|
@@ -98,13 +98,12 @@ const xctestCommands = __importStar(require("./commands/xctest"));
|
|
|
98
98
|
const xctestRecordScreenCommands = __importStar(require("./commands/xctest-record-screen"));
|
|
99
99
|
const increaseContrastCommands = __importStar(require("./commands/increase-contrast"));
|
|
100
100
|
const desired_caps_1 = require("./desired-caps");
|
|
101
|
-
const device_connections_factory_1 = require("./device-connections-factory");
|
|
101
|
+
const device_connections_factory_1 = require("./device/device-connections-factory");
|
|
102
102
|
const execute_method_map_1 = require("./execute-method-map");
|
|
103
103
|
const method_map_1 = require("./method-map");
|
|
104
|
-
const py_ios_device_client_1 = require("./
|
|
105
|
-
const real_device_management_1 = require("./real-device-management");
|
|
106
|
-
const
|
|
107
|
-
const simulator_management_1 = require("./simulator-management");
|
|
104
|
+
const py_ios_device_client_1 = require("./device/clients/py-ios-device-client");
|
|
105
|
+
const real_device_management_1 = require("./device/real-device-management");
|
|
106
|
+
const simulator_management_1 = require("./device/simulator-management");
|
|
108
107
|
const utils_1 = require("./utils");
|
|
109
108
|
const app_infos_cache_1 = require("./app-infos-cache");
|
|
110
109
|
const context_1 = require("./commands/context");
|
|
@@ -147,7 +146,6 @@ const WEB_ELEMENTS_CACHE_SIZE = 500;
|
|
|
147
146
|
const SUPPORTED_ORIENATIONS = ['LANDSCAPE', 'PORTRAIT'];
|
|
148
147
|
const DEFAULT_MJPEG_SERVER_PORT = 9100;
|
|
149
148
|
/* eslint-disable no-useless-escape */
|
|
150
|
-
/** @type {import('@appium/types').RouteMatcher[]} */
|
|
151
149
|
const NO_PROXY_NATIVE_LIST = [
|
|
152
150
|
['DELETE', /window/],
|
|
153
151
|
['GET', /^\/session\/[^\/]+$/],
|
|
@@ -194,7 +192,7 @@ const NO_PROXY_NATIVE_LIST = [
|
|
|
194
192
|
['GET', /cookie/],
|
|
195
193
|
['POST', /cookie/],
|
|
196
194
|
];
|
|
197
|
-
const NO_PROXY_WEB_LIST =
|
|
195
|
+
const NO_PROXY_WEB_LIST = [
|
|
198
196
|
['GET', /attribute/],
|
|
199
197
|
['GET', /element/],
|
|
200
198
|
['GET', /text/],
|
|
@@ -206,89 +204,55 @@ const NO_PROXY_WEB_LIST = /** @type {import('@appium/types').RouteMatcher[]} */
|
|
|
206
204
|
['POST', /frame/],
|
|
207
205
|
['POST', /keys/],
|
|
208
206
|
['POST', /refresh/],
|
|
209
|
-
|
|
207
|
+
...NO_PROXY_NATIVE_LIST,
|
|
208
|
+
];
|
|
210
209
|
/* eslint-enable no-useless-escape */
|
|
211
210
|
const MEMOIZED_FUNCTIONS = ['getStatusBarHeight', 'getDevicePixelRatio', 'getScreenInfo'];
|
|
212
211
|
// Capabilities that do not have xcodebuild process
|
|
213
212
|
const CAP_NAMES_NO_XCODEBUILD_REQUIRED = ['webDriverAgentUrl', 'usePreinstalledWDA'];
|
|
214
213
|
const BUNDLE_VERSION_PATTERN = /CFBundleVersion\s+=\s+"?([^(;|")]+)/;
|
|
215
|
-
/**
|
|
216
|
-
* @implements {ExternalDriver<XCUITestDriverConstraints, FullContext|string>}
|
|
217
|
-
* @extends {BaseDriver<XCUITestDriverConstraints>}
|
|
218
|
-
* @privateRemarks **This class should be considered "final"**. It cannot be extended
|
|
219
|
-
* due to use of public class field assignments. If extending this class becomes a hard requirement, refer to the implementation of `BaseDriver` on how to do so.
|
|
220
|
-
*/
|
|
221
214
|
class XCUITestDriver extends driver_1.BaseDriver {
|
|
222
215
|
static newMethodMap = method_map_1.newMethodMap;
|
|
223
216
|
static executeMethodMap = execute_method_map_1.executeMethodMap;
|
|
224
|
-
/** @type {string|null|undefined} */
|
|
225
217
|
curWindowHandle;
|
|
226
|
-
/**
|
|
227
|
-
* @type {boolean|undefined}
|
|
228
|
-
*/
|
|
229
218
|
selectingNewPage;
|
|
230
|
-
/** @type {string[]} */
|
|
231
219
|
contexts;
|
|
232
|
-
/** @type {string|null} */
|
|
233
220
|
curContext;
|
|
234
|
-
/** @type {string[]} */
|
|
235
221
|
curWebFrames;
|
|
236
|
-
/** @type {import('./types').CalibrationData|null} */
|
|
237
222
|
webviewCalibrationResult;
|
|
238
|
-
/** @type {import('./types').AsyncPromise|undefined} */
|
|
239
223
|
asyncPromise;
|
|
240
|
-
/** @type {number|undefined} */
|
|
241
224
|
asyncWaitMs;
|
|
242
|
-
/** @type {((logRecord: {message: string}) => void)|null} */
|
|
243
225
|
_syslogWebsocketListener;
|
|
244
|
-
/** @type {import('./commands/performance').PerfRecorder[]} */
|
|
245
226
|
_perfRecorders;
|
|
246
|
-
/** @type {LRUCache} */
|
|
247
227
|
webElementsCache;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
* @privateRemarks needs types
|
|
251
|
-
**/
|
|
252
|
-
_conditionInducerService;
|
|
253
|
-
/**
|
|
254
|
-
* @type {import('./commands/condition.js').DVTServiceWithConnection|null}
|
|
255
|
-
* @privateRemarks RemoteXPC DVT connection for iOS>=18 condition inducer
|
|
256
|
-
**/
|
|
257
|
-
_remoteXPCConditionInducerConnection;
|
|
258
|
-
/** @type {boolean|undefined} */
|
|
228
|
+
_conditionInducerService; // needs types
|
|
229
|
+
_remoteXPCConditionInducerConnection; // RemoteXPC DVT connection for iOS>=18 condition inducer
|
|
259
230
|
_isSafariIphone;
|
|
260
|
-
/** @type {boolean|undefined} */
|
|
261
231
|
_isSafariNotched;
|
|
262
|
-
/** @type {import('./commands/types').WaitingAtoms} */
|
|
263
232
|
_waitingAtoms;
|
|
264
|
-
/** @type {import('./types').LifecycleData} */
|
|
265
233
|
lifecycleData;
|
|
266
|
-
/** @type {import('./commands/record-audio').AudioRecorder|null} */
|
|
267
234
|
_audioRecorder;
|
|
268
|
-
/** @type {XcodeVersion|undefined} */
|
|
269
235
|
xcodeVersion;
|
|
270
|
-
/** @type {import('./commands/pcap').TrafficCapture|null} */
|
|
271
236
|
_trafficCapture;
|
|
272
|
-
/** @type {import('./commands/recordscreen').ScreenRecorder|null} */
|
|
273
237
|
_recentScreenRecorder;
|
|
274
|
-
/** @type {Simulator|RealDevice} */
|
|
275
238
|
_device;
|
|
276
|
-
/** @type {string|null} */
|
|
277
239
|
_iosSdkVersion;
|
|
278
|
-
|
|
279
|
-
wda;
|
|
280
|
-
/** @type {import('appium-remote-debugger').RemoteDebugger|null} */
|
|
240
|
+
_wda;
|
|
281
241
|
remote;
|
|
282
|
-
/** @type {DriverLogs} */
|
|
283
242
|
logs;
|
|
284
|
-
/** @type {import('./commands/types').LogListener|undefined} */
|
|
285
243
|
_bidiServerLogListener;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
244
|
+
// Additional properties that were missing
|
|
245
|
+
appInfosCache;
|
|
246
|
+
doesSupportBidi;
|
|
247
|
+
jwpProxyActive;
|
|
248
|
+
proxyReqRes;
|
|
249
|
+
safari;
|
|
250
|
+
cachedWdaStatus;
|
|
251
|
+
_currentUrl;
|
|
252
|
+
pageLoadMs;
|
|
253
|
+
landscapeWebCoordsOffset;
|
|
254
|
+
mjpegStream;
|
|
255
|
+
constructor(opts, shouldValidateCaps = true) {
|
|
292
256
|
super(opts, shouldValidateCaps);
|
|
293
257
|
this.locatorStrategies = [
|
|
294
258
|
'xpath',
|
|
@@ -332,7 +296,295 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
332
296
|
this.appInfosCache = new app_infos_cache_1.AppInfosCache(this.log);
|
|
333
297
|
this.remote = null;
|
|
334
298
|
this.doesSupportBidi = true;
|
|
299
|
+
this._wda = null;
|
|
300
|
+
}
|
|
301
|
+
// Override methods from BaseDriver
|
|
302
|
+
async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
|
|
303
|
+
try {
|
|
304
|
+
const [sessionId, initialCaps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
|
|
305
|
+
let caps = initialCaps;
|
|
306
|
+
// merge cli args to opts, and if we did merge any, revalidate opts to ensure the final set
|
|
307
|
+
// is also consistent
|
|
308
|
+
if (this.mergeCliArgsToOpts()) {
|
|
309
|
+
this.validateDesiredCaps({ ...caps, ...this.cliArgs });
|
|
310
|
+
}
|
|
311
|
+
await this.start();
|
|
312
|
+
// merge server capabilities + desired capabilities
|
|
313
|
+
caps = { ...defaultServerCaps, ...caps };
|
|
314
|
+
// update the udid with what is actually used
|
|
315
|
+
caps.udid = this.opts.udid;
|
|
316
|
+
// ensure we track nativeWebTap capability as a setting as well
|
|
317
|
+
if (lodash_1.default.has(this.opts, 'nativeWebTap')) {
|
|
318
|
+
await this.updateSettings({ nativeWebTap: this.opts.nativeWebTap });
|
|
319
|
+
}
|
|
320
|
+
// ensure we track nativeWebTapStrict capability as a setting as well
|
|
321
|
+
if (lodash_1.default.has(this.opts, 'nativeWebTapStrict')) {
|
|
322
|
+
await this.updateSettings({ nativeWebTapStrict: this.opts.nativeWebTapStrict });
|
|
323
|
+
}
|
|
324
|
+
// ensure we track useJSONSource capability as a setting as well
|
|
325
|
+
if (lodash_1.default.has(this.opts, 'useJSONSource')) {
|
|
326
|
+
await this.updateSettings({ useJSONSource: this.opts.useJSONSource });
|
|
327
|
+
}
|
|
328
|
+
const wdaSettings = {
|
|
329
|
+
elementResponseAttributes: DEFAULT_SETTINGS.elementResponseAttributes,
|
|
330
|
+
shouldUseCompactResponses: DEFAULT_SETTINGS.shouldUseCompactResponses,
|
|
331
|
+
};
|
|
332
|
+
if ('elementResponseAttributes' in this.opts && lodash_1.default.isString(this.opts.elementResponseAttributes)) {
|
|
333
|
+
wdaSettings.elementResponseAttributes = this.opts.elementResponseAttributes;
|
|
334
|
+
}
|
|
335
|
+
if ('shouldUseCompactResponses' in this.opts && lodash_1.default.isBoolean(this.opts.shouldUseCompactResponses)) {
|
|
336
|
+
wdaSettings.shouldUseCompactResponses = this.opts.shouldUseCompactResponses;
|
|
337
|
+
}
|
|
338
|
+
if ('mjpegServerScreenshotQuality' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerScreenshotQuality)) {
|
|
339
|
+
wdaSettings.mjpegServerScreenshotQuality = this.opts.mjpegServerScreenshotQuality;
|
|
340
|
+
}
|
|
341
|
+
if ('mjpegServerFramerate' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerFramerate)) {
|
|
342
|
+
wdaSettings.mjpegServerFramerate = this.opts.mjpegServerFramerate;
|
|
343
|
+
}
|
|
344
|
+
if (lodash_1.default.has(this.opts, 'screenshotQuality')) {
|
|
345
|
+
this.log.info(`Setting the quality of phone screenshot: '${this.opts.screenshotQuality}'`);
|
|
346
|
+
wdaSettings.screenshotQuality = this.opts.screenshotQuality;
|
|
347
|
+
}
|
|
348
|
+
// ensure WDA gets our defaults instead of whatever its own might be
|
|
349
|
+
await this.updateSettings(wdaSettings);
|
|
350
|
+
await this.handleMjpegOptions();
|
|
351
|
+
return [
|
|
352
|
+
sessionId,
|
|
353
|
+
caps,
|
|
354
|
+
];
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
this.log.error(JSON.stringify(e));
|
|
358
|
+
await this.deleteSession();
|
|
359
|
+
throw e;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async deleteSession(sessionId) {
|
|
363
|
+
await utils_1.removeAllSessionWebSocketHandlers.bind(this)();
|
|
364
|
+
for (const recorder of lodash_1.default.compact([
|
|
365
|
+
this._recentScreenRecorder,
|
|
366
|
+
this._audioRecorder,
|
|
367
|
+
this._trafficCapture,
|
|
368
|
+
])) {
|
|
369
|
+
await recorder.interrupt(true);
|
|
370
|
+
await recorder.cleanup();
|
|
371
|
+
}
|
|
372
|
+
if (!lodash_1.default.isEmpty(this._perfRecorders)) {
|
|
373
|
+
await bluebird_1.default.all(this._perfRecorders.map((x) => x.stop(true)));
|
|
374
|
+
this._perfRecorders = [];
|
|
375
|
+
}
|
|
376
|
+
if (this._conditionInducerService || this._remoteXPCConditionInducerConnection) {
|
|
377
|
+
try {
|
|
378
|
+
await this.disableConditionInducer();
|
|
379
|
+
}
|
|
380
|
+
catch (err) {
|
|
381
|
+
this.log.warn(`Cannot disable condition inducer: ${err.message}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
await this.stop();
|
|
385
|
+
if (this._wda && this.isXcodebuildNeeded()) {
|
|
386
|
+
if (this.opts.clearSystemFiles) {
|
|
387
|
+
let synchronizationKey = XCUITestDriver.name;
|
|
388
|
+
const derivedDataPath = await this.wda.retrieveDerivedDataPath();
|
|
389
|
+
if (derivedDataPath) {
|
|
390
|
+
synchronizationKey = node_path_1.default.normalize(derivedDataPath);
|
|
391
|
+
}
|
|
392
|
+
await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
|
|
393
|
+
await (0, utils_1.clearSystemFiles)(this.wda);
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
this.log.debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.');
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (this.remote) {
|
|
401
|
+
this.log.debug('Found a remote debugger session. Removing...');
|
|
402
|
+
await this.stopRemote();
|
|
403
|
+
}
|
|
404
|
+
if (this.opts.resetOnSessionStartOnly === false) {
|
|
405
|
+
await this.runReset(true);
|
|
406
|
+
}
|
|
407
|
+
const simulatorDevice = this.isSimulator() ? this.device : null;
|
|
408
|
+
if (simulatorDevice && this.lifecycleData.createSim) {
|
|
409
|
+
this.log.debug(`Deleting simulator created for this run (udid: '${simulatorDevice.udid}')`);
|
|
410
|
+
await simulator_management_1.shutdownSimulator.bind(this)();
|
|
411
|
+
await simulatorDevice.delete();
|
|
412
|
+
}
|
|
413
|
+
const shouldResetLocationService = this.isRealDevice() && !!this.opts.resetLocationService;
|
|
414
|
+
if (shouldResetLocationService) {
|
|
415
|
+
try {
|
|
416
|
+
await this.mobileResetLocationService();
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
/* Ignore this error since mobileResetLocationService already logged the error */
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
await this.logs.syslog?.stopCapture();
|
|
423
|
+
lodash_1.default.values(this.logs).forEach((x) => x?.removeAllListeners?.());
|
|
424
|
+
if (this._bidiServerLogListener) {
|
|
425
|
+
this.log.unwrap().off('log', this._bidiServerLogListener);
|
|
426
|
+
}
|
|
427
|
+
this.logs = {};
|
|
428
|
+
if (this.mjpegStream) {
|
|
429
|
+
this.log.info('Closing MJPEG stream');
|
|
430
|
+
this.mjpegStream.stop();
|
|
431
|
+
}
|
|
432
|
+
this.resetIos();
|
|
433
|
+
await super.deleteSession(sessionId);
|
|
434
|
+
}
|
|
435
|
+
async executeCommand(cmd, ...args) {
|
|
436
|
+
this.log.debug(`Executing command '${cmd}'`);
|
|
437
|
+
if (cmd === 'receiveAsyncResponse') {
|
|
438
|
+
return await this.receiveAsyncResponse(...args);
|
|
439
|
+
}
|
|
440
|
+
// TODO: once this fix gets into base driver remove from here
|
|
441
|
+
if (cmd === 'getStatus') {
|
|
442
|
+
return await this.getStatus();
|
|
443
|
+
}
|
|
444
|
+
return await super.executeCommand(cmd, ...args);
|
|
445
|
+
}
|
|
446
|
+
proxyActive() {
|
|
447
|
+
return Boolean(this.jwpProxyActive);
|
|
448
|
+
}
|
|
449
|
+
getProxyAvoidList() {
|
|
450
|
+
if (this.isWebview()) {
|
|
451
|
+
return NO_PROXY_WEB_LIST;
|
|
452
|
+
}
|
|
453
|
+
return NO_PROXY_NATIVE_LIST;
|
|
454
|
+
}
|
|
455
|
+
canProxy() {
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
validateLocatorStrategy(strategy) {
|
|
459
|
+
super.validateLocatorStrategy(strategy, this.isWebContext());
|
|
335
460
|
}
|
|
461
|
+
validateDesiredCaps(caps) {
|
|
462
|
+
if (!super.validateDesiredCaps(caps)) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
// make sure that the capabilities have one of `app` or `bundleId`
|
|
466
|
+
if (lodash_1.default.toLower(caps.browserName) !== 'safari' && !caps.app && !caps.bundleId) {
|
|
467
|
+
this.log.info('The desired capabilities include neither an app nor a bundleId. ' +
|
|
468
|
+
'WebDriverAgent will be started without the default app');
|
|
469
|
+
}
|
|
470
|
+
if (!support_1.util.coerceVersion(String(caps.platformVersion), false)) {
|
|
471
|
+
this.log.warn(`'platformVersion' capability ('${caps.platformVersion}') is not a valid version number. ` +
|
|
472
|
+
`Consider fixing it or be ready to experience an inconsistent driver behavior.`);
|
|
473
|
+
}
|
|
474
|
+
const verifyProcessArgument = (processArguments) => {
|
|
475
|
+
const { args, env } = processArguments;
|
|
476
|
+
if (!lodash_1.default.isNil(args) && !lodash_1.default.isArray(args)) {
|
|
477
|
+
throw this.log.errorWithException('processArguments.args must be an array of strings');
|
|
478
|
+
}
|
|
479
|
+
if (!lodash_1.default.isNil(env) && !lodash_1.default.isPlainObject(env)) {
|
|
480
|
+
throw this.log.errorWithException('processArguments.env must be an object <key,value> pair {a:b, c:d}');
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
// `processArguments` should be JSON string or an object with arguments and/ environment details
|
|
484
|
+
if (caps.processArguments) {
|
|
485
|
+
if (lodash_1.default.isString(caps.processArguments)) {
|
|
486
|
+
try {
|
|
487
|
+
// try to parse the string as JSON
|
|
488
|
+
caps.processArguments = JSON.parse(caps.processArguments);
|
|
489
|
+
verifyProcessArgument(caps.processArguments);
|
|
490
|
+
}
|
|
491
|
+
catch (err) {
|
|
492
|
+
throw this.log.errorWithException(`processArguments must be a JSON format or an object with format {args : [], env : {a:b, c:d}}. ` +
|
|
493
|
+
`Both environment and argument can be null. Error: ${err}`);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
else if (lodash_1.default.isPlainObject(caps.processArguments)) {
|
|
497
|
+
verifyProcessArgument(caps.processArguments);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
throw this.log.errorWithException(`'processArguments must be an object, or a string JSON object with format {args : [], env : {a:b, c:d}}. ` +
|
|
501
|
+
`Both environment and argument can be null.`);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// there is no point in having `keychainPath` without `keychainPassword`
|
|
505
|
+
if ((caps.keychainPath && !caps.keychainPassword) ||
|
|
506
|
+
(!caps.keychainPath && caps.keychainPassword)) {
|
|
507
|
+
throw this.log.errorWithException(`If 'keychainPath' is set, 'keychainPassword' must also be set (and vice versa).`);
|
|
508
|
+
}
|
|
509
|
+
// `resetOnSessionStartOnly` should be set to true by default
|
|
510
|
+
this.opts.resetOnSessionStartOnly =
|
|
511
|
+
!support_1.util.hasValue(this.opts.resetOnSessionStartOnly) || this.opts.resetOnSessionStartOnly;
|
|
512
|
+
this.opts.useNewWDA = support_1.util.hasValue(this.opts.useNewWDA) ? this.opts.useNewWDA : false;
|
|
513
|
+
if (caps.commandTimeouts) {
|
|
514
|
+
caps.commandTimeouts = (0, utils_1.normalizeCommandTimeouts)(caps.commandTimeouts);
|
|
515
|
+
}
|
|
516
|
+
if (lodash_1.default.isString(caps.webDriverAgentUrl)) {
|
|
517
|
+
const { protocol, host } = node_url_1.default.parse(caps.webDriverAgentUrl);
|
|
518
|
+
if (lodash_1.default.isEmpty(protocol) || lodash_1.default.isEmpty(host)) {
|
|
519
|
+
throw this.log.errorWithException(`'webDriverAgentUrl' capability is expected to contain a valid WebDriverAgent server URL. ` +
|
|
520
|
+
`'${caps.webDriverAgentUrl}' is given instead`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (caps.browserName) {
|
|
524
|
+
if (caps.bundleId) {
|
|
525
|
+
throw this.log.errorWithException(`'browserName' cannot be set together with 'bundleId' capability`);
|
|
526
|
+
}
|
|
527
|
+
// warn if the capabilities have both `app` and `browser, although this
|
|
528
|
+
// is common with selenium grid
|
|
529
|
+
if (caps.app) {
|
|
530
|
+
this.log.warn(`The capabilities should generally not include both an 'app' and a 'browserName'`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (caps.permissions) {
|
|
534
|
+
try {
|
|
535
|
+
for (const [bundleId, perms] of lodash_1.default.toPairs(JSON.parse(caps.permissions))) {
|
|
536
|
+
if (!lodash_1.default.isString(bundleId)) {
|
|
537
|
+
throw new Error(`'${JSON.stringify(bundleId)}' must be a string`);
|
|
538
|
+
}
|
|
539
|
+
if (!lodash_1.default.isPlainObject(perms)) {
|
|
540
|
+
throw new Error(`'${JSON.stringify(perms)}' must be a JSON object`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
catch (e) {
|
|
545
|
+
throw this.log.errorWithException(`'${caps.permissions}' is expected to be a valid object with format ` +
|
|
546
|
+
`{"<bundleId1>": {"<serviceName1>": "<serviceStatus1>", ...}, ...}. Original error: ${e.message}`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (caps.platformVersion && !support_1.util.coerceVersion(caps.platformVersion, false)) {
|
|
550
|
+
throw this.log.errorWithException(`'platformVersion' must be a valid version number. ` +
|
|
551
|
+
`'${caps.platformVersion}' is given instead.`);
|
|
552
|
+
}
|
|
553
|
+
// additionalWebviewBundleIds is an array, JSON array, or string
|
|
554
|
+
if (caps.additionalWebviewBundleIds) {
|
|
555
|
+
caps.additionalWebviewBundleIds = this.helpers.parseCapsArray(caps.additionalWebviewBundleIds);
|
|
556
|
+
}
|
|
557
|
+
// finally, return true since the superclass check passed, as did this
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
// Getter methods
|
|
561
|
+
get wda() {
|
|
562
|
+
if (!this._wda) {
|
|
563
|
+
throw new Error('WebDriverAgent is not initialized');
|
|
564
|
+
}
|
|
565
|
+
return this._wda;
|
|
566
|
+
}
|
|
567
|
+
get driverData() {
|
|
568
|
+
// TODO fill out resource info here
|
|
569
|
+
return {};
|
|
570
|
+
}
|
|
571
|
+
get device() {
|
|
572
|
+
return this._device;
|
|
573
|
+
}
|
|
574
|
+
// Utility methods
|
|
575
|
+
isSafari() {
|
|
576
|
+
return !!this.safari;
|
|
577
|
+
}
|
|
578
|
+
isRealDevice() {
|
|
579
|
+
return 'devicectl' in (this.device ?? {});
|
|
580
|
+
}
|
|
581
|
+
isSimulator() {
|
|
582
|
+
return 'simctl' in (this.device ?? {});
|
|
583
|
+
}
|
|
584
|
+
isXcodebuildNeeded() {
|
|
585
|
+
return !(CAP_NAMES_NO_XCODEBUILD_REQUIRED.some((x) => Boolean(this.opts[x])));
|
|
586
|
+
}
|
|
587
|
+
// Core driver methods
|
|
336
588
|
async onSettingsUpdate(key, value) {
|
|
337
589
|
// skip sending the update request to the WDA nor saving it in opts
|
|
338
590
|
// to not spend unnecessary time.
|
|
@@ -344,39 +596,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
344
596
|
settings: { [key]: value },
|
|
345
597
|
});
|
|
346
598
|
}
|
|
347
|
-
this.opts[key] = !!value;
|
|
348
|
-
}
|
|
349
|
-
resetIos() {
|
|
350
|
-
this.opts = this.opts || {};
|
|
351
|
-
// @ts-ignore this is ok
|
|
352
|
-
this.wda = null;
|
|
353
|
-
this.jwpProxyActive = false;
|
|
354
|
-
this.proxyReqRes = null;
|
|
355
|
-
this.safari = false;
|
|
356
|
-
this.cachedWdaStatus = null;
|
|
357
|
-
this.curWebFrames = [];
|
|
358
|
-
this._currentUrl = null;
|
|
359
|
-
this.curContext = null;
|
|
360
|
-
this.xcodeVersion = undefined;
|
|
361
|
-
this.contexts = [];
|
|
362
|
-
this.implicitWaitMs = 0;
|
|
363
|
-
this.pageLoadMs = 6000;
|
|
364
|
-
this.landscapeWebCoordsOffset = 0;
|
|
365
|
-
this.remote = null;
|
|
366
|
-
this._conditionInducerService = null;
|
|
367
|
-
this._remoteXPCConditionInducerConnection = null;
|
|
368
|
-
this.webElementsCache = new lru_cache_1.LRUCache({
|
|
369
|
-
max: WEB_ELEMENTS_CACHE_SIZE,
|
|
370
|
-
});
|
|
371
|
-
this._waitingAtoms = {
|
|
372
|
-
count: 0,
|
|
373
|
-
alertNotifier: new node_events_1.default(),
|
|
374
|
-
alertMonitor: bluebird_1.default.resolve(),
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
get driverData() {
|
|
378
|
-
// TODO fill out resource info here
|
|
379
|
-
return {};
|
|
599
|
+
this.opts[key] = !!value;
|
|
380
600
|
}
|
|
381
601
|
async getStatus() {
|
|
382
602
|
const status = {
|
|
@@ -401,79 +621,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
401
621
|
}
|
|
402
622
|
return didMerge;
|
|
403
623
|
}
|
|
404
|
-
/**
|
|
405
|
-
* @returns {Simulator|RealDevice}
|
|
406
|
-
*/
|
|
407
|
-
get device() {
|
|
408
|
-
return this._device;
|
|
409
|
-
}
|
|
410
|
-
isXcodebuildNeeded() {
|
|
411
|
-
return !(CAP_NAMES_NO_XCODEBUILD_REQUIRED.some((x) => Boolean(this.opts[x])));
|
|
412
|
-
}
|
|
413
|
-
async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
|
|
414
|
-
try {
|
|
415
|
-
let [sessionId, caps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
|
|
416
|
-
// merge cli args to opts, and if we did merge any, revalidate opts to ensure the final set
|
|
417
|
-
// is also consistent
|
|
418
|
-
if (this.mergeCliArgsToOpts()) {
|
|
419
|
-
this.validateDesiredCaps({ ...caps, ...this.cliArgs });
|
|
420
|
-
}
|
|
421
|
-
await this.start();
|
|
422
|
-
// merge server capabilities + desired capabilities
|
|
423
|
-
caps = { ...defaultServerCaps, ...caps };
|
|
424
|
-
// update the udid with what is actually used
|
|
425
|
-
caps.udid = this.opts.udid;
|
|
426
|
-
// ensure we track nativeWebTap capability as a setting as well
|
|
427
|
-
if (lodash_1.default.has(this.opts, 'nativeWebTap')) {
|
|
428
|
-
await this.updateSettings({ nativeWebTap: this.opts.nativeWebTap });
|
|
429
|
-
}
|
|
430
|
-
// ensure we track nativeWebTapStrict capability as a setting as well
|
|
431
|
-
if (lodash_1.default.has(this.opts, 'nativeWebTapStrict')) {
|
|
432
|
-
await this.updateSettings({ nativeWebTapStrict: this.opts.nativeWebTapStrict });
|
|
433
|
-
}
|
|
434
|
-
// ensure we track useJSONSource capability as a setting as well
|
|
435
|
-
if (lodash_1.default.has(this.opts, 'useJSONSource')) {
|
|
436
|
-
await this.updateSettings({ useJSONSource: this.opts.useJSONSource });
|
|
437
|
-
}
|
|
438
|
-
/** @type {import('appium-webdriveragent').WDASettings} */
|
|
439
|
-
let wdaSettings = {
|
|
440
|
-
elementResponseAttributes: DEFAULT_SETTINGS.elementResponseAttributes,
|
|
441
|
-
shouldUseCompactResponses: DEFAULT_SETTINGS.shouldUseCompactResponses,
|
|
442
|
-
};
|
|
443
|
-
if ('elementResponseAttributes' in this.opts && lodash_1.default.isString(this.opts.elementResponseAttributes)) {
|
|
444
|
-
wdaSettings.elementResponseAttributes = this.opts.elementResponseAttributes;
|
|
445
|
-
}
|
|
446
|
-
if ('shouldUseCompactResponses' in this.opts && lodash_1.default.isBoolean(this.opts.shouldUseCompactResponses)) {
|
|
447
|
-
wdaSettings.shouldUseCompactResponses = this.opts.shouldUseCompactResponses;
|
|
448
|
-
}
|
|
449
|
-
if ('mjpegServerScreenshotQuality' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerScreenshotQuality)) {
|
|
450
|
-
wdaSettings.mjpegServerScreenshotQuality = this.opts.mjpegServerScreenshotQuality;
|
|
451
|
-
}
|
|
452
|
-
if ('mjpegServerFramerate' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerFramerate)) {
|
|
453
|
-
wdaSettings.mjpegServerFramerate = this.opts.mjpegServerFramerate;
|
|
454
|
-
}
|
|
455
|
-
if (lodash_1.default.has(this.opts, 'screenshotQuality')) {
|
|
456
|
-
this.log.info(`Setting the quality of phone screenshot: '${this.opts.screenshotQuality}'`);
|
|
457
|
-
wdaSettings.screenshotQuality = this.opts.screenshotQuality;
|
|
458
|
-
}
|
|
459
|
-
// ensure WDA gets our defaults instead of whatever its own might be
|
|
460
|
-
await this.updateSettings(wdaSettings);
|
|
461
|
-
await this.handleMjpegOptions();
|
|
462
|
-
return /** @type {[string, import('@appium/types').DriverCaps<XCUITestDriverConstraints>]} */ ([
|
|
463
|
-
sessionId,
|
|
464
|
-
caps,
|
|
465
|
-
]);
|
|
466
|
-
}
|
|
467
|
-
catch (e) {
|
|
468
|
-
this.log.error(JSON.stringify(e));
|
|
469
|
-
await this.deleteSession();
|
|
470
|
-
throw e;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Handles MJPEG server-related capabilities
|
|
475
|
-
* @returns {Promise<void>}
|
|
476
|
-
*/
|
|
477
624
|
async handleMjpegOptions() {
|
|
478
625
|
await this.allocateMjpegServerPort();
|
|
479
626
|
// turn on mjpeg stream reading if requested
|
|
@@ -483,11 +630,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
483
630
|
await this.mjpegStream.start();
|
|
484
631
|
}
|
|
485
632
|
}
|
|
486
|
-
/**
|
|
487
|
-
* Allocates and configures port forwarding for the MJPEG server
|
|
488
|
-
* @returns {Promise<void>}
|
|
489
|
-
* @throws {Error} If port forwarding fails and mjpegServerPort capability value is provided explicitly
|
|
490
|
-
*/
|
|
491
633
|
async allocateMjpegServerPort() {
|
|
492
634
|
const mjpegServerPort = this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT;
|
|
493
635
|
this.log.debug(`Forwarding MJPEG server port ${mjpegServerPort} to local port ${mjpegServerPort}`);
|
|
@@ -511,10 +653,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
511
653
|
}
|
|
512
654
|
}
|
|
513
655
|
}
|
|
514
|
-
/**
|
|
515
|
-
* Returns the default URL for Safari browser
|
|
516
|
-
* @returns {string} The default URL
|
|
517
|
-
*/
|
|
518
656
|
getDefaultUrl() {
|
|
519
657
|
// Setting this to some external URL slows down the session init
|
|
520
658
|
return `${this.getWdaLocalhostRoot()}/health`;
|
|
@@ -534,7 +672,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
534
672
|
}
|
|
535
673
|
else {
|
|
536
674
|
this.log.info(`Setting simulator devices set path to '${this.opts.simulatorDevicesSetPath}'`);
|
|
537
|
-
|
|
675
|
+
this.device.devicesSetPath = this.opts.simulatorDevicesSetPath;
|
|
538
676
|
}
|
|
539
677
|
}
|
|
540
678
|
// at this point if there is no platformVersion, get it from the device
|
|
@@ -575,21 +713,26 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
575
713
|
}
|
|
576
714
|
}
|
|
577
715
|
await this.runReset();
|
|
578
|
-
this.
|
|
579
|
-
|
|
716
|
+
this._wda = new appium_webdriveragent_1.WebDriverAgent(
|
|
717
|
+
// @ts-ignore This property is not used by WDA, and will be removed in the future
|
|
718
|
+
this.xcodeVersion, {
|
|
580
719
|
...this.opts,
|
|
581
720
|
device: this.device,
|
|
582
721
|
realDevice: this.isRealDevice(),
|
|
583
722
|
iosSdkVersion: this._iosSdkVersion ?? undefined,
|
|
584
723
|
reqBasePath: this.basePath,
|
|
585
|
-
},
|
|
586
|
-
// @ts-ignore this is ok
|
|
587
|
-
this.log);
|
|
724
|
+
}, this.log);
|
|
588
725
|
// Derived data path retrieval is an expensive operation
|
|
589
726
|
// We could start that now in background and get the cached result
|
|
590
727
|
// whenever it is needed
|
|
591
|
-
|
|
592
|
-
|
|
728
|
+
(async () => {
|
|
729
|
+
try {
|
|
730
|
+
await this.wda.retrieveDerivedDataPath();
|
|
731
|
+
}
|
|
732
|
+
catch (e) {
|
|
733
|
+
this.log.debug(e);
|
|
734
|
+
}
|
|
735
|
+
})();
|
|
593
736
|
const memoizedLogInfo = lodash_1.default.memoize(() => {
|
|
594
737
|
this.log.info("'skipLogCapture' is set. Skipping starting logs such as crash, system, safari console and safari network.");
|
|
595
738
|
});
|
|
@@ -632,7 +775,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
632
775
|
if (this.opts.permissions) {
|
|
633
776
|
this.log.debug('Setting the requested permissions before WDA is started');
|
|
634
777
|
for (const [bundleId, permissionsMapping] of lodash_1.default.toPairs(JSON.parse(this.opts.permissions))) {
|
|
635
|
-
await
|
|
778
|
+
await this.device.setPermissions(bundleId, permissionsMapping);
|
|
636
779
|
}
|
|
637
780
|
}
|
|
638
781
|
// TODO: Deprecate and remove this block together with calendarAccessAuthorized capability
|
|
@@ -671,11 +814,40 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
671
814
|
}
|
|
672
815
|
}
|
|
673
816
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
817
|
+
async runReset(enforceSimulatorShutdown = false) {
|
|
818
|
+
this.logEvent('resetStarted');
|
|
819
|
+
if (this.isRealDevice()) {
|
|
820
|
+
await real_device_management_1.runRealDeviceReset.bind(this)();
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
await simulator_management_1.runSimulatorReset.bind(this)(enforceSimulatorShutdown);
|
|
824
|
+
}
|
|
825
|
+
this.logEvent('resetComplete');
|
|
826
|
+
}
|
|
827
|
+
async stop() {
|
|
828
|
+
this.jwpProxyActive = false;
|
|
829
|
+
this.proxyReqRes = null;
|
|
830
|
+
if (this._wda?.fullyStarted) {
|
|
831
|
+
if (this.wda.jwproxy) {
|
|
832
|
+
try {
|
|
833
|
+
await this.proxyCommand(`/session/${this.sessionId}`, 'DELETE');
|
|
834
|
+
}
|
|
835
|
+
catch (err) {
|
|
836
|
+
// an error here should not short-circuit the rest of clean up
|
|
837
|
+
this.log.debug(`Unable to DELETE session on WDA: '${err.message}'. Continuing shutdown.`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
// The former could cache the xcodebuild, so should not quit the process.
|
|
841
|
+
// If the session skipped the xcodebuild (this.wda.canSkipXcodebuild), the this.wda instance
|
|
842
|
+
// should quit properly.
|
|
843
|
+
if ((!this.wda.webDriverAgentUrl && this.opts.useNewWDA) || this.wda.canSkipXcodebuild) {
|
|
844
|
+
await this.wda.quit();
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
device_connections_factory_1.DEVICE_CONNECTIONS_FACTORY.releaseConnection(this.opts.udid);
|
|
848
|
+
}
|
|
677
849
|
async initSimulator() {
|
|
678
|
-
const device =
|
|
850
|
+
const device = this.device;
|
|
679
851
|
if (this.opts.shutdownOtherSimulators) {
|
|
680
852
|
this.assertFeatureEnabled(SHUTDOWN_OTHER_FEAT_NAME);
|
|
681
853
|
await simulator_management_1.shutdownOtherSimulators.bind(this)();
|
|
@@ -692,7 +864,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
692
864
|
if (await simulator_management_1.setLocalizationPrefs.bind(this)()) {
|
|
693
865
|
this.log.debug('Localization preferences have been updated');
|
|
694
866
|
}
|
|
695
|
-
/** @type {Promise[]} */
|
|
696
867
|
const promises = ['reduceMotion', 'reduceTransparency', 'autoFillPasswords']
|
|
697
868
|
.filter((optName) => lodash_1.default.isBoolean(this.opts[optName]))
|
|
698
869
|
.map((optName) => {
|
|
@@ -714,9 +885,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
714
885
|
}
|
|
715
886
|
this.logEvent('simStarted');
|
|
716
887
|
}
|
|
717
|
-
/**
|
|
718
|
-
* Start WebDriverAgentRunner
|
|
719
|
-
*/
|
|
720
888
|
async startWda() {
|
|
721
889
|
// Don't cleanup the processes if webDriverAgentUrl is set
|
|
722
890
|
if (!support_1.util.hasValue(this.wda.webDriverAgentUrl)) {
|
|
@@ -787,7 +955,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
787
955
|
this.log.debug(`Trying to start WebDriverAgent once since at least one of ${CAP_NAMES_NO_XCODEBUILD_REQUIRED} capabilities is provided`);
|
|
788
956
|
startupRetries = 1;
|
|
789
957
|
}
|
|
790
|
-
/** @type {Error|null} */
|
|
791
958
|
let shortCircuitError = null;
|
|
792
959
|
let retryCount = 0;
|
|
793
960
|
await (0, asyncbox_1.retryInterval)(startupRetries, startupRetryInterval, async () => {
|
|
@@ -799,207 +966,84 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
799
966
|
if (this.opts.usePreinstalledWDA) {
|
|
800
967
|
await this.preparePreinstalledWda();
|
|
801
968
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
this.
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
if (this.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
this.cachedWdaStatus = this.cachedWdaStatus || (await this.proxyCommand('/status', 'GET'));
|
|
840
|
-
await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
|
|
841
|
-
this.logEvent('wdaSessionStarted');
|
|
842
|
-
}
|
|
843
|
-
catch (err) {
|
|
844
|
-
this.logEvent('wdaSessionFailed');
|
|
845
|
-
this.log.debug(err.stack);
|
|
846
|
-
if (err instanceof driver_1.errors.TimeoutError) {
|
|
847
|
-
// Session startup timed out. There is no point to retry
|
|
848
|
-
shortCircuitError = err;
|
|
849
|
-
return;
|
|
850
|
-
}
|
|
851
|
-
let errorMsg = `Unable to start WebDriverAgent session. Original error: ${err.message}`;
|
|
852
|
-
if (this.isRealDevice() && lodash_1.default.includes(err.message, 'xcodebuild')) {
|
|
853
|
-
errorMsg += ` Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}.`;
|
|
854
|
-
}
|
|
855
|
-
throw new Error(errorMsg);
|
|
856
|
-
}
|
|
857
|
-
if (this.opts.clearSystemFiles && this.isXcodebuildNeeded()) {
|
|
858
|
-
await (0, utils_1.markSystemFilesForCleanup)(this.wda);
|
|
859
|
-
}
|
|
860
|
-
// We don't restrict the version, but show what version of WDA is running on the device for debugging purposes.
|
|
861
|
-
if (this.cachedWdaStatus?.build) {
|
|
862
|
-
this.log.info(`WebDriverAgent version: '${this.cachedWdaStatus.build.version}'`);
|
|
863
|
-
}
|
|
864
|
-
else {
|
|
865
|
-
this.log.warn(`WebDriverAgent does not provide any version information. ` +
|
|
866
|
-
`This might indicate either a custom or an outdated build.`);
|
|
867
|
-
}
|
|
868
|
-
// we expect certain socket errors until this point, but now
|
|
869
|
-
// mark things as fully working
|
|
870
|
-
this.wda.fullyStarted = true;
|
|
871
|
-
this.logEvent('wdaStarted');
|
|
872
|
-
});
|
|
873
|
-
if (shortCircuitError) {
|
|
874
|
-
throw shortCircuitError;
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
/**
|
|
879
|
-
*
|
|
880
|
-
* @param {boolean} [enforceSimulatorShutdown=false]
|
|
881
|
-
*/
|
|
882
|
-
async runReset(enforceSimulatorShutdown = false) {
|
|
883
|
-
this.logEvent('resetStarted');
|
|
884
|
-
if (this.isRealDevice()) {
|
|
885
|
-
await real_device_management_1.runRealDeviceReset.bind(this)();
|
|
886
|
-
}
|
|
887
|
-
else {
|
|
888
|
-
await simulator_management_1.runSimulatorReset.bind(this)(enforceSimulatorShutdown);
|
|
889
|
-
}
|
|
890
|
-
this.logEvent('resetComplete');
|
|
891
|
-
}
|
|
892
|
-
async deleteSession(sessionId) {
|
|
893
|
-
await utils_1.removeAllSessionWebSocketHandlers.bind(this)();
|
|
894
|
-
for (const recorder of lodash_1.default.compact([
|
|
895
|
-
this._recentScreenRecorder,
|
|
896
|
-
this._audioRecorder,
|
|
897
|
-
this._trafficCapture,
|
|
898
|
-
])) {
|
|
899
|
-
await recorder.interrupt(true);
|
|
900
|
-
await recorder.cleanup();
|
|
901
|
-
}
|
|
902
|
-
if (!lodash_1.default.isEmpty(this._perfRecorders)) {
|
|
903
|
-
await bluebird_1.default.all(this._perfRecorders.map((x) => x.stop(true)));
|
|
904
|
-
this._perfRecorders = [];
|
|
905
|
-
}
|
|
906
|
-
if (this._conditionInducerService || this._remoteXPCConditionInducerConnection) {
|
|
907
|
-
try {
|
|
908
|
-
await this.disableConditionInducer();
|
|
909
|
-
}
|
|
910
|
-
catch (err) {
|
|
911
|
-
this.log.warn(`Cannot disable condition inducer: ${err.message}`);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
await this.stop();
|
|
915
|
-
if (this.wda && this.isXcodebuildNeeded()) {
|
|
916
|
-
if (this.opts.clearSystemFiles) {
|
|
917
|
-
let synchronizationKey = XCUITestDriver.name;
|
|
918
|
-
const derivedDataPath = await this.wda.retrieveDerivedDataPath();
|
|
919
|
-
if (derivedDataPath) {
|
|
920
|
-
synchronizationKey = node_path_1.default.normalize(derivedDataPath);
|
|
921
|
-
}
|
|
922
|
-
await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
|
|
923
|
-
await (0, utils_1.clearSystemFiles)(this.wda);
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
else {
|
|
927
|
-
this.log.debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.');
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
if (this.remote) {
|
|
931
|
-
this.log.debug('Found a remote debugger session. Removing...');
|
|
932
|
-
await this.stopRemote();
|
|
933
|
-
}
|
|
934
|
-
if (this.opts.resetOnSessionStartOnly === false) {
|
|
935
|
-
await this.runReset(true);
|
|
936
|
-
}
|
|
937
|
-
const simulatorDevice = this.isSimulator() ? /** @type {Simulator} */ (this.device) : null;
|
|
938
|
-
if (simulatorDevice && this.lifecycleData.createSim) {
|
|
939
|
-
this.log.debug(`Deleting simulator created for this run (udid: '${simulatorDevice.udid}')`);
|
|
940
|
-
await simulator_management_1.shutdownSimulator.bind(this)();
|
|
941
|
-
await simulatorDevice.delete();
|
|
942
|
-
}
|
|
943
|
-
const shouldResetLocationService = this.isRealDevice() && !!this.opts.resetLocationService;
|
|
944
|
-
if (shouldResetLocationService) {
|
|
945
|
-
try {
|
|
946
|
-
await this.mobileResetLocationService();
|
|
947
|
-
}
|
|
948
|
-
catch {
|
|
949
|
-
/* Ignore this error since mobileResetLocationService already logged the error */
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
await this.logs.syslog?.stopCapture();
|
|
953
|
-
lodash_1.default.values(this.logs).forEach((x) => x.removeAllListeners());
|
|
954
|
-
if (this._bidiServerLogListener) {
|
|
955
|
-
this.log.unwrap().off('log', this._bidiServerLogListener);
|
|
956
|
-
}
|
|
957
|
-
this.logs = {};
|
|
958
|
-
if (this.mjpegStream) {
|
|
959
|
-
this.log.info('Closing MJPEG stream');
|
|
960
|
-
this.mjpegStream.stop();
|
|
961
|
-
}
|
|
962
|
-
this.resetIos();
|
|
963
|
-
await super.deleteSession(sessionId);
|
|
964
|
-
}
|
|
965
|
-
async stop() {
|
|
966
|
-
this.jwpProxyActive = false;
|
|
967
|
-
this.proxyReqRes = null;
|
|
968
|
-
if (this.wda?.fullyStarted) {
|
|
969
|
-
if (this.wda.jwproxy) {
|
|
969
|
+
if (!this.sessionId) {
|
|
970
|
+
throw new Error('Session ID is required but was not set');
|
|
971
|
+
}
|
|
972
|
+
this.cachedWdaStatus = await this.wda.launch(this.sessionId);
|
|
973
|
+
}
|
|
974
|
+
catch (err) {
|
|
975
|
+
this.logEvent('wdaStartFailed');
|
|
976
|
+
this.log.debug(err.stack);
|
|
977
|
+
retryCount++;
|
|
978
|
+
let errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}`;
|
|
979
|
+
if (this.isRealDevice()) {
|
|
980
|
+
errorMsg += `. Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}`;
|
|
981
|
+
}
|
|
982
|
+
if (this.opts.usePreinstalledWDA) {
|
|
983
|
+
try {
|
|
984
|
+
// In case the bundle id process start got failed because of
|
|
985
|
+
// auth popup in the device. Then, the bundle id process itself started. It is safe to stop it here.
|
|
986
|
+
await this.mobileKillApp(this.wda.bundleIdForXctest);
|
|
987
|
+
}
|
|
988
|
+
catch { }
|
|
989
|
+
;
|
|
990
|
+
// Mostly it failed to start the WDA process as no the bundle id
|
|
991
|
+
// e.g. '<bundle id of WDA> not found on device <udid>'
|
|
992
|
+
errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}. ` +
|
|
993
|
+
`Make sure the application ${this.wda.bundleIdForXctest} exists and it is launchable.`;
|
|
994
|
+
if (this.isRealDevice()) {
|
|
995
|
+
errorMsg += ` ${WDA_REAL_DEV_TUTORIAL_URL} may help to complete the preparation.`;
|
|
996
|
+
}
|
|
997
|
+
;
|
|
998
|
+
throw new Error(errorMsg);
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
await quitAndUninstall(errorMsg);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
this.proxyReqRes = this.wda.proxyReqRes.bind(this.wda);
|
|
1005
|
+
this.jwpProxyActive = true;
|
|
970
1006
|
try {
|
|
971
|
-
|
|
1007
|
+
this.logEvent('wdaSessionAttempted');
|
|
1008
|
+
this.log.debug('Sending createSession command to WDA');
|
|
1009
|
+
this.cachedWdaStatus = this.cachedWdaStatus || (await this.proxyCommand('/status', 'GET'));
|
|
1010
|
+
await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
|
|
1011
|
+
this.logEvent('wdaSessionStarted');
|
|
972
1012
|
}
|
|
973
1013
|
catch (err) {
|
|
974
|
-
|
|
975
|
-
this.log.debug(
|
|
1014
|
+
this.logEvent('wdaSessionFailed');
|
|
1015
|
+
this.log.debug(err.stack);
|
|
1016
|
+
if (err instanceof driver_1.errors.TimeoutError) {
|
|
1017
|
+
// Session startup timed out. There is no point to retry
|
|
1018
|
+
shortCircuitError = err;
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
let errorMsg = `Unable to start WebDriverAgent session. Original error: ${err.message}`;
|
|
1022
|
+
if (this.isRealDevice() && lodash_1.default.includes(err.message, 'xcodebuild')) {
|
|
1023
|
+
errorMsg += ` Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}.`;
|
|
1024
|
+
}
|
|
1025
|
+
throw new Error(errorMsg);
|
|
976
1026
|
}
|
|
1027
|
+
if (this.opts.clearSystemFiles && this.isXcodebuildNeeded()) {
|
|
1028
|
+
await (0, utils_1.markSystemFilesForCleanup)(this.wda);
|
|
1029
|
+
}
|
|
1030
|
+
// We don't restrict the version, but show what version of WDA is running on the device for debugging purposes.
|
|
1031
|
+
if (this.cachedWdaStatus?.build) {
|
|
1032
|
+
this.log.info(`WebDriverAgent version: '${this.cachedWdaStatus.build.version}'`);
|
|
1033
|
+
}
|
|
1034
|
+
else {
|
|
1035
|
+
this.log.warn(`WebDriverAgent does not provide any version information. ` +
|
|
1036
|
+
`This might indicate either a custom or an outdated build.`);
|
|
1037
|
+
}
|
|
1038
|
+
// we expect certain socket errors until this point, but now
|
|
1039
|
+
// mark things as fully working
|
|
1040
|
+
this.wda.fullyStarted = true;
|
|
1041
|
+
this.logEvent('wdaStarted');
|
|
1042
|
+
});
|
|
1043
|
+
if (shortCircuitError) {
|
|
1044
|
+
throw shortCircuitError;
|
|
977
1045
|
}
|
|
978
|
-
|
|
979
|
-
// If the session skipped the xcodebuild (this.wda.canSkipXcodebuild), the this.wda instance
|
|
980
|
-
// should quit properly.
|
|
981
|
-
if ((!this.wda.webDriverAgentUrl && this.opts.useNewWDA) || this.wda.canSkipXcodebuild) {
|
|
982
|
-
await this.wda.quit();
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
device_connections_factory_1.DEVICE_CONNECTIONS_FACTORY.releaseConnection(this.opts.udid);
|
|
986
|
-
}
|
|
987
|
-
/**
|
|
988
|
-
*
|
|
989
|
-
* @param {string} cmd
|
|
990
|
-
* @param {...any} args
|
|
991
|
-
* @returns {Promise<any>}
|
|
992
|
-
*/
|
|
993
|
-
async executeCommand(cmd, ...args) {
|
|
994
|
-
this.log.debug(`Executing command '${cmd}'`);
|
|
995
|
-
if (cmd === 'receiveAsyncResponse') {
|
|
996
|
-
return await this.receiveAsyncResponse(...args);
|
|
997
|
-
}
|
|
998
|
-
// TODO: once this fix gets into base driver remove from here
|
|
999
|
-
if (cmd === 'getStatus') {
|
|
1000
|
-
return await this.getStatus();
|
|
1001
|
-
}
|
|
1002
|
-
return await super.executeCommand(cmd, ...args);
|
|
1046
|
+
});
|
|
1003
1047
|
}
|
|
1004
1048
|
async configureApp() {
|
|
1005
1049
|
function appIsPackageOrBundle(app) {
|
|
@@ -1021,11 +1065,11 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1021
1065
|
switch (lodash_1.default.toLower(this.opts.app)) {
|
|
1022
1066
|
case 'settings':
|
|
1023
1067
|
this.opts.bundleId = 'com.apple.Preferences';
|
|
1024
|
-
this.opts.app =
|
|
1068
|
+
this.opts.app = undefined;
|
|
1025
1069
|
return;
|
|
1026
1070
|
case 'calendar':
|
|
1027
1071
|
this.opts.bundleId = 'com.apple.mobilecal';
|
|
1028
|
-
this.opts.app =
|
|
1072
|
+
this.opts.app = undefined;
|
|
1029
1073
|
return;
|
|
1030
1074
|
}
|
|
1031
1075
|
this.opts.app = await this.helpers.configureApp(this.opts.app, {
|
|
@@ -1070,7 +1114,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1070
1114
|
let isRealDeviceUdid = false;
|
|
1071
1115
|
const shouldCheckAvailableRealDevices = !this.opts.webDriverAgentUrl;
|
|
1072
1116
|
if (shouldCheckAvailableRealDevices) {
|
|
1073
|
-
const devices = await (0,
|
|
1117
|
+
const devices = await (0, real_device_management_1.getConnectedDevices)();
|
|
1074
1118
|
this.log.debug(`Available real devices: ${devices.join(', ')}`);
|
|
1075
1119
|
isRealDeviceUdid = devices.includes(this.opts.udid);
|
|
1076
1120
|
}
|
|
@@ -1092,7 +1136,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1092
1136
|
}
|
|
1093
1137
|
}
|
|
1094
1138
|
this.log.debug(`Creating iDevice object with udid '${this.opts.udid}'`);
|
|
1095
|
-
const device = new
|
|
1139
|
+
const device = new real_device_management_1.RealDevice(this.opts.udid, this.log);
|
|
1096
1140
|
return { device, realDevice: true, udid: this.opts.udid };
|
|
1097
1141
|
}
|
|
1098
1142
|
this.log.info(`No real device udid has been provided in capabilities. ` +
|
|
@@ -1115,9 +1159,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1115
1159
|
return { device, realDevice: false, udid: device.udid };
|
|
1116
1160
|
}
|
|
1117
1161
|
async startSim() {
|
|
1118
|
-
/** @type {import('appium-ios-simulator').DevicePreferences} */
|
|
1119
1162
|
const devicePreferences = {};
|
|
1120
|
-
/** @type {import('appium-ios-simulator').RunOptions} */
|
|
1121
1163
|
const runOpts = {
|
|
1122
1164
|
scaleFactor: this.opts.scaleFactor,
|
|
1123
1165
|
connectHardwareKeyboard: !!this.opts.connectHardwareKeyboard,
|
|
@@ -1146,7 +1188,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1146
1188
|
devicePreferences.SimulatorWindowRotationAngle = 0;
|
|
1147
1189
|
break;
|
|
1148
1190
|
}
|
|
1149
|
-
await
|
|
1191
|
+
await this.device.run(runOpts);
|
|
1150
1192
|
}
|
|
1151
1193
|
async createSim() {
|
|
1152
1194
|
this.lifecycleData.createSim = true;
|
|
@@ -1185,7 +1227,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1185
1227
|
// https://developer.apple.com/forums/thread/86951?answerId=263395022#263395022
|
|
1186
1228
|
env.TZ = this.opts.appTimeZone;
|
|
1187
1229
|
}
|
|
1188
|
-
/** @type {import('appium-webdriveragent').WDACapabilities} */
|
|
1189
1230
|
const wdaCaps = {
|
|
1190
1231
|
bundleId: this.opts.autoLaunch === false ? undefined : bundleId,
|
|
1191
1232
|
arguments: args,
|
|
@@ -1227,155 +1268,9 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1227
1268
|
});
|
|
1228
1269
|
this.log.info(`WDA session startup took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
1229
1270
|
}
|
|
1230
|
-
// Override Proxy methods from BaseDriver
|
|
1231
|
-
proxyActive() {
|
|
1232
|
-
return Boolean(this.jwpProxyActive);
|
|
1233
|
-
}
|
|
1234
|
-
getProxyAvoidList() {
|
|
1235
|
-
if (this.isWebview()) {
|
|
1236
|
-
return NO_PROXY_WEB_LIST;
|
|
1237
|
-
}
|
|
1238
|
-
return NO_PROXY_NATIVE_LIST;
|
|
1239
|
-
}
|
|
1240
|
-
canProxy() {
|
|
1241
|
-
return true;
|
|
1242
|
-
}
|
|
1243
|
-
/**
|
|
1244
|
-
* @returns {boolean}
|
|
1245
|
-
*/
|
|
1246
|
-
isSafari() {
|
|
1247
|
-
return !!this.safari;
|
|
1248
|
-
}
|
|
1249
|
-
/**
|
|
1250
|
-
* @returns {boolean}
|
|
1251
|
-
*/
|
|
1252
|
-
isRealDevice() {
|
|
1253
|
-
return 'devicectl' in (this.device ?? {});
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* @returns {boolean}
|
|
1257
|
-
*/
|
|
1258
|
-
isSimulator() {
|
|
1259
|
-
return 'simctl' in (this.device ?? {});
|
|
1260
|
-
}
|
|
1261
|
-
/**
|
|
1262
|
-
* @param {string} strategy
|
|
1263
|
-
*/
|
|
1264
|
-
validateLocatorStrategy(strategy) {
|
|
1265
|
-
super.validateLocatorStrategy(strategy, this.isWebContext());
|
|
1266
|
-
}
|
|
1267
|
-
/**
|
|
1268
|
-
* @param {any} caps
|
|
1269
|
-
* @returns {caps is import('@appium/types').DriverCaps<XCUITestDriverConstraints>}
|
|
1270
|
-
*/
|
|
1271
|
-
validateDesiredCaps(caps) {
|
|
1272
|
-
if (!super.validateDesiredCaps(caps)) {
|
|
1273
|
-
return false;
|
|
1274
|
-
}
|
|
1275
|
-
// make sure that the capabilities have one of `app` or `bundleId`
|
|
1276
|
-
if (lodash_1.default.toLower(caps.browserName) !== 'safari' && !caps.app && !caps.bundleId) {
|
|
1277
|
-
this.log.info('The desired capabilities include neither an app nor a bundleId. ' +
|
|
1278
|
-
'WebDriverAgent will be started without the default app');
|
|
1279
|
-
}
|
|
1280
|
-
if (!support_1.util.coerceVersion(String(caps.platformVersion), false)) {
|
|
1281
|
-
this.log.warn(`'platformVersion' capability ('${caps.platformVersion}') is not a valid version number. ` +
|
|
1282
|
-
`Consider fixing it or be ready to experience an inconsistent driver behavior.`);
|
|
1283
|
-
}
|
|
1284
|
-
let verifyProcessArgument = (processArguments) => {
|
|
1285
|
-
const { args, env } = processArguments;
|
|
1286
|
-
if (!lodash_1.default.isNil(args) && !lodash_1.default.isArray(args)) {
|
|
1287
|
-
throw this.log.errorWithException('processArguments.args must be an array of strings');
|
|
1288
|
-
}
|
|
1289
|
-
if (!lodash_1.default.isNil(env) && !lodash_1.default.isPlainObject(env)) {
|
|
1290
|
-
throw this.log.errorWithException('processArguments.env must be an object <key,value> pair {a:b, c:d}');
|
|
1291
|
-
}
|
|
1292
|
-
};
|
|
1293
|
-
// `processArguments` should be JSON string or an object with arguments and/ environment details
|
|
1294
|
-
if (caps.processArguments) {
|
|
1295
|
-
if (lodash_1.default.isString(caps.processArguments)) {
|
|
1296
|
-
try {
|
|
1297
|
-
// try to parse the string as JSON
|
|
1298
|
-
caps.processArguments = JSON.parse(caps.processArguments);
|
|
1299
|
-
verifyProcessArgument(caps.processArguments);
|
|
1300
|
-
}
|
|
1301
|
-
catch (err) {
|
|
1302
|
-
throw this.log.errorWithException(`processArguments must be a JSON format or an object with format {args : [], env : {a:b, c:d}}. ` +
|
|
1303
|
-
`Both environment and argument can be null. Error: ${err}`);
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
else if (lodash_1.default.isPlainObject(caps.processArguments)) {
|
|
1307
|
-
verifyProcessArgument(caps.processArguments);
|
|
1308
|
-
}
|
|
1309
|
-
else {
|
|
1310
|
-
throw this.log.errorWithException(`'processArguments must be an object, or a string JSON object with format {args : [], env : {a:b, c:d}}. ` +
|
|
1311
|
-
`Both environment and argument can be null.`);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
// there is no point in having `keychainPath` without `keychainPassword`
|
|
1315
|
-
if ((caps.keychainPath && !caps.keychainPassword) ||
|
|
1316
|
-
(!caps.keychainPath && caps.keychainPassword)) {
|
|
1317
|
-
throw this.log.errorWithException(`If 'keychainPath' is set, 'keychainPassword' must also be set (and vice versa).`);
|
|
1318
|
-
}
|
|
1319
|
-
// `resetOnSessionStartOnly` should be set to true by default
|
|
1320
|
-
this.opts.resetOnSessionStartOnly =
|
|
1321
|
-
!support_1.util.hasValue(this.opts.resetOnSessionStartOnly) || this.opts.resetOnSessionStartOnly;
|
|
1322
|
-
this.opts.useNewWDA = support_1.util.hasValue(this.opts.useNewWDA) ? this.opts.useNewWDA : false;
|
|
1323
|
-
if (caps.commandTimeouts) {
|
|
1324
|
-
caps.commandTimeouts = (0, utils_1.normalizeCommandTimeouts)(caps.commandTimeouts);
|
|
1325
|
-
}
|
|
1326
|
-
if (lodash_1.default.isString(caps.webDriverAgentUrl)) {
|
|
1327
|
-
const { protocol, host } = node_url_1.default.parse(caps.webDriverAgentUrl);
|
|
1328
|
-
if (lodash_1.default.isEmpty(protocol) || lodash_1.default.isEmpty(host)) {
|
|
1329
|
-
throw this.log.errorWithException(`'webDriverAgentUrl' capability is expected to contain a valid WebDriverAgent server URL. ` +
|
|
1330
|
-
`'${caps.webDriverAgentUrl}' is given instead`);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
if (caps.browserName) {
|
|
1334
|
-
if (caps.bundleId) {
|
|
1335
|
-
throw this.log.errorWithException(`'browserName' cannot be set together with 'bundleId' capability`);
|
|
1336
|
-
}
|
|
1337
|
-
// warn if the capabilities have both `app` and `browser, although this
|
|
1338
|
-
// is common with selenium grid
|
|
1339
|
-
if (caps.app) {
|
|
1340
|
-
this.log.warn(`The capabilities should generally not include both an 'app' and a 'browserName'`);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
if (caps.permissions) {
|
|
1344
|
-
try {
|
|
1345
|
-
for (const [bundleId, perms] of lodash_1.default.toPairs(JSON.parse(caps.permissions))) {
|
|
1346
|
-
if (!lodash_1.default.isString(bundleId)) {
|
|
1347
|
-
throw new Error(`'${JSON.stringify(bundleId)}' must be a string`);
|
|
1348
|
-
}
|
|
1349
|
-
if (!lodash_1.default.isPlainObject(perms)) {
|
|
1350
|
-
throw new Error(`'${JSON.stringify(perms)}' must be a JSON object`);
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
catch (e) {
|
|
1355
|
-
throw this.log.errorWithException(`'${caps.permissions}' is expected to be a valid object with format ` +
|
|
1356
|
-
`{"<bundleId1>": {"<serviceName1>": "<serviceStatus1>", ...}, ...}. Original error: ${e.message}`);
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
if (caps.platformVersion && !support_1.util.coerceVersion(caps.platformVersion, false)) {
|
|
1360
|
-
throw this.log.errorWithException(`'platformVersion' must be a valid version number. ` +
|
|
1361
|
-
`'${caps.platformVersion}' is given instead.`);
|
|
1362
|
-
}
|
|
1363
|
-
// additionalWebviewBundleIds is an array, JSON array, or string
|
|
1364
|
-
if (caps.additionalWebviewBundleIds) {
|
|
1365
|
-
caps.additionalWebviewBundleIds = this.helpers.parseCapsArray(caps.additionalWebviewBundleIds);
|
|
1366
|
-
}
|
|
1367
|
-
// finally, return true since the superclass check passed, as did this
|
|
1368
|
-
return true;
|
|
1369
|
-
}
|
|
1370
|
-
/**
|
|
1371
|
-
* Check if the given app can be installed, or should uninstall before installing it.
|
|
1372
|
-
*
|
|
1373
|
-
* @param {AutInstallationStateOptions} [opts]
|
|
1374
|
-
* @returns {Promise<AutInstallationState>}
|
|
1375
|
-
*/
|
|
1376
1271
|
async checkAutInstallationState(opts) {
|
|
1377
1272
|
const { enforceAppInstall, fullReset, noReset, bundleId, app } = opts ?? this.opts;
|
|
1378
|
-
const wasAppInstalled = await this.device.isAppInstalled(bundleId);
|
|
1273
|
+
const wasAppInstalled = !!bundleId && await this.device.isAppInstalled(bundleId);
|
|
1379
1274
|
if (wasAppInstalled) {
|
|
1380
1275
|
this.log.info(`App '${bundleId}' is already installed`);
|
|
1381
1276
|
if (noReset) {
|
|
@@ -1396,7 +1291,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1396
1291
|
skipUninstall: !wasAppInstalled,
|
|
1397
1292
|
};
|
|
1398
1293
|
}
|
|
1399
|
-
const candidateBundleVersion = await this.appInfosCache.extractBundleVersion(app);
|
|
1294
|
+
const candidateBundleVersion = app ? await this.appInfosCache.extractBundleVersion(app) : undefined;
|
|
1400
1295
|
this.log.debug(`CFBundleVersion from Info.plist: ${candidateBundleVersion}`);
|
|
1401
1296
|
if (!candidateBundleVersion) {
|
|
1402
1297
|
return {
|
|
@@ -1405,8 +1300,8 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1405
1300
|
};
|
|
1406
1301
|
}
|
|
1407
1302
|
const appBundleVersion = this.isRealDevice()
|
|
1408
|
-
? (await
|
|
1409
|
-
: BUNDLE_VERSION_PATTERN.exec(await
|
|
1303
|
+
? (await this.device.fetchAppInfo(bundleId))?.CFBundleVersion
|
|
1304
|
+
: BUNDLE_VERSION_PATTERN.exec(await this.device.simctl.appInfo(bundleId))?.[1];
|
|
1410
1305
|
this.log.debug(`CFBundleVersion from installed app info: ${appBundleVersion}`);
|
|
1411
1306
|
if (!appBundleVersion) {
|
|
1412
1307
|
return {
|
|
@@ -1463,19 +1358,14 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1463
1358
|
}
|
|
1464
1359
|
if (support_1.util.hasValue(this.opts.iosInstallPause)) {
|
|
1465
1360
|
// https://github.com/appium/appium/issues/6889
|
|
1466
|
-
const pauseMs =
|
|
1361
|
+
const pauseMs = this.opts.iosInstallPause;
|
|
1467
1362
|
this.log.debug(`iosInstallPause set. Pausing ${pauseMs} ms before continuing`);
|
|
1468
1363
|
await bluebird_1.default.delay(pauseMs);
|
|
1469
1364
|
}
|
|
1470
1365
|
this.logEvent('appInstalled');
|
|
1471
1366
|
}
|
|
1472
1367
|
}
|
|
1473
|
-
/**
|
|
1474
|
-
* @param {string|string[]} otherApps
|
|
1475
|
-
* @returns {Promise<void>}
|
|
1476
|
-
*/
|
|
1477
1368
|
async installOtherApps(otherApps) {
|
|
1478
|
-
/** @type {string[]|undefined} */
|
|
1479
1369
|
let appsList;
|
|
1480
1370
|
try {
|
|
1481
1371
|
appsList = this.helpers.parseCapsArray(otherApps);
|
|
@@ -1487,13 +1377,11 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1487
1377
|
this.log.info(`Got zero apps from 'otherApps' capability value. Doing nothing`);
|
|
1488
1378
|
return;
|
|
1489
1379
|
}
|
|
1490
|
-
/** @type {string[]} */
|
|
1491
1380
|
const appPaths = await bluebird_1.default.all(appsList.map((app) => this.helpers.configureApp(app, {
|
|
1492
1381
|
onPostProcess: app_utils_1.onPostConfigureApp.bind(this),
|
|
1493
1382
|
onDownload: app_utils_1.onDownloadApp.bind(this),
|
|
1494
1383
|
supportedExtensions: app_utils_1.SUPPORTED_EXTENSIONS,
|
|
1495
1384
|
})));
|
|
1496
|
-
/** @type {string[]} */
|
|
1497
1385
|
const appIds = await bluebird_1.default.all(appPaths.map((appPath) => this.appInfosCache.extractBundleId(appPath)));
|
|
1498
1386
|
for (const [appId, appPath] of lodash_1.default.zip(appIds, appPaths)) {
|
|
1499
1387
|
if (this.isRealDevice()) {
|
|
@@ -1509,10 +1397,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1509
1397
|
}
|
|
1510
1398
|
}
|
|
1511
1399
|
}
|
|
1512
|
-
/**
|
|
1513
|
-
* @param {string} orientation
|
|
1514
|
-
* @returns {Promise<void>}
|
|
1515
|
-
*/
|
|
1516
1400
|
async setInitialOrientation(orientation) {
|
|
1517
1401
|
const dstOrientation = lodash_1.default.toUpper(orientation);
|
|
1518
1402
|
if (!SUPPORTED_ORIENATIONS.includes(dstOrientation)) {
|
|
@@ -1528,21 +1412,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1528
1412
|
this.log.warn(`Setting initial orientation failed with: ${err.message}`);
|
|
1529
1413
|
}
|
|
1530
1414
|
}
|
|
1531
|
-
/**
|
|
1532
|
-
* @param {string} [cmdName]
|
|
1533
|
-
* @returns {number|undefined}
|
|
1534
|
-
*/
|
|
1535
|
-
_getCommandTimeout(cmdName) {
|
|
1536
|
-
if (this.opts.commandTimeouts) {
|
|
1537
|
-
if (cmdName && lodash_1.default.has(this.opts.commandTimeouts, cmdName)) {
|
|
1538
|
-
return this.opts.commandTimeouts[cmdName];
|
|
1539
|
-
}
|
|
1540
|
-
return this.opts.commandTimeouts[utils_1.DEFAULT_TIMEOUT_KEY];
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
/**
|
|
1544
|
-
* Reset the current session (run the delete session and create session subroutines)
|
|
1545
|
-
*/
|
|
1546
1415
|
async reset() {
|
|
1547
1416
|
throw new Error(`The reset API has been deprecated and is not supported anymore. ` +
|
|
1548
1417
|
`Consider using corresponding 'mobile:' extensions to manage the state of the app under test.`);
|
|
@@ -1571,6 +1440,41 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1571
1440
|
await simulator_management_1.installToSimulator.bind(this)(this.opts.prebuiltWDAPath, candidateBundleId);
|
|
1572
1441
|
}
|
|
1573
1442
|
}
|
|
1443
|
+
resetIos() {
|
|
1444
|
+
this.opts = this.opts || {};
|
|
1445
|
+
this._wda = null;
|
|
1446
|
+
this.jwpProxyActive = false;
|
|
1447
|
+
this.proxyReqRes = null;
|
|
1448
|
+
this.safari = false;
|
|
1449
|
+
this.cachedWdaStatus = null;
|
|
1450
|
+
this.curWebFrames = [];
|
|
1451
|
+
this._currentUrl = null;
|
|
1452
|
+
this.curContext = null;
|
|
1453
|
+
this.xcodeVersion = undefined;
|
|
1454
|
+
this.contexts = [];
|
|
1455
|
+
this.implicitWaitMs = 0;
|
|
1456
|
+
this.pageLoadMs = 6000;
|
|
1457
|
+
this.landscapeWebCoordsOffset = 0;
|
|
1458
|
+
this.remote = null;
|
|
1459
|
+
this._conditionInducerService = null;
|
|
1460
|
+
this._remoteXPCConditionInducerConnection = null;
|
|
1461
|
+
this.webElementsCache = new lru_cache_1.LRUCache({
|
|
1462
|
+
max: WEB_ELEMENTS_CACHE_SIZE,
|
|
1463
|
+
});
|
|
1464
|
+
this._waitingAtoms = {
|
|
1465
|
+
count: 0,
|
|
1466
|
+
alertNotifier: new node_events_1.default(),
|
|
1467
|
+
alertMonitor: bluebird_1.default.resolve(),
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
_getCommandTimeout(cmdName) {
|
|
1471
|
+
if (this.opts.commandTimeouts) {
|
|
1472
|
+
if (cmdName && lodash_1.default.has(this.opts.commandTimeouts, cmdName)) {
|
|
1473
|
+
return this.opts.commandTimeouts[cmdName];
|
|
1474
|
+
}
|
|
1475
|
+
return this.opts.commandTimeouts[utils_1.DEFAULT_TIMEOUT_KEY];
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1574
1478
|
/*---------------+
|
|
1575
1479
|
| ACTIVEAPPINFO |
|
|
1576
1480
|
+---------------+*/
|
|
@@ -1946,32 +1850,4 @@ class XCUITestDriver extends driver_1.BaseDriver {
|
|
|
1946
1850
|
}
|
|
1947
1851
|
exports.XCUITestDriver = XCUITestDriver;
|
|
1948
1852
|
exports.default = XCUITestDriver;
|
|
1949
|
-
/**
|
|
1950
|
-
* @template {import('@appium/types').Constraints} C
|
|
1951
|
-
* @template [Ctx=string]
|
|
1952
|
-
* @typedef {import('@appium/types').ExternalDriver<C, Ctx>} ExternalDriver
|
|
1953
|
-
*/
|
|
1954
|
-
/**
|
|
1955
|
-
* @typedef {Pick<XCUITestDriverOpts, 'enforceAppInstall' | 'fullReset' | 'noReset' | 'bundleId' | 'app'>} AutInstallationStateOptions
|
|
1956
|
-
*/
|
|
1957
|
-
/**
|
|
1958
|
-
* @typedef {Object} AutInstallationState
|
|
1959
|
-
* @property {boolean} install - If the given app should install, or not need to install.
|
|
1960
|
-
* @property {boolean} skipUninstall - If the installed app should be uninstalled, or not.
|
|
1961
|
-
*/
|
|
1962
|
-
/**
|
|
1963
|
-
* @typedef {typeof desiredCapConstraints} XCUITestDriverConstraints
|
|
1964
|
-
* @typedef {import('@appium/types').DriverOpts<XCUITestDriverConstraints>} XCUITestDriverOpts
|
|
1965
|
-
* @typedef {import('./commands/types').FullContext} FullContext
|
|
1966
|
-
* @typedef {import('appium-xcode').XcodeVersion} XcodeVersion
|
|
1967
|
-
* @typedef {import('appium-ios-simulator').Simulator} Simulator
|
|
1968
|
-
*/
|
|
1969
|
-
/**
|
|
1970
|
-
* @typedef {Object} DriverLogs
|
|
1971
|
-
* @property {import('./device-log/ios-device-log').IOSDeviceLog|import('./device-log/ios-simulator-log').IOSSimulatorLog} [syslog]
|
|
1972
|
-
* @property {import('./device-log/ios-crash-log').IOSCrashLog} [crashlog]
|
|
1973
|
-
* @property {import('./device-log/safari-console-log').SafariConsoleLog} [safariConsole]
|
|
1974
|
-
* @property {import('./device-log/safari-network-log').SafariNetworkLog} [safariNetwork]
|
|
1975
|
-
* @property {import('./device-log/ios-performance-log').IOSPerformanceLog} [performance]
|
|
1976
|
-
*/
|
|
1977
1853
|
//# sourceMappingURL=driver.js.map
|