@limrun/appium-xcuitest-driver 10.4.3-lim.1
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 +2600 -0
- package/LICENSE +201 -0
- package/README.md +55 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +41 -0
- package/build/lib/app-infos-cache.d.ts +62 -0
- package/build/lib/app-infos-cache.d.ts.map +1 -0
- package/build/lib/app-infos-cache.js +180 -0
- package/build/lib/app-infos-cache.js.map +1 -0
- package/build/lib/app-utils.d.ts +89 -0
- package/build/lib/app-utils.d.ts.map +1 -0
- package/build/lib/app-utils.js +657 -0
- package/build/lib/app-utils.js.map +1 -0
- package/build/lib/commands/active-app-info.d.ts +9 -0
- package/build/lib/commands/active-app-info.d.ts.map +1 -0
- package/build/lib/commands/active-app-info.js +14 -0
- package/build/lib/commands/active-app-info.js.map +1 -0
- package/build/lib/commands/advanced-battery-types.d.ts +444 -0
- package/build/lib/commands/advanced-battery-types.d.ts.map +1 -0
- package/build/lib/commands/advanced-battery-types.js +8 -0
- package/build/lib/commands/advanced-battery-types.js.map +1 -0
- package/build/lib/commands/alert.d.ts +45 -0
- package/build/lib/commands/alert.d.ts.map +1 -0
- package/build/lib/commands/alert.js +87 -0
- package/build/lib/commands/alert.js.map +1 -0
- package/build/lib/commands/app-management.d.ts +153 -0
- package/build/lib/commands/app-management.d.ts.map +1 -0
- package/build/lib/commands/app-management.js +323 -0
- package/build/lib/commands/app-management.js.map +1 -0
- package/build/lib/commands/app-strings.d.ts +16 -0
- package/build/lib/commands/app-strings.d.ts.map +1 -0
- package/build/lib/commands/app-strings.js +30 -0
- package/build/lib/commands/app-strings.js.map +1 -0
- package/build/lib/commands/appearance.d.ts +22 -0
- package/build/lib/commands/appearance.d.ts.map +1 -0
- package/build/lib/commands/appearance.js +74 -0
- package/build/lib/commands/appearance.js.map +1 -0
- package/build/lib/commands/audit.d.ts +43 -0
- package/build/lib/commands/audit.d.ts.map +1 -0
- package/build/lib/commands/audit.js +31 -0
- package/build/lib/commands/audit.js.map +1 -0
- package/build/lib/commands/battery.d.ts +13 -0
- package/build/lib/commands/battery.d.ts.map +1 -0
- package/build/lib/commands/battery.js +49 -0
- package/build/lib/commands/battery.js.map +1 -0
- package/build/lib/commands/bidi/constants.d.ts +6 -0
- package/build/lib/commands/bidi/constants.d.ts.map +1 -0
- package/build/lib/commands/bidi/constants.js +10 -0
- package/build/lib/commands/bidi/constants.js.map +1 -0
- package/build/lib/commands/bidi/models.d.ts +9 -0
- package/build/lib/commands/bidi/models.d.ts.map +1 -0
- package/build/lib/commands/bidi/models.js +54 -0
- package/build/lib/commands/bidi/models.js.map +1 -0
- package/build/lib/commands/bidi/types.d.ts +26 -0
- package/build/lib/commands/bidi/types.d.ts.map +1 -0
- package/build/lib/commands/bidi/types.js +4 -0
- package/build/lib/commands/bidi/types.js.map +1 -0
- package/build/lib/commands/biometric.d.ts +32 -0
- package/build/lib/commands/biometric.d.ts.map +1 -0
- package/build/lib/commands/biometric.js +54 -0
- package/build/lib/commands/biometric.js.map +1 -0
- package/build/lib/commands/certificate.d.ts +50 -0
- package/build/lib/commands/certificate.d.ts.map +1 -0
- package/build/lib/commands/certificate.js +454 -0
- package/build/lib/commands/certificate.js.map +1 -0
- package/build/lib/commands/clipboard.d.ts +21 -0
- package/build/lib/commands/clipboard.d.ts.map +1 -0
- package/build/lib/commands/clipboard.js +36 -0
- package/build/lib/commands/clipboard.js.map +1 -0
- package/build/lib/commands/condition.d.ts +102 -0
- package/build/lib/commands/condition.d.ts.map +1 -0
- package/build/lib/commands/condition.js +146 -0
- package/build/lib/commands/condition.js.map +1 -0
- package/build/lib/commands/content-size.d.ts +30 -0
- package/build/lib/commands/content-size.d.ts.map +1 -0
- package/build/lib/commands/content-size.js +67 -0
- package/build/lib/commands/content-size.js.map +1 -0
- package/build/lib/commands/context.d.ts +191 -0
- package/build/lib/commands/context.d.ts.map +1 -0
- package/build/lib/commands/context.js +625 -0
- package/build/lib/commands/context.js.map +1 -0
- package/build/lib/commands/deviceInfo.d.ts +12 -0
- package/build/lib/commands/deviceInfo.d.ts.map +1 -0
- package/build/lib/commands/deviceInfo.js +25 -0
- package/build/lib/commands/deviceInfo.js.map +1 -0
- package/build/lib/commands/element.d.ts +108 -0
- package/build/lib/commands/element.d.ts.map +1 -0
- package/build/lib/commands/element.js +395 -0
- package/build/lib/commands/element.js.map +1 -0
- package/build/lib/commands/enum.d.ts +105 -0
- package/build/lib/commands/enum.d.ts.map +1 -0
- package/build/lib/commands/enum.js +113 -0
- package/build/lib/commands/enum.js.map +1 -0
- package/build/lib/commands/execute.d.ts +33 -0
- package/build/lib/commands/execute.d.ts.map +1 -0
- package/build/lib/commands/execute.js +142 -0
- package/build/lib/commands/execute.js.map +1 -0
- package/build/lib/commands/file-movement.d.ts +90 -0
- package/build/lib/commands/file-movement.d.ts.map +1 -0
- package/build/lib/commands/file-movement.js +477 -0
- package/build/lib/commands/file-movement.js.map +1 -0
- package/build/lib/commands/find.d.ts +21 -0
- package/build/lib/commands/find.d.ts.map +1 -0
- package/build/lib/commands/find.js +199 -0
- package/build/lib/commands/find.js.map +1 -0
- package/build/lib/commands/general.d.ts +137 -0
- package/build/lib/commands/general.d.ts.map +1 -0
- package/build/lib/commands/general.js +270 -0
- package/build/lib/commands/general.js.map +1 -0
- package/build/lib/commands/geolocation.d.ts +57 -0
- package/build/lib/commands/geolocation.d.ts.map +1 -0
- package/build/lib/commands/geolocation.js +58 -0
- package/build/lib/commands/geolocation.js.map +1 -0
- package/build/lib/commands/gesture.d.ts +283 -0
- package/build/lib/commands/gesture.d.ts.map +1 -0
- package/build/lib/commands/gesture.js +565 -0
- package/build/lib/commands/gesture.js.map +1 -0
- package/build/lib/commands/hid-event.d.ts +2773 -0
- package/build/lib/commands/hid-event.d.ts.map +1 -0
- package/build/lib/commands/hid-event.js +1633 -0
- package/build/lib/commands/hid-event.js.map +1 -0
- package/build/lib/commands/increase-contrast.d.ts +24 -0
- package/build/lib/commands/increase-contrast.d.ts.map +1 -0
- package/build/lib/commands/increase-contrast.js +49 -0
- package/build/lib/commands/increase-contrast.js.map +1 -0
- package/build/lib/commands/iohid.d.ts +1372 -0
- package/build/lib/commands/iohid.d.ts.map +1 -0
- package/build/lib/commands/iohid.js +63 -0
- package/build/lib/commands/iohid.js.map +1 -0
- package/build/lib/commands/keyboard.d.ts +32 -0
- package/build/lib/commands/keyboard.d.ts.map +1 -0
- package/build/lib/commands/keyboard.js +67 -0
- package/build/lib/commands/keyboard.js.map +1 -0
- package/build/lib/commands/keychains.d.ts +10 -0
- package/build/lib/commands/keychains.d.ts.map +1 -0
- package/build/lib/commands/keychains.js +22 -0
- package/build/lib/commands/keychains.js.map +1 -0
- package/build/lib/commands/localization.d.ts +17 -0
- package/build/lib/commands/localization.d.ts.map +1 -0
- package/build/lib/commands/localization.js +34 -0
- package/build/lib/commands/localization.js.map +1 -0
- package/build/lib/commands/location.d.ts +40 -0
- package/build/lib/commands/location.d.ts.map +1 -0
- package/build/lib/commands/location.js +121 -0
- package/build/lib/commands/location.js.map +1 -0
- package/build/lib/commands/lock.d.ts +23 -0
- package/build/lib/commands/lock.d.ts.map +1 -0
- package/build/lib/commands/lock.js +49 -0
- package/build/lib/commands/lock.js.map +1 -0
- package/build/lib/commands/log.d.ts +68 -0
- package/build/lib/commands/log.d.ts.map +1 -0
- package/build/lib/commands/log.js +287 -0
- package/build/lib/commands/log.js.map +1 -0
- package/build/lib/commands/memory.d.ts +11 -0
- package/build/lib/commands/memory.d.ts.map +1 -0
- package/build/lib/commands/memory.js +49 -0
- package/build/lib/commands/memory.js.map +1 -0
- package/build/lib/commands/navigation.d.ts +44 -0
- package/build/lib/commands/navigation.d.ts.map +1 -0
- package/build/lib/commands/navigation.js +121 -0
- package/build/lib/commands/navigation.js.map +1 -0
- package/build/lib/commands/notifications.d.ts +28 -0
- package/build/lib/commands/notifications.d.ts.map +1 -0
- package/build/lib/commands/notifications.js +64 -0
- package/build/lib/commands/notifications.js.map +1 -0
- package/build/lib/commands/pasteboard.d.ts +23 -0
- package/build/lib/commands/pasteboard.d.ts.map +1 -0
- package/build/lib/commands/pasteboard.js +43 -0
- package/build/lib/commands/pasteboard.js.map +1 -0
- package/build/lib/commands/pcap.d.ts +54 -0
- package/build/lib/commands/pcap.d.ts.map +1 -0
- package/build/lib/commands/pcap.js +149 -0
- package/build/lib/commands/pcap.js.map +1 -0
- package/build/lib/commands/performance.d.ts +85 -0
- package/build/lib/commands/performance.d.ts.map +1 -0
- package/build/lib/commands/performance.js +331 -0
- package/build/lib/commands/performance.js.map +1 -0
- package/build/lib/commands/permissions.d.ts +36 -0
- package/build/lib/commands/permissions.d.ts.map +1 -0
- package/build/lib/commands/permissions.js +80 -0
- package/build/lib/commands/permissions.js.map +1 -0
- package/build/lib/commands/proxy-helper.d.ts +15 -0
- package/build/lib/commands/proxy-helper.d.ts.map +1 -0
- package/build/lib/commands/proxy-helper.js +117 -0
- package/build/lib/commands/proxy-helper.js.map +1 -0
- package/build/lib/commands/record-audio.d.ts +69 -0
- package/build/lib/commands/record-audio.d.ts.map +1 -0
- package/build/lib/commands/record-audio.js +228 -0
- package/build/lib/commands/record-audio.js.map +1 -0
- package/build/lib/commands/recordscreen.d.ts +89 -0
- package/build/lib/commands/recordscreen.d.ts.map +1 -0
- package/build/lib/commands/recordscreen.js +326 -0
- package/build/lib/commands/recordscreen.js.map +1 -0
- package/build/lib/commands/screenshots.d.ts +16 -0
- package/build/lib/commands/screenshots.d.ts.map +1 -0
- package/build/lib/commands/screenshots.js +129 -0
- package/build/lib/commands/screenshots.js.map +1 -0
- package/build/lib/commands/simctl.d.ts +27 -0
- package/build/lib/commands/simctl.d.ts.map +1 -0
- package/build/lib/commands/simctl.js +65 -0
- package/build/lib/commands/simctl.js.map +1 -0
- package/build/lib/commands/source.d.ts +16 -0
- package/build/lib/commands/source.d.ts.map +1 -0
- package/build/lib/commands/source.js +128 -0
- package/build/lib/commands/source.js.map +1 -0
- package/build/lib/commands/timeouts.d.ts +53 -0
- package/build/lib/commands/timeouts.d.ts.map +1 -0
- package/build/lib/commands/timeouts.js +71 -0
- package/build/lib/commands/timeouts.js.map +1 -0
- package/build/lib/commands/types.d.ts +539 -0
- package/build/lib/commands/types.d.ts.map +1 -0
- package/build/lib/commands/types.js +3 -0
- package/build/lib/commands/types.js.map +1 -0
- package/build/lib/commands/web.d.ts +297 -0
- package/build/lib/commands/web.d.ts.map +1 -0
- package/build/lib/commands/web.js +1029 -0
- package/build/lib/commands/web.js.map +1 -0
- package/build/lib/commands/xctest-record-screen.d.ts +92 -0
- package/build/lib/commands/xctest-record-screen.d.ts.map +1 -0
- package/build/lib/commands/xctest-record-screen.js +193 -0
- package/build/lib/commands/xctest-record-screen.js.map +1 -0
- package/build/lib/commands/xctest.d.ts +71 -0
- package/build/lib/commands/xctest.d.ts.map +1 -0
- package/build/lib/commands/xctest.js +257 -0
- package/build/lib/commands/xctest.js.map +1 -0
- package/build/lib/css-converter.d.ts +10 -0
- package/build/lib/css-converter.d.ts.map +1 -0
- package/build/lib/css-converter.js +258 -0
- package/build/lib/css-converter.js.map +1 -0
- package/build/lib/desired-caps.d.ts +506 -0
- package/build/lib/desired-caps.d.ts.map +1 -0
- package/build/lib/desired-caps.js +400 -0
- package/build/lib/desired-caps.js.map +1 -0
- package/build/lib/device-connections-factory.d.ts +13 -0
- package/build/lib/device-connections-factory.d.ts.map +1 -0
- package/build/lib/device-connections-factory.js +244 -0
- package/build/lib/device-connections-factory.js.map +1 -0
- package/build/lib/device-log/helpers.d.ts +10 -0
- package/build/lib/device-log/helpers.d.ts.map +1 -0
- package/build/lib/device-log/helpers.js +37 -0
- package/build/lib/device-log/helpers.js.map +1 -0
- package/build/lib/device-log/ios-crash-log.d.ts +34 -0
- package/build/lib/device-log/ios-crash-log.d.ts.map +1 -0
- package/build/lib/device-log/ios-crash-log.js +141 -0
- package/build/lib/device-log/ios-crash-log.js.map +1 -0
- package/build/lib/device-log/ios-device-log.d.ts +19 -0
- package/build/lib/device-log/ios-device-log.d.ts.map +1 -0
- package/build/lib/device-log/ios-device-log.js +42 -0
- package/build/lib/device-log/ios-device-log.js.map +1 -0
- package/build/lib/device-log/ios-log.d.ts +24 -0
- package/build/lib/device-log/ios-log.d.ts.map +1 -0
- package/build/lib/device-log/ios-log.js +50 -0
- package/build/lib/device-log/ios-log.js.map +1 -0
- package/build/lib/device-log/ios-performance-log.d.ts +18 -0
- package/build/lib/device-log/ios-performance-log.d.ts.map +1 -0
- package/build/lib/device-log/ios-performance-log.js +43 -0
- package/build/lib/device-log/ios-performance-log.js.map +1 -0
- package/build/lib/device-log/ios-simulator-log.d.ts +38 -0
- package/build/lib/device-log/ios-simulator-log.d.ts.map +1 -0
- package/build/lib/device-log/ios-simulator-log.js +184 -0
- package/build/lib/device-log/ios-simulator-log.js.map +1 -0
- package/build/lib/device-log/line-consuming-log.d.ts +9 -0
- package/build/lib/device-log/line-consuming-log.d.ts.map +1 -0
- package/build/lib/device-log/line-consuming-log.js +16 -0
- package/build/lib/device-log/line-consuming-log.js.map +1 -0
- package/build/lib/device-log/safari-console-log.d.ts +67 -0
- package/build/lib/device-log/safari-console-log.d.ts.map +1 -0
- package/build/lib/device-log/safari-console-log.js +81 -0
- package/build/lib/device-log/safari-console-log.js.map +1 -0
- package/build/lib/device-log/safari-network-log.d.ts +75 -0
- package/build/lib/device-log/safari-network-log.d.ts.map +1 -0
- package/build/lib/device-log/safari-network-log.js +47 -0
- package/build/lib/device-log/safari-network-log.js.map +1 -0
- package/build/lib/doctor/checks.d.ts +3 -0
- package/build/lib/doctor/checks.d.ts.map +1 -0
- package/build/lib/doctor/checks.js +39 -0
- package/build/lib/doctor/checks.js.map +1 -0
- package/build/lib/doctor/optional-checks.d.ts +46 -0
- package/build/lib/doctor/optional-checks.d.ts.map +1 -0
- package/build/lib/doctor/optional-checks.js +129 -0
- package/build/lib/doctor/optional-checks.js.map +1 -0
- package/build/lib/doctor/required-checks.d.ts +42 -0
- package/build/lib/doctor/required-checks.d.ts.map +1 -0
- package/build/lib/doctor/required-checks.js +94 -0
- package/build/lib/doctor/required-checks.js.map +1 -0
- package/build/lib/doctor/utils.d.ts +8 -0
- package/build/lib/doctor/utils.d.ts.map +1 -0
- package/build/lib/doctor/utils.js +21 -0
- package/build/lib/doctor/utils.js.map +1 -0
- package/build/lib/driver.d.ts +2429 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +1967 -0
- package/build/lib/driver.js.map +1 -0
- package/build/lib/execute-method-map.d.ts +552 -0
- package/build/lib/execute-method-map.d.ts.map +1 -0
- package/build/lib/execute-method-map.js +586 -0
- package/build/lib/execute-method-map.js.map +1 -0
- package/build/lib/ios-fs-helpers.d.ts +75 -0
- package/build/lib/ios-fs-helpers.d.ts.map +1 -0
- package/build/lib/ios-fs-helpers.js +370 -0
- package/build/lib/ios-fs-helpers.js.map +1 -0
- package/build/lib/ios-generic-simulators.d.ts +6 -0
- package/build/lib/ios-generic-simulators.d.ts.map +1 -0
- package/build/lib/ios-generic-simulators.js +14 -0
- package/build/lib/ios-generic-simulators.js.map +1 -0
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +6 -0
- package/build/lib/logger.js.map +1 -0
- package/build/lib/method-map.d.ts +229 -0
- package/build/lib/method-map.d.ts.map +1 -0
- package/build/lib/method-map.js +200 -0
- package/build/lib/method-map.js.map +1 -0
- package/build/lib/real-device-clients/base-device-client.d.ts +22 -0
- package/build/lib/real-device-clients/base-device-client.d.ts.map +1 -0
- package/build/lib/real-device-clients/base-device-client.js +14 -0
- package/build/lib/real-device-clients/base-device-client.js.map +1 -0
- package/build/lib/real-device-clients/py-ios-device-client.d.ts +21 -0
- package/build/lib/real-device-clients/py-ios-device-client.d.ts.map +1 -0
- package/build/lib/real-device-clients/py-ios-device-client.js +125 -0
- package/build/lib/real-device-clients/py-ios-device-client.js.map +1 -0
- package/build/lib/real-device-management.d.ts +53 -0
- package/build/lib/real-device-management.d.ts.map +1 -0
- package/build/lib/real-device-management.js +128 -0
- package/build/lib/real-device-management.js.map +1 -0
- package/build/lib/real-device.d.ts +112 -0
- package/build/lib/real-device.d.ts.map +1 -0
- package/build/lib/real-device.js +352 -0
- package/build/lib/real-device.js.map +1 -0
- package/build/lib/simulator-management.d.ts +96 -0
- package/build/lib/simulator-management.d.ts.map +1 -0
- package/build/lib/simulator-management.js +278 -0
- package/build/lib/simulator-management.js.map +1 -0
- package/build/lib/stubs.d.ts +3 -0
- package/build/lib/stubs.d.ts.map +1 -0
- package/build/lib/stubs.js +3 -0
- package/build/lib/stubs.js.map +1 -0
- package/build/lib/types.d.ts +31 -0
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/types.js +3 -0
- package/build/lib/types.js.map +1 -0
- package/build/lib/utils.d.ts +191 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +549 -0
- package/build/lib/utils.js.map +1 -0
- package/build/lib/xcrun.d.ts +3 -0
- package/build/lib/xcrun.d.ts.map +1 -0
- package/build/lib/xcrun.js +17 -0
- package/build/lib/xcrun.js.map +1 -0
- package/index.js +7 -0
- package/lib/app-infos-cache.js +187 -0
- package/lib/app-utils.js +710 -0
- package/lib/commands/active-app-info.js +12 -0
- package/lib/commands/advanced-battery-types.ts +454 -0
- package/lib/commands/alert.js +88 -0
- package/lib/commands/app-management.js +346 -0
- package/lib/commands/app-strings.js +30 -0
- package/lib/commands/appearance.js +71 -0
- package/lib/commands/audit.js +31 -0
- package/lib/commands/battery.js +45 -0
- package/lib/commands/bidi/constants.ts +6 -0
- package/lib/commands/bidi/models.ts +55 -0
- package/lib/commands/bidi/types.ts +31 -0
- package/lib/commands/biometric.js +53 -0
- package/lib/commands/certificate.js +497 -0
- package/lib/commands/clipboard.js +35 -0
- package/lib/commands/condition.js +155 -0
- package/lib/commands/content-size.js +68 -0
- package/lib/commands/context.js +705 -0
- package/lib/commands/deviceInfo.js +27 -0
- package/lib/commands/element.js +423 -0
- package/lib/commands/enum.ts +108 -0
- package/lib/commands/execute.js +153 -0
- package/lib/commands/file-movement.js +510 -0
- package/lib/commands/find.js +205 -0
- package/lib/commands/general.js +278 -0
- package/lib/commands/geolocation.js +56 -0
- package/lib/commands/gesture.js +596 -0
- package/lib/commands/hid-event.ts +1634 -0
- package/lib/commands/increase-contrast.js +50 -0
- package/lib/commands/iohid.js +64 -0
- package/lib/commands/keyboard.js +62 -0
- package/lib/commands/keychains.js +18 -0
- package/lib/commands/localization.js +30 -0
- package/lib/commands/location.js +131 -0
- package/lib/commands/lock.js +46 -0
- package/lib/commands/log.js +327 -0
- package/lib/commands/memory.js +51 -0
- package/lib/commands/navigation.js +125 -0
- package/lib/commands/notifications.js +66 -0
- package/lib/commands/pasteboard.js +42 -0
- package/lib/commands/pcap.js +168 -0
- package/lib/commands/performance.js +392 -0
- package/lib/commands/permissions.js +85 -0
- package/lib/commands/proxy-helper.js +122 -0
- package/lib/commands/record-audio.js +264 -0
- package/lib/commands/recordscreen.js +391 -0
- package/lib/commands/screenshots.js +137 -0
- package/lib/commands/simctl.js +71 -0
- package/lib/commands/source.js +131 -0
- package/lib/commands/timeouts.js +68 -0
- package/lib/commands/types.ts +648 -0
- package/lib/commands/web.js +1113 -0
- package/lib/commands/xctest-record-screen.js +204 -0
- package/lib/commands/xctest.js +285 -0
- package/lib/css-converter.js +311 -0
- package/lib/desired-caps.js +396 -0
- package/lib/device-connections-factory.js +269 -0
- package/lib/device-log/helpers.ts +40 -0
- package/lib/device-log/ios-crash-log.ts +166 -0
- package/lib/device-log/ios-device-log.ts +51 -0
- package/lib/device-log/ios-log.ts +70 -0
- package/lib/device-log/ios-performance-log.ts +50 -0
- package/lib/device-log/ios-simulator-log.ts +202 -0
- package/lib/device-log/line-consuming-log.ts +16 -0
- package/lib/device-log/safari-console-log.ts +117 -0
- package/lib/device-log/safari-network-log.ts +120 -0
- package/lib/doctor/checks.ts +3 -0
- package/lib/doctor/optional-checks.ts +173 -0
- package/lib/doctor/required-checks.ts +120 -0
- package/lib/doctor/utils.ts +18 -0
- package/lib/driver.js +2316 -0
- package/lib/execute-method-map.ts +585 -0
- package/lib/ios-fs-helpers.js +355 -0
- package/lib/ios-generic-simulators.js +11 -0
- package/lib/logger.js +5 -0
- package/lib/method-map.js +196 -0
- package/lib/real-device-clients/base-device-client.ts +34 -0
- package/lib/real-device-clients/py-ios-device-client.ts +149 -0
- package/lib/real-device-management.js +133 -0
- package/lib/real-device.js +347 -0
- package/lib/simulator-management.js +324 -0
- package/lib/stubs.ts +3 -0
- package/lib/types.ts +33 -0
- package/lib/utils.js +551 -0
- package/lib/xcrun.js +16 -0
- package/package.json +175 -0
- package/scripts/build-docs.js +56 -0
- package/scripts/build-wda.js +42 -0
- package/scripts/download-wda-sim.mjs +68 -0
- package/scripts/image-mounter.mjs +239 -0
- package/scripts/open-wda.mjs +15 -0
- package/scripts/tunnel-creation.mjs +359 -0
- package/scripts/utils.js +16 -0
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
import {createRemoteDebugger, RemoteDebugger} from 'appium-remote-debugger';
|
|
2
|
+
import {errors, isErrorType} from 'appium/driver';
|
|
3
|
+
import {util, timing} from 'appium/support';
|
|
4
|
+
import {IOSPerformanceLog} from '../device-log/ios-performance-log';
|
|
5
|
+
import _ from 'lodash';
|
|
6
|
+
import { NATIVE_WIN } from '../utils';
|
|
7
|
+
import {
|
|
8
|
+
makeContextUpdatedEvent,
|
|
9
|
+
makeObsoleteContextUpdatedEvent,
|
|
10
|
+
} from './bidi/models';
|
|
11
|
+
import { BIDI_EVENT_NAME } from './bidi/constants';
|
|
12
|
+
import { assignBiDiLogListener } from './log';
|
|
13
|
+
|
|
14
|
+
const WEBVIEW_WIN = 'WEBVIEW';
|
|
15
|
+
const WEBVIEW_BASE = `${WEBVIEW_WIN}_`;
|
|
16
|
+
const DEFAULT_REMOTE_DEBUGGER_CONNECT_TIMEOUT_MS = 5000;
|
|
17
|
+
const DEFAULT_LIST_WEB_FRAMES_RETRIES = 20;
|
|
18
|
+
const DEFAULT_NATIVE_WINDOW_HANDLE = '1';
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @this {XCUITestDriver}
|
|
23
|
+
* @param {boolean} [useUrl=false]
|
|
24
|
+
* @returns {Promise<import('./types').ViewContext[]>}
|
|
25
|
+
*/
|
|
26
|
+
export async function getContextsAndViews(useUrl = true) {
|
|
27
|
+
this.log.debug('Retrieving contexts and views');
|
|
28
|
+
const webviews = await this.listWebFrames(useUrl);
|
|
29
|
+
/**
|
|
30
|
+
* @type {import('./types').ViewContext[]}
|
|
31
|
+
*/
|
|
32
|
+
const ctxs = [{id: NATIVE_WIN, view: {}}];
|
|
33
|
+
this.contexts = [NATIVE_WIN];
|
|
34
|
+
for (const view of webviews) {
|
|
35
|
+
ctxs.push({id: `${WEBVIEW_BASE}${view.id}`, view});
|
|
36
|
+
this.contexts.push(view.id.toString());
|
|
37
|
+
}
|
|
38
|
+
return ctxs;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated this method is not used anywhere and will be removed in the future
|
|
43
|
+
* @this {XCUITestDriver}
|
|
44
|
+
* @returns {boolean}
|
|
45
|
+
*/
|
|
46
|
+
export function useNewSafari() {
|
|
47
|
+
return this.isSimulator() && this.isSafari();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @this {XCUITestDriver}
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
export async function activateRecentWebview() {
|
|
55
|
+
this.log.debug('Activating a recent webview');
|
|
56
|
+
const timer = new timing.Timer().start();
|
|
57
|
+
const contextId = await this.getRecentWebviewContextId(/.*/, /.*/);
|
|
58
|
+
if (contextId) {
|
|
59
|
+
this.log.info(`Picking webview '${contextId}' after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
60
|
+
await this.setContext(contextId);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const appDict = (/** @type {RemoteDebugger} */ (this.remote)).appDict;
|
|
64
|
+
const errSuffix = `Make sure your web application is debuggable ` +
|
|
65
|
+
`and could be inspected in Safari Web Inspector.`;
|
|
66
|
+
if (_.isEmpty(appDict)) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`The remote debugger did not return any connected web applications after ` +
|
|
69
|
+
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms. ` +
|
|
70
|
+
`${errSuffix} ` +
|
|
71
|
+
`You may try to change the 'webviewConnectTimeout' capability value to ` +
|
|
72
|
+
`customize the retrieval timeout.`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
const errSuffix2 = `${errSuffix} You may try to change the 'webviewConnectRetries' ` +
|
|
76
|
+
`capability value to customize the amount of pages retrieval retries.`;
|
|
77
|
+
const appsWithPages = _.values(appDict).filter(({pageArray}) => !_.isEmpty(pageArray));
|
|
78
|
+
if (appsWithPages.length > 0) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`The remote debugger returned ${util.pluralize('web application', appsWithPages.length, true)} ` +
|
|
81
|
+
`with pages after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms, ` +
|
|
82
|
+
`although none of them matched our page search criteria. ${errSuffix2}`
|
|
83
|
+
);
|
|
84
|
+
} else {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`The remote debugger returned ${util.pluralize('web application', _.size(appDict), true)}, ` +
|
|
87
|
+
`but none of them had pages after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms. ` +
|
|
88
|
+
`${errSuffix2} Also, in rare cases the device restart or device OS upgrade may fix this ` +
|
|
89
|
+
`issue if none of the above advices helps.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @this {XCUITestDriver}
|
|
96
|
+
* @returns {Promise<import('../types').Page[]>}
|
|
97
|
+
*/
|
|
98
|
+
export async function listWebFrames(useUrl = true) {
|
|
99
|
+
const shouldFilterByUrl = useUrl && !this.isRealDevice() && !!this.getCurrentUrl();
|
|
100
|
+
this.log.debug(
|
|
101
|
+
`Selecting by url: ${shouldFilterByUrl}` +
|
|
102
|
+
(shouldFilterByUrl ? ` (expected url: '${this.getCurrentUrl()}')` : '')
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (!this.remote) {
|
|
106
|
+
await this.connectToRemoteDebugger();
|
|
107
|
+
}
|
|
108
|
+
const doListPages = async (/** @type {number} */ retries) => {
|
|
109
|
+
try {
|
|
110
|
+
const pageArray = await (/** @type {RemoteDebugger} */ (this.remote)).selectApp(
|
|
111
|
+
shouldFilterByUrl ? this.getCurrentUrl() : undefined,
|
|
112
|
+
retries,
|
|
113
|
+
this.opts.ignoreAboutBlankUrl,
|
|
114
|
+
);
|
|
115
|
+
if (_.isEmpty(pageArray)) {
|
|
116
|
+
// we have no web frames, but continue anyway
|
|
117
|
+
this.log.debug(`No web frames found after ${util.pluralize('retry', retries, true)}`);
|
|
118
|
+
}
|
|
119
|
+
return pageArray;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
this.log.debug(
|
|
122
|
+
`No available web pages after ${util.pluralize('retry', retries, true)}: ${err.message}`
|
|
123
|
+
);
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/** @type {number} */
|
|
129
|
+
const maxRetriesCount = _.isInteger(this.opts.webviewConnectRetries)
|
|
130
|
+
? Math.max(/** @type {number} */ (this.opts.webviewConnectRetries), 1)
|
|
131
|
+
: DEFAULT_LIST_WEB_FRAMES_RETRIES;
|
|
132
|
+
this.log.debug(
|
|
133
|
+
`About to select a web application with ${util.pluralize('retry', maxRetriesCount, true)} ` +
|
|
134
|
+
`and 500ms interval between each retry. Consider customizing the value of 'webviewConnectRetries' ` +
|
|
135
|
+
`capability to change the amount of retries.`
|
|
136
|
+
);
|
|
137
|
+
return await doListPages(maxRetriesCount);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @this {XCUITestDriver}
|
|
142
|
+
* @returns {Promise<void>}
|
|
143
|
+
*/
|
|
144
|
+
export async function connectToRemoteDebugger() {
|
|
145
|
+
this.remote = await this.getNewRemoteDebugger();
|
|
146
|
+
|
|
147
|
+
// @ts-ignore static is fine
|
|
148
|
+
this.remote.on(RemoteDebugger.EVENT_PAGE_CHANGE, this.onPageChange.bind(this));
|
|
149
|
+
// @ts-ignore static is fine
|
|
150
|
+
this.remote.on(RemoteDebugger.EVENT_FRAMES_DETACHED, () => {
|
|
151
|
+
if (!_.isEmpty(this.curWebFrames)) {
|
|
152
|
+
const curWebFrames = this.curWebFrames;
|
|
153
|
+
this.log.debug(
|
|
154
|
+
`Clearing ${util.pluralize('frame', curWebFrames.length, true)}: ${curWebFrames.join(
|
|
155
|
+
', ',
|
|
156
|
+
)}`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
this.curWebFrames = [];
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const timeoutMs = this.opts.webviewConnectTimeout ?? DEFAULT_REMOTE_DEBUGGER_CONNECT_TIMEOUT_MS;
|
|
163
|
+
const apps = await this.remote.connect(timeoutMs);
|
|
164
|
+
if (_.isEmpty(apps)) {
|
|
165
|
+
this.log.info(
|
|
166
|
+
`The remote debugger did not report any active web applications within ${timeoutMs}ms timeout. ` +
|
|
167
|
+
`Consider increasing the value of 'webviewConnectTimeout' capability to wait longer ` +
|
|
168
|
+
`on slower devices.`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Retrieves the list of available contexts.
|
|
175
|
+
*
|
|
176
|
+
* The list includes extended context information, like URLs and page names.
|
|
177
|
+
* This is different from the standard `getContexts` API, because the latter
|
|
178
|
+
* only has web view names without any additional information.
|
|
179
|
+
*
|
|
180
|
+
* @remarks In situations where multiple web views are available at once, the
|
|
181
|
+
* client code would have to connect to each of them in order to detect the
|
|
182
|
+
* one which needs to be interacted with. This extra effort is not needed with
|
|
183
|
+
* the information provided by this extension.
|
|
184
|
+
* @param {number} [waitForWebviewMs=0] - The period to poll for available webview(s) (in ms)
|
|
185
|
+
* @returns {Promise<Context[]>} The list of available context objects along with their properties.
|
|
186
|
+
* @this {XCUITestDriver}
|
|
187
|
+
*/
|
|
188
|
+
export async function mobileGetContexts(waitForWebviewMs = 0) {
|
|
189
|
+
// make sure it is a number, so the duration check works properly
|
|
190
|
+
if (!_.isNumber(waitForWebviewMs)) {
|
|
191
|
+
waitForWebviewMs = parseInt(waitForWebviewMs, 10);
|
|
192
|
+
if (isNaN(waitForWebviewMs)) {
|
|
193
|
+
waitForWebviewMs = 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const curOpt = this.opts.fullContextList;
|
|
198
|
+
this.opts.fullContextList = true;
|
|
199
|
+
|
|
200
|
+
const timer = new timing.Timer().start();
|
|
201
|
+
try {
|
|
202
|
+
/** @type {FullContext[]} */
|
|
203
|
+
let contexts;
|
|
204
|
+
do {
|
|
205
|
+
contexts = /** @type {FullContext[]} */ (await this.getContexts());
|
|
206
|
+
|
|
207
|
+
if (contexts.length >= 2) {
|
|
208
|
+
this.log.debug(
|
|
209
|
+
`Found webview context after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
|
|
210
|
+
);
|
|
211
|
+
return contexts;
|
|
212
|
+
}
|
|
213
|
+
this.log.debug(`No webviews found in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
214
|
+
} while (timer.getDuration().asMilliSeconds < waitForWebviewMs);
|
|
215
|
+
return contexts;
|
|
216
|
+
} finally {
|
|
217
|
+
// reset the option so there are no side effects
|
|
218
|
+
this.opts.fullContextList = curOpt;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @this {XCUITestDriver}
|
|
224
|
+
* @param {import('./types').PageChangeNotification} pageChangeNotification
|
|
225
|
+
* @returns {Promise<void>}
|
|
226
|
+
*/
|
|
227
|
+
export async function onPageChange(pageChangeNotification) {
|
|
228
|
+
this.log.debug(
|
|
229
|
+
`Remote debugger notified us of a new page listing: ${JSON.stringify(
|
|
230
|
+
pageChangeNotification,
|
|
231
|
+
)}`,
|
|
232
|
+
);
|
|
233
|
+
if (this.selectingNewPage) {
|
|
234
|
+
this.log.debug('We are in the middle of selecting a page, ignoring');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (!this.remote?.isConnected) {
|
|
238
|
+
this.log.debug('We have not yet connected, ignoring');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const {appIdKey, pageArray} = pageChangeNotification;
|
|
243
|
+
|
|
244
|
+
/** @type {string[]} */
|
|
245
|
+
const newIds = [];
|
|
246
|
+
/** @type {string[]} */
|
|
247
|
+
const newPages = [];
|
|
248
|
+
/** @type {string|null} */
|
|
249
|
+
let keyId = null;
|
|
250
|
+
for (const page of pageArray) {
|
|
251
|
+
const id = page.id.toString();
|
|
252
|
+
newIds.push(id);
|
|
253
|
+
if (page.isKey) {
|
|
254
|
+
keyId = id;
|
|
255
|
+
}
|
|
256
|
+
const contextId = `${appIdKey}.${id}`;
|
|
257
|
+
|
|
258
|
+
// add if this is a new page
|
|
259
|
+
if (!_.includes(this.contexts, contextId)) {
|
|
260
|
+
if (isUrlIgnored(page.url, this.opts.safariIgnoreWebHostnames)) {
|
|
261
|
+
this.log.info(
|
|
262
|
+
`Not tracking '${page.url}' page because it is blacklisted. ` +
|
|
263
|
+
`'safariIgnoreWebHostnames'=${this.opts.safariIgnoreWebHostnames}`,
|
|
264
|
+
);
|
|
265
|
+
} else {
|
|
266
|
+
newPages.push(id);
|
|
267
|
+
this.contexts.push(contextId);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (!keyId) {
|
|
273
|
+
// if there is no key id, pull the first id from the page array and use that
|
|
274
|
+
// as a stand in
|
|
275
|
+
this.log.debug('No key id found. Choosing first id from page array');
|
|
276
|
+
keyId = newIds[0] || null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (!util.hasValue(this.curContext)) {
|
|
280
|
+
this.log.debug('We do not appear to have window set yet, ignoring');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const [curAppIdKey, curPageIdKey] = this.curContext.split('.');
|
|
284
|
+
if (curAppIdKey !== appIdKey) {
|
|
285
|
+
this.log.debug('Page change not referring to currently selected app, ignoring.');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** @type {string|null} */
|
|
290
|
+
let newPage = null;
|
|
291
|
+
if (newPages.length) {
|
|
292
|
+
newPage = /** @type {string} */ (_.last(newPages));
|
|
293
|
+
this.log.debug(`We have new pages, selecting page '${newPage}'`);
|
|
294
|
+
} else if (!_.includes(newIds, curPageIdKey)) {
|
|
295
|
+
this.log.debug(
|
|
296
|
+
'New page listing from remote debugger does not contain ' +
|
|
297
|
+
'current window; assuming it is closed',
|
|
298
|
+
);
|
|
299
|
+
if (!util.hasValue(keyId)) {
|
|
300
|
+
this.log.error(
|
|
301
|
+
'Do not have our current window anymore, and there ' +
|
|
302
|
+
'are not any more to load! Doing nothing...',
|
|
303
|
+
);
|
|
304
|
+
this.setCurrentUrl(undefined);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
this.log.debug(`Debugger already selected page '${keyId}', ` + `confirming that choice.`);
|
|
309
|
+
this.curContext = `${appIdKey}.${keyId}`;
|
|
310
|
+
newPage = keyId;
|
|
311
|
+
} else {
|
|
312
|
+
// at this point, there are no new pages, and the current page still exists
|
|
313
|
+
this.log.debug('New page listing is same as old, doing nothing');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// make sure that the page listing isn't indicating a redirect
|
|
317
|
+
if (util.hasValue(this.curContext)) {
|
|
318
|
+
const currentPageId = parseInt(String(_.last(this.curContext.split('.'))), 10);
|
|
319
|
+
const page = _.find(pageArray, (p) => parseInt(String(p.id), 10) === currentPageId);
|
|
320
|
+
if (page && page.url !== this.getCurrentUrl()) {
|
|
321
|
+
this.log.debug(`Redirected from '${this.getCurrentUrl()}' to '${page.url}'`);
|
|
322
|
+
this.setCurrentUrl(page.url);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (util.hasValue(newPage)) {
|
|
327
|
+
this.selectingNewPage = true;
|
|
328
|
+
const oldContext = this.curContext;
|
|
329
|
+
this.curContext = `${appIdKey}.${newPage}`;
|
|
330
|
+
try {
|
|
331
|
+
await this.remote.selectPage(appIdKey, parseInt(newPage, 10));
|
|
332
|
+
await notifyBiDiContextChange.bind(this)();
|
|
333
|
+
} catch (e) {
|
|
334
|
+
this.log.warn(`Failed to select page: ${e.message}`);
|
|
335
|
+
this.curContext = oldContext;
|
|
336
|
+
} finally {
|
|
337
|
+
this.selectingNewPage = false;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* @this {XCUITestDriver}
|
|
344
|
+
* @returns {Promise<void>}
|
|
345
|
+
*/
|
|
346
|
+
export async function stopRemote(closeWindowBeforeDisconnecting = false) {
|
|
347
|
+
if (!this.remote) {
|
|
348
|
+
throw this.log.errorWithException('Tried to leave a web frame but were not in one');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (closeWindowBeforeDisconnecting) {
|
|
352
|
+
await this.closeWindow();
|
|
353
|
+
}
|
|
354
|
+
await this.remote.disconnect();
|
|
355
|
+
this.curContext = null;
|
|
356
|
+
await notifyBiDiContextChange.bind(this)();
|
|
357
|
+
this.curWebFrames = [];
|
|
358
|
+
this.remote = null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @this {XCUITestDriver}
|
|
363
|
+
* @param {string|undefined|null} url
|
|
364
|
+
*/
|
|
365
|
+
export function setCurrentUrl(url) {
|
|
366
|
+
this._currentUrl = url;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* @this {XCUITestDriver}
|
|
371
|
+
* @returns {string|undefined|null}
|
|
372
|
+
*/
|
|
373
|
+
export function getCurrentUrl() {
|
|
374
|
+
return this._currentUrl;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @param {RegExp} titleRegExp
|
|
379
|
+
* @param {RegExp} urlRegExp
|
|
380
|
+
* @this {XCUITestDriver}
|
|
381
|
+
* @returns {Promise<string|undefined>}
|
|
382
|
+
*/
|
|
383
|
+
export async function getRecentWebviewContextId(titleRegExp, urlRegExp) {
|
|
384
|
+
if (!_.isRegExp(titleRegExp) && !_.isRegExp(urlRegExp)) {
|
|
385
|
+
throw new errors.InvalidArgumentError(
|
|
386
|
+
'A regular expression for either web view title or url must be provided',
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const currentUrl = this.getCurrentUrl();
|
|
391
|
+
const contexts = _.filter(await this.getContextsAndViews(false), 'view');
|
|
392
|
+
// first try to match by current url
|
|
393
|
+
if (currentUrl) {
|
|
394
|
+
const ctx = contexts.find(({view}) => (view?.url || '') === currentUrl);
|
|
395
|
+
if (ctx) {
|
|
396
|
+
return ctx.id;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// if not, try to match by regular expression
|
|
400
|
+
return contexts.find(
|
|
401
|
+
({view}) =>
|
|
402
|
+
(view?.title && titleRegExp?.test(view.title)) || (view?.url && urlRegExp?.test(view.url)),
|
|
403
|
+
)?.id;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* @this {XCUITestDriver}
|
|
408
|
+
* @returns {boolean}
|
|
409
|
+
*/
|
|
410
|
+
export function isWebContext() {
|
|
411
|
+
return !!this.curContext && this.curContext !== NATIVE_WIN;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* @this {XCUITestDriver}
|
|
416
|
+
* @returns {boolean}
|
|
417
|
+
*/
|
|
418
|
+
export function isWebview() {
|
|
419
|
+
return this.isWebContext();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* @this {XCUITestDriver}
|
|
424
|
+
* @returns {Promise<RemoteDebugger>}
|
|
425
|
+
*/
|
|
426
|
+
export async function getNewRemoteDebugger() {
|
|
427
|
+
const socketPath = this.isRealDevice()
|
|
428
|
+
? undefined
|
|
429
|
+
: (await /** @type {import('../driver').Simulator} */ (this.device).getWebInspectorSocket() ?? undefined);
|
|
430
|
+
return createRemoteDebugger(
|
|
431
|
+
{
|
|
432
|
+
bundleId: this.opts.bundleId,
|
|
433
|
+
additionalBundleIds: this.opts.additionalWebviewBundleIds,
|
|
434
|
+
isSafari: this.isSafari(),
|
|
435
|
+
includeSafari: this.opts.includeSafariInWebviews,
|
|
436
|
+
pageLoadMs: this.pageLoadMs,
|
|
437
|
+
platformVersion: this.opts.platformVersion,
|
|
438
|
+
socketPath,
|
|
439
|
+
remoteDebugProxy: this.opts.remoteDebugProxy,
|
|
440
|
+
garbageCollectOnExecute: util.hasValue(this.opts.safariGarbageCollect)
|
|
441
|
+
? !!this.opts.safariGarbageCollect
|
|
442
|
+
: false,
|
|
443
|
+
udid: this.opts.udid,
|
|
444
|
+
logAllCommunication: this.opts.safariLogAllCommunication,
|
|
445
|
+
logAllCommunicationHexDump: this.opts.safariLogAllCommunicationHexDump,
|
|
446
|
+
socketChunkSize: this.opts.safariSocketChunkSize,
|
|
447
|
+
webInspectorMaxFrameLength: this.opts.safariWebInspectorMaxFrameLength,
|
|
448
|
+
pageLoadStrategy: this.caps.pageLoadStrategy,
|
|
449
|
+
},
|
|
450
|
+
this.isRealDevice(),
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* @this {XCUITestDriver}
|
|
456
|
+
* @returns {Promise<string>}
|
|
457
|
+
*/
|
|
458
|
+
export async function getCurrentContext() {
|
|
459
|
+
if (this.curContext && this.curContext !== NATIVE_WIN) {
|
|
460
|
+
return `${WEBVIEW_BASE}${this.curContext}`;
|
|
461
|
+
}
|
|
462
|
+
return NATIVE_WIN;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Set context
|
|
467
|
+
*
|
|
468
|
+
* @param {string|Context} name - The name of context to set. It could be 'null' as NATIVE_WIN.
|
|
469
|
+
* @param {any} [callback] The callback. (It is not called in this method)
|
|
470
|
+
* @param {boolean} [skipReadyCheck=false] - Whether it waits for the new context is ready
|
|
471
|
+
* @this {XCUITestDriver}
|
|
472
|
+
* @returns {Promise<void>}
|
|
473
|
+
*/
|
|
474
|
+
export async function setContext(name, callback, skipReadyCheck = false) {
|
|
475
|
+
function alreadyInContext(desired, current) {
|
|
476
|
+
return (
|
|
477
|
+
desired === current ||
|
|
478
|
+
(desired === null && current === NATIVE_WIN) ||
|
|
479
|
+
(desired === NATIVE_WIN && current === null)
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
function isNativeContext(context) {
|
|
483
|
+
return context === NATIVE_WIN || context === null;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// allow the full context list to be passed in
|
|
487
|
+
const strName = String(typeof name === 'object' && name.id ? name.id : name);
|
|
488
|
+
|
|
489
|
+
this.log.debug(
|
|
490
|
+
`Attempting to set context to '${strName || NATIVE_WIN}' from '${
|
|
491
|
+
this.curContext ? this.curContext : NATIVE_WIN
|
|
492
|
+
}'`,
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
if (
|
|
496
|
+
alreadyInContext(strName, this.curContext) ||
|
|
497
|
+
alreadyInContext(_.replace(strName, WEBVIEW_BASE, ''), this.curContext)
|
|
498
|
+
) {
|
|
499
|
+
// already in the named context, no need to do anything
|
|
500
|
+
this.log.debug(`Already in '${strName || NATIVE_WIN}' context. Doing nothing.`);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (isNativeContext(strName)) {
|
|
504
|
+
// switching into the native context
|
|
505
|
+
this.curContext = null;
|
|
506
|
+
await notifyBiDiContextChange.bind(this)();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// switching into a webview context
|
|
511
|
+
|
|
512
|
+
// if contexts have not already been retrieved, get them
|
|
513
|
+
if (_.isUndefined(this.contexts)) {
|
|
514
|
+
await this.getContexts();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
let contextId = _.replace(strName, WEBVIEW_BASE, '');
|
|
518
|
+
if (contextId === '') {
|
|
519
|
+
// allow user to pass in "WEBVIEW" without an index
|
|
520
|
+
// the second context will be the first webview as
|
|
521
|
+
// the first is always NATIVE_APP
|
|
522
|
+
contextId = /** @type {string[]} */ (this.contexts)[1];
|
|
523
|
+
}
|
|
524
|
+
if (!_.includes(this.contexts, contextId)) {
|
|
525
|
+
throw new errors.NoSuchContextError();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const oldContext = this.curContext;
|
|
529
|
+
this.curContext = this.curWindowHandle = contextId;
|
|
530
|
+
|
|
531
|
+
// `contextId` will be in the form of `appId.pageId` in this case
|
|
532
|
+
const [appIdKey, pageIdKey] = _.map(contextId.split('.'), (id) => parseInt(id, 10));
|
|
533
|
+
try {
|
|
534
|
+
this.selectingNewPage = true;
|
|
535
|
+
await (/** @type {RemoteDebugger} */ (this.remote)).selectPage(appIdKey, pageIdKey, skipReadyCheck);
|
|
536
|
+
await notifyBiDiContextChange.bind(this)();
|
|
537
|
+
} catch (err) {
|
|
538
|
+
this.curContext = this.curWindowHandle = oldContext;
|
|
539
|
+
throw err;
|
|
540
|
+
} finally {
|
|
541
|
+
this.selectingNewPage = false;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// attempt to start performance logging, if requested
|
|
545
|
+
if (this.opts.enablePerformanceLogging && this.remote) {
|
|
546
|
+
const context = this.curContext;
|
|
547
|
+
this.log.debug(`Starting performance log on '${context}'`);
|
|
548
|
+
[this.logs.performance,] = assignBiDiLogListener.bind(this)(
|
|
549
|
+
new IOSPerformanceLog({
|
|
550
|
+
remoteDebugger: this.remote,
|
|
551
|
+
log: this.log,
|
|
552
|
+
}), {
|
|
553
|
+
type: 'performance',
|
|
554
|
+
context,
|
|
555
|
+
}
|
|
556
|
+
);
|
|
557
|
+
await this.logs.performance?.startCapture();
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// start safari logging if the logs handlers are active
|
|
561
|
+
if (name && name !== NATIVE_WIN && this.logs) {
|
|
562
|
+
if (this.logs.safariConsole) {
|
|
563
|
+
(/** @type {RemoteDebugger} */ (this.remote)).startConsole(
|
|
564
|
+
this.logs.safariConsole.onConsoleLogEvent.bind(this.logs.safariConsole),
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
if (this.logs.safariNetwork) {
|
|
568
|
+
(/** @type {RemoteDebugger} */ (this.remote)).startNetwork(
|
|
569
|
+
this.logs.safariNetwork.onNetworkEvent.bind(this.logs.safariNetwork),
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* @this {XCUITestDriver}
|
|
577
|
+
* @returns {Promise<string[]|FullContext[]>}
|
|
578
|
+
*/
|
|
579
|
+
export async function getContexts() {
|
|
580
|
+
this.log.debug('Getting list of available contexts');
|
|
581
|
+
const contexts = await this.getContextsAndViews(false);
|
|
582
|
+
|
|
583
|
+
if (this.opts.fullContextList) {
|
|
584
|
+
return /** @type {import('./types').FullContext[]} */ (
|
|
585
|
+
contexts.map((context) => ({
|
|
586
|
+
id: context.id.toString(),
|
|
587
|
+
title: context.view?.title,
|
|
588
|
+
url: context.view?.url,
|
|
589
|
+
bundleId: context.view?.bundleId,
|
|
590
|
+
}))
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
return /** @type {string[]} */ (contexts.map((context) => context.id.toString()));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* @this {XCUITestDriver}
|
|
598
|
+
* @param {string} name
|
|
599
|
+
* @param {boolean} [skipReadyCheck]
|
|
600
|
+
* @returns {Promise<void>}
|
|
601
|
+
*/
|
|
602
|
+
export async function setWindow(name, skipReadyCheck) {
|
|
603
|
+
if (!this.isWebContext()) {
|
|
604
|
+
// https://github.com/appium/appium/issues/20710
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
await this.setContext(name, _.noop, skipReadyCheck);
|
|
609
|
+
} catch (err) {
|
|
610
|
+
// translate the error in terms of windows
|
|
611
|
+
throw isErrorType(err, errors.NoSuchContextError) ? new errors.NoSuchWindowError() : err;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @this {XCUITestDriver}
|
|
617
|
+
* @returns {Promise<string>}
|
|
618
|
+
*/
|
|
619
|
+
export async function getWindowHandle() {
|
|
620
|
+
if (!this.isWebContext()) {
|
|
621
|
+
// https://github.com/appium/appium/issues/20710
|
|
622
|
+
return DEFAULT_NATIVE_WINDOW_HANDLE;
|
|
623
|
+
}
|
|
624
|
+
if (!this.curContext) {
|
|
625
|
+
throw new errors.InvalidContextError();
|
|
626
|
+
}
|
|
627
|
+
this.log.debug(`Getting current window handle`);
|
|
628
|
+
return this.curContext;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* @this {XCUITestDriver}
|
|
633
|
+
* @returns {Promise<string[]>}
|
|
634
|
+
*/
|
|
635
|
+
export async function getWindowHandles() {
|
|
636
|
+
if (!this.isWebContext()) {
|
|
637
|
+
// https://github.com/appium/appium/issues/20710
|
|
638
|
+
return [DEFAULT_NATIVE_WINDOW_HANDLE];
|
|
639
|
+
}
|
|
640
|
+
this.log.debug('Getting list of available window handles');
|
|
641
|
+
const contexts = await this.getContextsAndViews(false);
|
|
642
|
+
return (
|
|
643
|
+
contexts
|
|
644
|
+
// get rid of the native app context
|
|
645
|
+
.filter((context) => context.id !== NATIVE_WIN)
|
|
646
|
+
// get the `app.id` format expected
|
|
647
|
+
.map((context) =>
|
|
648
|
+
// This is non-nullable because the `FullContext` having `id` `NATIVE_WIN`
|
|
649
|
+
// _looks like_ the only with an empty view.
|
|
650
|
+
context.view?.id?.toString() ?? ''
|
|
651
|
+
)
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Checks if a URL is blacklisted in the 'safariIgnoreWebHostnames' capability
|
|
657
|
+
*
|
|
658
|
+
* @param {string} url
|
|
659
|
+
* @param {string} [safariIgnoreWebHostnames]
|
|
660
|
+
* @returns {boolean}
|
|
661
|
+
*/
|
|
662
|
+
function isUrlIgnored(url, safariIgnoreWebHostnames) {
|
|
663
|
+
if (!safariIgnoreWebHostnames || _.isEmpty(safariIgnoreWebHostnames)) {
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const ignoredHosts = safariIgnoreWebHostnames
|
|
668
|
+
.split(',')
|
|
669
|
+
.map((b) => b.trim())
|
|
670
|
+
.filter((b) => !_.isEmpty(b));
|
|
671
|
+
for (const ignoredHost of ignoredHosts) {
|
|
672
|
+
if (ignoredHost === 'about:blank' && url === 'about:blank') {
|
|
673
|
+
return true;
|
|
674
|
+
} else {
|
|
675
|
+
try {
|
|
676
|
+
const hostname = new URL(url).hostname;
|
|
677
|
+
if (hostname === ignoredHost) {
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
} catch {
|
|
681
|
+
// do nothing if invalid URL
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* https://github.com/appium/appium/issues/20741
|
|
690
|
+
*
|
|
691
|
+
* @this {XCUITestDriver}
|
|
692
|
+
* @returns {Promise<void>}
|
|
693
|
+
*/
|
|
694
|
+
export async function notifyBiDiContextChange() {
|
|
695
|
+
const name = await this.getCurrentContext();
|
|
696
|
+
this.eventEmitter.emit(BIDI_EVENT_NAME, makeContextUpdatedEvent(name));
|
|
697
|
+
this.eventEmitter.emit(BIDI_EVENT_NAME, makeObsoleteContextUpdatedEvent(name));
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* @typedef {import('../driver').XCUITestDriver} XCUITestDriver
|
|
703
|
+
* @typedef {import('./types').Context} Context
|
|
704
|
+
* @typedef {import('./types').FullContext} FullContext
|
|
705
|
+
*/
|