@devicelab/maestro-runner-darwin-x64 1.1.25
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/LICENSE +191 -0
- package/README.md +166 -0
- package/THIRD_PARTY_LICENSES +186 -0
- package/bin/maestro-runner +0 -0
- package/drivers/android/appium-uiautomator2-server-debug-androidTest.apk +0 -0
- package/drivers/android/appium-uiautomator2-server-v9.11.1.apk +0 -0
- package/drivers/android/devicelab-android-driver-test.apk +0 -0
- package/drivers/android/devicelab-android-driver.apk +0 -0
- package/drivers/android/settings_apk-debug.apk +0 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunner/App.swift +11 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunner.xcodeproj/project.pbxproj +523 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/ATTRIBUTION.md +73 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/Bridging-Header.h +4 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/PixelDiff.swift +72 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/PrivateHeaders/XCTest/XCPointerEventPath.h +43 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h +32 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/PrivateHeaders/XCTest/XCUIApplication+ActiveApp.h +23 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/PrivateHeaders/XCTest/XCUIDevice.h +30 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerObjCExceptionCatcher.h +11 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerObjCExceptionCatcher.m +16 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Alert.swift +155 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+CommandExecution.swift +961 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Environment.swift +37 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Interaction.swift +1864 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Lifecycle.swift +351 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Media.swift +81 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Models.swift +258 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+ScreenRecorder.swift +279 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Snapshot.swift +703 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+SystemModal.swift +230 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+Transport.swift +137 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+TvRemote.swift +185 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests.swift +197 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/SnapshotParams.h +28 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/SnapshotParams.m +49 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/SyntheticTyping.h +17 -0
- package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/SyntheticTyping.m +86 -0
- package/drivers/ios/DevicelabIOSRunner/PROTOCOL.md +258 -0
- package/drivers/ios/DevicelabIOSRunner/README.md +38 -0
- package/drivers/ios/DevicelabIOSRunner/project.yml +49 -0
- package/drivers/ios/WebDriverAgent/.github/ISSUE_TEMPLATE.md +4 -0
- package/drivers/ios/WebDriverAgent/.github/actions/xcode-setup/action.yml +32 -0
- package/drivers/ios/WebDriverAgent/.github/dependabot.yml +22 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/functional-test.yml +62 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/pr-title.yml +10 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/publish.js.yml +105 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/unit-test.yml +30 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/wda-package.yml +107 -0
- package/drivers/ios/WebDriverAgent/.github/workflows/wda-tests.yml +221 -0
- package/drivers/ios/WebDriverAgent/.mocharc.js +4 -0
- package/drivers/ios/WebDriverAgent/.releaserc +45 -0
- package/drivers/ios/WebDriverAgent/CHANGELOG.md +1547 -0
- package/drivers/ios/WebDriverAgent/CONTRIBUTING.md +35 -0
- package/drivers/ios/WebDriverAgent/Configurations/IOSSettings.xcconfig +31 -0
- package/drivers/ios/WebDriverAgent/Configurations/IOSTestSettings.xcconfig +1 -0
- package/drivers/ios/WebDriverAgent/Configurations/TVOSSettings.xcconfig +31 -0
- package/drivers/ios/WebDriverAgent/Configurations/TVOSTestSettings.xcconfig +1 -0
- package/drivers/ios/WebDriverAgent/Fastlane/Fastfile +13 -0
- package/drivers/ios/WebDriverAgent/Gemfile +3 -0
- package/drivers/ios/WebDriverAgent/LICENSE +30 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/AccessibilityUtilities/AXSettings.h +15 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/MobileCoreServices/LSApplicationWorkspace.h +127 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/TextInput/TIPreferencesController.h +45 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/UIKitCore/UIKeyboardImpl.h +27 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/CDStructures.h +28 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/NSString-XCTAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/NSValue-XCTestAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UIGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UILongPressGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UIPanGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UIPinchGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UISwipeGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/UITapGestureRecognizer-RecordingAdditions.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCAXClient_iOS.h +55 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCActivityRecord.h +39 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCApplicationMonitor.h +44 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCApplicationMonitor_iOS.h +18 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCApplicationQuery.h +23 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCDebugLogDelegate-Protocol.h +11 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCDeviceEvent.h +27 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCEventGenerator.h +73 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCKeyMappingPath.h +36 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCKeyboardInputSolver.h +41 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCKeyboardKeyMap.h +101 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCKeyboardLayout.h +35 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCPointerEvent.h +30 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCPointerEventPath.h +43 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSourceCodeRecording.h +42 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSourceCodeTreeNode.h +84 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSourceCodeTreeNodeEnumerator.h +18 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSymbolicationRecord.h +29 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSymbolicatorHolder.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h +32 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTAXClient-Protocol.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTAsyncActivity-Protocol.h +16 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTAsyncActivity.h +23 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTAutomationTarget-Protocol.h +12 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTDarwinNotificationExpectation.h +23 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTElementSetTransformer-Protocol.h +18 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTKVOExpectation.h +28 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTMetric.h +29 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTNSNotificationExpectation.h +27 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTNSPredicateExpectation.h +24 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTNSPredicateExpectationObject-Protocol.h +15 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTRunnerAutomationSession.h +21 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h +98 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTRunnerIDESession.h +65 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTTestRunSession.h +25 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTTestRunSessionDelegate-Protocol.h +17 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTUIApplicationMonitor-Protocol.h +17 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTWaiter.h +55 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTWaiterDelegate-Protocol.h +16 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTWaiterDelegatePrivate-Protocol.h +12 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTWaiterManagement-Protocol.h +13 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTWaiterManager.h +28 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTest.h +34 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestCase.h +102 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestCaseRun.h +18 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestCaseSuite.h +19 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestConfiguration.h +66 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestContext.h +26 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestContextScope.h +19 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestDriver.h +38 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestDriverInterface-Protocol.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestExpectation.h +39 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestExpectationDelegate-Protocol.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestExpectationWaiter.h +17 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestLog.h +32 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h +36 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +54 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestManager_TestsInterface-Protocol.h +12 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestMisuseObserver.h +37 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestObservation-Protocol.h +20 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestObservationCenter.h +36 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestObserver.h +20 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestProbe.h +13 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestRun.h +39 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestSuite.h +48 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestSuiteRun.h +28 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCTestWaiter.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIApplication.h +60 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIApplicationImpl.h +38 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIApplicationProcess.h +85 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUICoordinate.h +44 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIDevice.h +30 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIElement.h +74 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIElementAsynchronousHandlerWrapper.h +19 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIElementHitPointCoordinate.h +24 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIElementQuery.h +70 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIHitPointResult.h +20 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIRecorderNodeFinder.h +65 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIRecorderNodeFinderMatch.h +25 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIRecorderTimingMessage.h +20 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIRecorderUtilities.h +45 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIScreen.h +27 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/XCUIScreenDataSource-Protocol.h +19 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCInternalTestRun.h +43 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCKVOExpectationImplementation.h +32 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTDarwinNotificationExpectationImplementation.h +27 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTNSNotificationExpectationImplementation.h +30 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTNSPredicateExpectationImplementation.h +29 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTWaiterImpl.h +41 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestCaseImplementation.h +70 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestCaseInterruptionException.h +13 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestExpectationImplementation.h +40 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestImplementation.h +14 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestObservationCenterImplementation.h +19 -0
- package/drivers/ios/WebDriverAgent/PrivateHeaders/XCTest/_XCTestSuiteImplementation.h +23 -0
- package/drivers/ios/WebDriverAgent/README.md +56 -0
- package/drivers/ios/WebDriverAgent/Scripts/build-webdriveragent.mjs +85 -0
- package/drivers/ios/WebDriverAgent/Scripts/build.sh +124 -0
- package/drivers/ios/WebDriverAgent/Scripts/ci/build-real.sh +24 -0
- package/drivers/ios/WebDriverAgent/Scripts/ci/build-sim.sh +15 -0
- package/drivers/ios/WebDriverAgent/Scripts/fetch-prebuilt-wda.mjs +69 -0
- package/drivers/ios/WebDriverAgent/Scripts/update-wda-version.mjs +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/project.pbxproj +4547 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationApp.xcscheme +87 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_1.xcscheme +86 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_2.xcscheme +86 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_3.xcscheme +86 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentLib.xcscheme +125 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentLib_tvOS.xcscheme +95 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner-nodebug.xcscheme +87 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme +114 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme +123 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h +100 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m +192 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h +39 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m +87 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSExpression+FBFormat.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSExpression+FBFormat.m +34 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSString+FBVisualLength.h +18 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSString+FBVisualLength.m +18 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.h +27 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.m +30 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.h +25 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m +82 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.h +17 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m +35 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h +23 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +109 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBFocused.h +23 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +171 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +645 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.h +24 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.m +28 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m +75 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.h +22 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.m +31 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h +27 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +118 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.h +30 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.m +47 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h +193 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +388 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m +68 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +50 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +36 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h +57 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.m +98 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBCustomActions.h +27 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBCustomActions.m +127 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBFind.h +75 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +133 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m +52 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +28 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +78 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.h +33 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.m +75 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.h +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +58 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +37 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +51 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h +98 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +342 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m +56 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.h +35 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m +71 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h +64 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +199 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +85 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +106 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +170 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h +35 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m +52 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +32 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +294 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +28 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +46 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBAlertViewCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBAlertViewCommands.m +130 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBCustomCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBCustomCommands.m +633 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBDebugCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBDebugCommands.m +81 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBElementCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBElementCommands.m +705 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBFindElementCommands.h +18 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBFindElementCommands.m +186 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBOrientationCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBOrientationCommands.m +185 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBScreenshotCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBScreenshotCommands.m +40 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBSessionCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBSessionCommands.m +594 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBTouchActionCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBTouchActionCommands.m +41 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBTouchIDCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBTouchIDCommands.m +30 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBUnknownCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBUnknownCommands.m +39 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBVideoCommands.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Commands/FBVideoCommands.m +84 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/FBAlert.h +91 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/FBAlert.m +274 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Info.plist +26 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBCommandHandler.h +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBCommandStatus.h +80 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBCommandStatus.m +279 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBElement.h +95 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBElementCache.h +61 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBElementCache.m +100 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBElementUtils.h +76 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBElementUtils.m +153 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBExceptionHandler.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBExceptionHandler.m +58 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBExceptions.h +60 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBExceptions.m +24 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBHTTPStatusCodes.h +581 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBResponseJSONPayload.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBResponseJSONPayload.m +59 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBResponsePayload.h +74 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBResponsePayload.m +148 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBRoute.h +77 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBRoute.m +174 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBRouteRequest-Private.h +20 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBRouteRequest.h +39 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBRouteRequest.m +32 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h +56 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m +72 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m +31 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h +39 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m +94 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBSession-Private.h +26 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBSession.h +141 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBSession.m +295 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBTCPSocket.h +65 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBTCPSocket.m +85 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBWebServer.h +52 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBWebServer.m +248 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCAccessibilityElement.h +34 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCAccessibilityElement.m +17 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +34 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCElementSnapshot.h +82 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +9 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +114 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBAccessibilityTraits.h +20 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBAccessibilityTraits.m +61 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +56 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +87 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBAlertsMonitor.h +51 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +94 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +131 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +165 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBCapabilities.h +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBCapabilities.m +25 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBClassChainQueryParser.h +99 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +666 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBConfiguration.h +403 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBConfiguration.m +711 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.h +26 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.m +49 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBElementHelpers.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBElementHelpers.m +21 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBElementTypeTransformer.h +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m +149 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBErrorBuilder.h +64 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBErrorBuilder.m +75 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBFailureProofTestCase.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBFailureProofTestCase.m +68 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBImageProcessor.h +55 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBImageProcessor.m +170 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBImageUtils.h +25 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBImageUtils.m +80 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBKeyboard.h +37 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBKeyboard.m +123 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBLogger.h +32 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBLogger.m +47 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBMacros.h +57 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBMathUtils.h +36 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBMathUtils.m +63 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBMjpegServer.h +24 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBMjpegServer.m +151 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBNotificationsHelper.h +37 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBNotificationsHelper.m +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBPasteboard.h +40 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBPasteboard.m +172 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBProtocolHelpers.h +46 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBProtocolHelpers.m +144 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBReflectionUtils.h +23 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBReflectionUtils.m +31 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBRunLoopSpinner.h +77 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBRunLoopSpinner.m +94 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBRuntimeUtils.h +79 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBRuntimeUtils.m +112 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBScreen.h +22 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBScreen.m +21 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBScreenshot.h +44 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBScreenshot.m +227 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBSettings.h +48 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBSettings.m +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h +27 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h +52 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +142 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.h +26 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m +21 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m +119 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.h +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +885 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBWebServerParams.h +22 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBWebServerParams.m +23 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +49 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +119 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +359 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +80 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +99 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.h +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.m +25 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXPath-Private.h +56 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXPath.h +59 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/FBXPath.m +979 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h +66 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m +146 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/LRUCache/LRUCacheNode.h +43 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/LRUCache/LRUCacheNode.m +51 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h +42 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +69 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +78 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +107 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.h +37 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +83 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +1220 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +8812 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.h +1036 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m +5868 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.h +12 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.m +88 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.h +56 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.m +106 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.h +107 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.m +2238 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPLogging.h +122 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.h +53 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.m +357 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPResponse.h +149 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.h +126 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.m +372 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/LICENSE +18 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.h +13 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.m +83 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.h +9 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.m +40 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.h +13 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.m +84 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/LICENSE +19 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.h +18 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.m +11 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.h +16 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.m +50 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.h +20 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.m +66 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.h +5 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m +142 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.h +55 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.m +303 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentLib/WebDriverAgentLib.h +59 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentRunner/Info.plist +30 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentRunner/UITestingUITests.m +58 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h +14 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h +14 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m +82 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.h +12 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.m +25 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.h +13 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.m +39 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.h +16 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.m +35 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/SceneDelegate.h +20 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/SceneDelegate.m +48 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h +17 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m +28 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.h +23 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.m +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h +29 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m +108 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/ViewController.h +12 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m +88 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Info.plist +71 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard +620 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationApp/main.m +15 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +194 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m +73 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m +38 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +264 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +127 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m +73 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBFailureProofTestCaseTests.m +41 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBForceTouchTests.m +85 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m +82 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h +76 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m +140 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m +61 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBPasteboardTests.m +91 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBPickerWheelSelectTests.m +55 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m +73 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBScreenTests.m +31 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m +126 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +131 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBTapTest.m +103 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBTestMacros.h +33 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBTypingTest.m +68 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m +64 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m +124 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +491 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m +184 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +157 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/Info.plist +24 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +211 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +30 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +162 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIDeviceHealthCheckTests.m +27 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +220 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIDeviceRotationTests.m +84 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIElementAttributesTests.m +248 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +472 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +51 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.h +16 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +110 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.h +17 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.m +66 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +51 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +104 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBClassChainTests.m +313 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBConfigurationTests.m +60 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBElementCacheTests.m +124 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBElementTypeTransformerTests.m +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBElementUtilitiesTests.m +36 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBErrorBuilderTests.m +61 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBExceptionHandlerTests.m +59 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBLRUCacheTests.m +127 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m +113 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBProtocolHelpersTests.m +81 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBRouteTests.m +129 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBRunLoopSpinnerTests.m +98 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBRuntimeUtilsTests.m +45 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBSDKVersionTests.m +66 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBSessionTests.m +67 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBXMLSafeStringTests.m +35 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/FBXPathTests.m +155 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/Info.plist +24 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m +34 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/NSExpressionFBFormatTests.m +60 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m +72 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests/XCUIElementHelpersTests.m +50 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +46 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m +80 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests_tvOS/FBTVNavigationTrackerTests.m +86 -0
- package/drivers/ios/WebDriverAgent/WebDriverAgentTests/UnitTests_tvOS/Info.plist +24 -0
- package/drivers/ios/WebDriverAgent/eslint.config.mjs +13 -0
- package/drivers/ios/WebDriverAgent/index.ts +7 -0
- package/drivers/ios/WebDriverAgent/lib/check-dependencies.ts +34 -0
- package/drivers/ios/WebDriverAgent/lib/constants.ts +18 -0
- package/drivers/ios/WebDriverAgent/lib/logger.ts +3 -0
- package/drivers/ios/WebDriverAgent/lib/no-session-proxy.ts +25 -0
- package/drivers/ios/WebDriverAgent/lib/types.ts +139 -0
- package/drivers/ios/WebDriverAgent/lib/utils.ts +342 -0
- package/drivers/ios/WebDriverAgent/lib/webdriveragent.ts +715 -0
- package/drivers/ios/WebDriverAgent/lib/xcodebuild.ts +488 -0
- package/drivers/ios/WebDriverAgent/package.json +102 -0
- package/drivers/ios/WebDriverAgent/test/functional/desired.ts +7 -0
- package/drivers/ios/WebDriverAgent/test/functional/helpers/simulator.ts +34 -0
- package/drivers/ios/WebDriverAgent/test/functional/webdriveragent-e2e-specs.ts +119 -0
- package/drivers/ios/WebDriverAgent/test/unit/utils-specs.ts +157 -0
- package/drivers/ios/WebDriverAgent/test/unit/webdriveragent-specs.ts +446 -0
- package/drivers/ios/WebDriverAgent/tsconfig.json +16 -0
- package/package.json +16 -0
package/drivers/ios/DevicelabIOSRunner/DevicelabIOSRunnerUITests/RunnerTests+CommandExecution.swift
ADDED
|
@@ -0,0 +1,961 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
extension RunnerTests {
|
|
4
|
+
// MARK: - Main Thread Dispatch
|
|
5
|
+
|
|
6
|
+
private func currentUptimeMs() -> Double {
|
|
7
|
+
ProcessInfo.processInfo.systemUptime * 1000
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func measureGesture(_ action: () -> Void) -> (gestureStartUptimeMs: Double, gestureEndUptimeMs: Double) {
|
|
11
|
+
let gestureStartUptimeMs = currentUptimeMs()
|
|
12
|
+
action()
|
|
13
|
+
return (gestureStartUptimeMs, currentUptimeMs())
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func unsupportedResponse(for outcome: RunnerInteractionOutcome) -> Response? {
|
|
17
|
+
switch outcome {
|
|
18
|
+
case .performed:
|
|
19
|
+
return nil
|
|
20
|
+
case .unsupported(let message):
|
|
21
|
+
return Response(
|
|
22
|
+
ok: false,
|
|
23
|
+
error: ErrorPayload(code: "UNSUPPORTED_OPERATION", message: message)
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func execute(command: Command) throws -> Response {
|
|
29
|
+
if Thread.isMainThread {
|
|
30
|
+
return try executeOnMainSafely(command: command)
|
|
31
|
+
}
|
|
32
|
+
var result: Result<Response, Error>?
|
|
33
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
34
|
+
DispatchQueue.main.async {
|
|
35
|
+
do {
|
|
36
|
+
result = .success(try self.executeOnMainSafely(command: command))
|
|
37
|
+
} catch {
|
|
38
|
+
result = .failure(error)
|
|
39
|
+
}
|
|
40
|
+
semaphore.signal()
|
|
41
|
+
}
|
|
42
|
+
let waitResult = semaphore.wait(timeout: .now() + mainThreadExecutionTimeout)
|
|
43
|
+
if waitResult == .timedOut {
|
|
44
|
+
// The main queue work may still be running; we stop waiting and report timeout.
|
|
45
|
+
throw NSError(
|
|
46
|
+
domain: RunnerErrorDomain.general,
|
|
47
|
+
code: RunnerErrorCode.mainThreadExecutionTimedOut,
|
|
48
|
+
userInfo: [NSLocalizedDescriptionKey: "main thread execution timed out"]
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
switch result {
|
|
52
|
+
case .success(let response):
|
|
53
|
+
return response
|
|
54
|
+
case .failure(let error):
|
|
55
|
+
throw error
|
|
56
|
+
case .none:
|
|
57
|
+
throw NSError(
|
|
58
|
+
domain: RunnerErrorDomain.general,
|
|
59
|
+
code: RunnerErrorCode.noResponseFromMainThread,
|
|
60
|
+
userInfo: [NSLocalizedDescriptionKey: "no response from main thread"]
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// MARK: - Command Handling
|
|
66
|
+
|
|
67
|
+
private func executeOnMainSafely(command: Command) throws -> Response {
|
|
68
|
+
var hasRetried = false
|
|
69
|
+
while true {
|
|
70
|
+
var response: Response?
|
|
71
|
+
var swiftError: Error?
|
|
72
|
+
let exceptionMessage = RunnerObjCExceptionCatcher.catchException({
|
|
73
|
+
do {
|
|
74
|
+
response = try self.executeOnMain(command: command)
|
|
75
|
+
} catch {
|
|
76
|
+
swiftError = error
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
if let exceptionMessage {
|
|
81
|
+
currentApp = nil
|
|
82
|
+
currentBundleId = nil
|
|
83
|
+
if !hasRetried, shouldRetryException(command, message: exceptionMessage) {
|
|
84
|
+
NSLog(
|
|
85
|
+
"AGENT_DEVICE_RUNNER_RETRY command=%@ reason=objc_exception",
|
|
86
|
+
command.command.rawValue
|
|
87
|
+
)
|
|
88
|
+
hasRetried = true
|
|
89
|
+
sleepFor(retryCooldown)
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
throw NSError(
|
|
93
|
+
domain: RunnerErrorDomain.exception,
|
|
94
|
+
code: RunnerErrorCode.objcException,
|
|
95
|
+
userInfo: [NSLocalizedDescriptionKey: exceptionMessage]
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
if let swiftError {
|
|
99
|
+
throw swiftError
|
|
100
|
+
}
|
|
101
|
+
guard let response else {
|
|
102
|
+
throw NSError(
|
|
103
|
+
domain: RunnerErrorDomain.general,
|
|
104
|
+
code: RunnerErrorCode.commandReturnedNoResponse,
|
|
105
|
+
userInfo: [NSLocalizedDescriptionKey: "command returned no response"]
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
if !hasRetried, shouldRetryCommand(command), shouldRetryResponse(response) {
|
|
109
|
+
NSLog(
|
|
110
|
+
"AGENT_DEVICE_RUNNER_RETRY command=%@ reason=response_unavailable",
|
|
111
|
+
command.command.rawValue
|
|
112
|
+
)
|
|
113
|
+
hasRetried = true
|
|
114
|
+
currentApp = nil
|
|
115
|
+
currentBundleId = nil
|
|
116
|
+
sleepFor(retryCooldown)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
return response
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private func executeOnMain(command: Command) throws -> Response {
|
|
124
|
+
var activeApp = currentApp ?? app
|
|
125
|
+
if !isRunnerLifecycleCommand(command.command) {
|
|
126
|
+
let normalizedBundleId = command.appBundleId?
|
|
127
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
128
|
+
let requestedBundleId = (normalizedBundleId?.isEmpty == true) ? nil : normalizedBundleId
|
|
129
|
+
if let bundleId = requestedBundleId {
|
|
130
|
+
if currentBundleId != bundleId || currentApp == nil {
|
|
131
|
+
_ = activateTarget(bundleId: bundleId, reason: "bundle_changed")
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// Do not reuse stale bundle targets when the caller does not explicitly request one.
|
|
135
|
+
currentApp = nil
|
|
136
|
+
currentBundleId = nil
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
activeApp = currentApp ?? app
|
|
140
|
+
if let bundleId = requestedBundleId, targetNeedsActivation(activeApp) {
|
|
141
|
+
activeApp = activateTarget(bundleId: bundleId, reason: "stale_target")
|
|
142
|
+
} else if requestedBundleId == nil, targetNeedsActivation(activeApp) {
|
|
143
|
+
// No bundle named: target whatever is on screen rather than
|
|
144
|
+
// hijacking it with the placeholder host app.
|
|
145
|
+
if let front = frontmostApplication() {
|
|
146
|
+
currentApp = front
|
|
147
|
+
activeApp = front
|
|
148
|
+
} else {
|
|
149
|
+
ensureRunnerHostAppActive(reason: "missing_app_bundle")
|
|
150
|
+
activeApp = app
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let skipExistenceWait = canUseFastForegroundAppGuard(
|
|
155
|
+
activeApp: activeApp,
|
|
156
|
+
requestedBundleId: requestedBundleId,
|
|
157
|
+
command: command.command
|
|
158
|
+
)
|
|
159
|
+
if !skipExistenceWait && !activeApp.waitForExistence(timeout: appExistenceTimeout) {
|
|
160
|
+
if let bundleId = requestedBundleId {
|
|
161
|
+
activeApp = activateTarget(bundleId: bundleId, reason: "missing_after_wait")
|
|
162
|
+
guard activeApp.waitForExistence(timeout: appExistenceTimeout) else {
|
|
163
|
+
return Response(ok: false, error: ErrorPayload(message: "app '\(bundleId)' is not available"))
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
return Response(ok: false, error: ErrorPayload(message: "runner app is not available"))
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if isInteractionCommand(command.command) {
|
|
171
|
+
if let bundleId = requestedBundleId, activeApp.state != .runningForeground {
|
|
172
|
+
activeApp = activateTarget(bundleId: bundleId, reason: "interaction_foreground_guard")
|
|
173
|
+
} else if requestedBundleId == nil, activeApp.state != .runningForeground {
|
|
174
|
+
if let front = frontmostApplication() {
|
|
175
|
+
currentApp = front
|
|
176
|
+
activeApp = front
|
|
177
|
+
} else {
|
|
178
|
+
ensureRunnerHostAppActive(reason: "interaction_missing_app_bundle")
|
|
179
|
+
activeApp = app
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
let skipInteractionExistenceWait = canUseFastForegroundAppGuard(
|
|
183
|
+
activeApp: activeApp,
|
|
184
|
+
requestedBundleId: requestedBundleId,
|
|
185
|
+
command: command.command
|
|
186
|
+
)
|
|
187
|
+
if !skipInteractionExistenceWait && !activeApp.waitForExistence(timeout: 2) {
|
|
188
|
+
if let bundleId = requestedBundleId {
|
|
189
|
+
return Response(ok: false, error: ErrorPayload(message: "app '\(bundleId)' is not available"))
|
|
190
|
+
}
|
|
191
|
+
return Response(ok: false, error: ErrorPayload(message: "runner app is not available"))
|
|
192
|
+
}
|
|
193
|
+
applyInteractionStabilizationIfNeeded()
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
switch command.command {
|
|
198
|
+
case .shutdown:
|
|
199
|
+
stopRecordingIfNeeded()
|
|
200
|
+
return Response(ok: true, data: DataPayload(message: "shutdown"))
|
|
201
|
+
case .addMedia:
|
|
202
|
+
return try executeAddMedia(command: command)
|
|
203
|
+
case .idleCheck:
|
|
204
|
+
// Local extension: take two consecutive screenshots in-process,
|
|
205
|
+
// diff them on the runner side, return just the fraction of
|
|
206
|
+
// differing pixels. Reuses the previous iteration's screenshot
|
|
207
|
+
// when it's still fresh (within idleScreenshotCacheTTL) — that
|
|
208
|
+
// halves the screenshot cost for waitForAnimationToEnd loops that
|
|
209
|
+
// need multiple iterations.
|
|
210
|
+
let now = Date()
|
|
211
|
+
let prev: RunnerImage
|
|
212
|
+
if let cached = lastIdleScreenshot,
|
|
213
|
+
now.timeIntervalSince(cached.capturedAt) < Self.idleScreenshotCacheTTL {
|
|
214
|
+
prev = cached.image
|
|
215
|
+
} else {
|
|
216
|
+
prev = XCUIScreen.main.screenshot().image
|
|
217
|
+
}
|
|
218
|
+
let curImg = XCUIScreen.main.screenshot().image
|
|
219
|
+
lastIdleScreenshot = (image: curImg, capturedAt: Date())
|
|
220
|
+
let diff = computePixelDiffFraction(prev, curImg)
|
|
221
|
+
return Response(ok: true, data: DataPayload(diffFraction: diff))
|
|
222
|
+
case .awaitIdle:
|
|
223
|
+
// Local extension: runner-side wait loop. Compares consecutive
|
|
224
|
+
// XCUI accessibility-tree snapshots (NOT screenshots) and returns
|
|
225
|
+
// when two adjacent samples produce the same tree signature.
|
|
226
|
+
//
|
|
227
|
+
// Why tree-diff over pixel-diff:
|
|
228
|
+
// - 2-4× faster per iteration (app.snapshot() is cheaper than
|
|
229
|
+
// XCUIScreen.screenshot() + PNG decode + per-pixel compare).
|
|
230
|
+
// - Ignores visual noise that doesn't affect interactivity:
|
|
231
|
+
// cursor blink, status-bar clock tick, scroll-indicator
|
|
232
|
+
// fade, animated GIFs, video playback. Those tripped the
|
|
233
|
+
// prior 2% pixel threshold and forced us to wait the full
|
|
234
|
+
// timeout on screens that were functionally settled.
|
|
235
|
+
// - Catches the signals we actually care about for tap-readiness:
|
|
236
|
+
// element frames moving (navigation transitions, layout
|
|
237
|
+
// animations) and elements appearing/disappearing.
|
|
238
|
+
//
|
|
239
|
+
// Caller still passes timeoutMs (via durationMs). `scale` is
|
|
240
|
+
// accepted for wire-compat but ignored — tree equality is exact.
|
|
241
|
+
let timeoutMs = command.durationMs ?? 15000
|
|
242
|
+
let timeout = max(0.0, timeoutMs) / 1000.0
|
|
243
|
+
let started = Date()
|
|
244
|
+
var prevSig: UInt64?
|
|
245
|
+
do {
|
|
246
|
+
prevSig = try treeSignature(of: activeApp.snapshot())
|
|
247
|
+
} catch {
|
|
248
|
+
prevSig = nil
|
|
249
|
+
}
|
|
250
|
+
while Date().timeIntervalSince(started) < timeout {
|
|
251
|
+
let curSig: UInt64
|
|
252
|
+
do {
|
|
253
|
+
curSig = try treeSignature(of: activeApp.snapshot())
|
|
254
|
+
} catch {
|
|
255
|
+
// Snapshot failed (rare — usually app momentarily gone).
|
|
256
|
+
// Treat as "still changing" and keep polling.
|
|
257
|
+
continue
|
|
258
|
+
}
|
|
259
|
+
if curSig == prevSig {
|
|
260
|
+
let elapsed = (Date().timeIntervalSince(started)) * 1000
|
|
261
|
+
return Response(ok: true, data: DataPayload(
|
|
262
|
+
message: "settled",
|
|
263
|
+
currentUptimeMs: elapsed
|
|
264
|
+
))
|
|
265
|
+
}
|
|
266
|
+
prevSig = curSig
|
|
267
|
+
}
|
|
268
|
+
return Response(ok: true, data: DataPayload(
|
|
269
|
+
message: "wait timed out (proceeding)",
|
|
270
|
+
currentUptimeMs: timeout * 1000
|
|
271
|
+
))
|
|
272
|
+
case .recordStart:
|
|
273
|
+
guard
|
|
274
|
+
let requestedOutPath = command.outPath?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
275
|
+
!requestedOutPath.isEmpty
|
|
276
|
+
else {
|
|
277
|
+
return Response(ok: false, error: ErrorPayload(message: "recordStart requires outPath"))
|
|
278
|
+
}
|
|
279
|
+
let hasAppBundleId = !(command.appBundleId?
|
|
280
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
281
|
+
.isEmpty ?? true)
|
|
282
|
+
guard hasAppBundleId else {
|
|
283
|
+
return Response(ok: false, error: ErrorPayload(message: "recordStart requires appBundleId"))
|
|
284
|
+
}
|
|
285
|
+
if activeRecording != nil {
|
|
286
|
+
return Response(ok: false, error: ErrorPayload(message: "recording already in progress"))
|
|
287
|
+
}
|
|
288
|
+
if let requestedFps = command.fps, (requestedFps < minRecordingFps || requestedFps > maxRecordingFps) {
|
|
289
|
+
return Response(ok: false, error: ErrorPayload(message: "recordStart fps must be between \(minRecordingFps) and \(maxRecordingFps)"))
|
|
290
|
+
}
|
|
291
|
+
if let requestedQuality = command.quality, (requestedQuality < minRecordingQuality || requestedQuality > maxRecordingQuality) {
|
|
292
|
+
return Response(ok: false, error: ErrorPayload(message: "recordStart quality must be between \(minRecordingQuality) and \(maxRecordingQuality)"))
|
|
293
|
+
}
|
|
294
|
+
do {
|
|
295
|
+
let resolvedOutPath = resolveRecordingOutPath(requestedOutPath)
|
|
296
|
+
let fpsLabel = command.fps.map(String.init) ?? String(RunnerTests.defaultRecordingFps)
|
|
297
|
+
let qualityLabel = command.quality.map(String.init) ?? "native"
|
|
298
|
+
NSLog(
|
|
299
|
+
"AGENT_DEVICE_RUNNER_RECORD_START requestedOutPath=%@ resolvedOutPath=%@ fps=%@ quality=%@",
|
|
300
|
+
requestedOutPath,
|
|
301
|
+
resolvedOutPath,
|
|
302
|
+
fpsLabel,
|
|
303
|
+
qualityLabel
|
|
304
|
+
)
|
|
305
|
+
let recorder = ScreenRecorder(
|
|
306
|
+
outputPath: resolvedOutPath,
|
|
307
|
+
fps: command.fps.map { Int32($0) },
|
|
308
|
+
quality: command.quality
|
|
309
|
+
)
|
|
310
|
+
try recorder.start { [weak self] in
|
|
311
|
+
return self?.captureRunnerFrame()
|
|
312
|
+
}
|
|
313
|
+
activeRecording = recorder
|
|
314
|
+
return Response(ok: true, data: DataPayload(message: "recording started"))
|
|
315
|
+
} catch {
|
|
316
|
+
activeRecording = nil
|
|
317
|
+
return Response(ok: false, error: ErrorPayload(message: "failed to start recording: \(error.localizedDescription)"))
|
|
318
|
+
}
|
|
319
|
+
case .recordStop:
|
|
320
|
+
guard let recorder = activeRecording else {
|
|
321
|
+
return Response(ok: false, error: ErrorPayload(message: "no active recording"))
|
|
322
|
+
}
|
|
323
|
+
do {
|
|
324
|
+
try recorder.stop()
|
|
325
|
+
activeRecording = nil
|
|
326
|
+
return Response(ok: true, data: DataPayload(message: "recording stopped"))
|
|
327
|
+
} catch {
|
|
328
|
+
activeRecording = nil
|
|
329
|
+
return Response(ok: false, error: ErrorPayload(message: "failed to stop recording: \(error.localizedDescription)"))
|
|
330
|
+
}
|
|
331
|
+
case .uptime:
|
|
332
|
+
return Response(
|
|
333
|
+
ok: true,
|
|
334
|
+
data: DataPayload(currentUptimeMs: currentUptimeMs())
|
|
335
|
+
)
|
|
336
|
+
case .tap:
|
|
337
|
+
if let selectorKey = command.selectorKey, let selectorValue = command.selectorValue {
|
|
338
|
+
let match = findElement(app: activeApp, selectorKey: selectorKey, selectorValue: selectorValue)
|
|
339
|
+
if match.isAmbiguous {
|
|
340
|
+
return Response(ok: false, error: ErrorPayload(code: "AMBIGUOUS_MATCH", message: "selector matched multiple elements"))
|
|
341
|
+
}
|
|
342
|
+
if let element = match.element {
|
|
343
|
+
let frame = element.frame
|
|
344
|
+
let touchFrame = frame.isEmpty
|
|
345
|
+
? nil
|
|
346
|
+
: resolvedTouchVisualizationFrame(app: activeApp, x: frame.midX, y: frame.midY)
|
|
347
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
348
|
+
let timing = measureGesture {
|
|
349
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
350
|
+
outcome = activateElement(app: activeApp, element: element, action: "tap by selector")
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
354
|
+
return response
|
|
355
|
+
}
|
|
356
|
+
return Response(
|
|
357
|
+
ok: true,
|
|
358
|
+
data: DataPayload(
|
|
359
|
+
message: "tapped",
|
|
360
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
361
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
362
|
+
x: touchFrame?.x,
|
|
363
|
+
y: touchFrame?.y,
|
|
364
|
+
referenceWidth: touchFrame?.referenceWidth,
|
|
365
|
+
referenceHeight: touchFrame?.referenceHeight
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
return Response(ok: false, error: ErrorPayload(code: "ELEMENT_NOT_FOUND", message: "element not found"))
|
|
370
|
+
}
|
|
371
|
+
if let text = command.text {
|
|
372
|
+
if let element = findElement(app: activeApp, text: text) {
|
|
373
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
374
|
+
let timing = measureGesture {
|
|
375
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
376
|
+
outcome = activateElement(app: activeApp, element: element, action: "tap by text")
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
380
|
+
return response
|
|
381
|
+
}
|
|
382
|
+
return Response(
|
|
383
|
+
ok: true,
|
|
384
|
+
data: DataPayload(
|
|
385
|
+
message: "tapped",
|
|
386
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
387
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
}
|
|
391
|
+
return Response(ok: false, error: ErrorPayload(message: "element not found"))
|
|
392
|
+
}
|
|
393
|
+
if let x = command.x, let y = command.y {
|
|
394
|
+
let touchFrame = resolvedTouchVisualizationFrame(app: activeApp, x: x, y: y)
|
|
395
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
396
|
+
let timing = measureGesture {
|
|
397
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
398
|
+
outcome = tapAt(app: activeApp, x: x, y: y)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
402
|
+
return response
|
|
403
|
+
}
|
|
404
|
+
return Response(
|
|
405
|
+
ok: true,
|
|
406
|
+
data: DataPayload(
|
|
407
|
+
message: "tapped",
|
|
408
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
409
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
410
|
+
x: touchFrame.x,
|
|
411
|
+
y: touchFrame.y,
|
|
412
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
413
|
+
referenceHeight: touchFrame.referenceHeight
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
return Response(ok: false, error: ErrorPayload(message: "tap requires text or x/y"))
|
|
418
|
+
case .tapBySelector:
|
|
419
|
+
// Find-and-act path: walk the XCUI tree once, find best liberal match
|
|
420
|
+
// (substring + case-insensitive + prefer-editable-inputs ranking),
|
|
421
|
+
// tap at its center. On miss, return the walked snapshot so Go side
|
|
422
|
+
// can fall back to its own snapshot+filter+tap.
|
|
423
|
+
guard let selectorKey = command.selectorKey, let selectorValue = command.selectorValue else {
|
|
424
|
+
return Response(ok: false, error: ErrorPayload(message: "tapBySelector requires selectorKey and selectorValue"))
|
|
425
|
+
}
|
|
426
|
+
// Alerts live in a separate UIWindow whose frames don't translate
|
|
427
|
+
// to the main app's coordinate space — using tapAt(x,y) on those
|
|
428
|
+
// coordinates misses the button and dismisses the alert. So when
|
|
429
|
+
// an alert is up and one of its buttons matches the selector, tap
|
|
430
|
+
// that XCUIElement directly (XCTest handles the window math).
|
|
431
|
+
if let alertResp = tryTapAlertButton(app: activeApp, selectorKey: selectorKey, selectorValue: selectorValue) {
|
|
432
|
+
return alertResp
|
|
433
|
+
}
|
|
434
|
+
// findLiberalMatch's loop doubles as the animation-end gate:
|
|
435
|
+
// it walks the tree per iteration, computes a tree signature
|
|
436
|
+
// in the same pass, and returns only after two consecutive
|
|
437
|
+
// identical signatures — meaning the screen is settled and the
|
|
438
|
+
// match's frame is trustworthy. No separate refresh pass needed.
|
|
439
|
+
let result = findLiberalMatch(app: activeApp, selectorKey: selectorKey, selectorValue: selectorValue)
|
|
440
|
+
guard let matched = result.matched else {
|
|
441
|
+
// Miss — return walked nodes so Go-side fallback can re-filter.
|
|
442
|
+
return Response(ok: false, data: DataPayload(nodes: result.walkedNodes))
|
|
443
|
+
}
|
|
444
|
+
let x = Double(matched.frame.midX)
|
|
445
|
+
let y = Double(matched.frame.midY)
|
|
446
|
+
let touchFrame = resolvedTouchVisualizationFrame(app: activeApp, x: x, y: y)
|
|
447
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
448
|
+
let timing = measureGesture {
|
|
449
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
450
|
+
outcome = tapAt(app: activeApp, x: x, y: y)
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
454
|
+
return response
|
|
455
|
+
}
|
|
456
|
+
// Note: response returns the raw element-relative x/y, not
|
|
457
|
+
// touchFrame.x/y. touchFrame applies the appFrame origin (screen-
|
|
458
|
+
// absolute), but the Go side feeds these into the next inputText's
|
|
459
|
+
// type command which expects element-relative coords.
|
|
460
|
+
return Response(
|
|
461
|
+
ok: true,
|
|
462
|
+
data: DataPayload(
|
|
463
|
+
message: "tapped by selector",
|
|
464
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
465
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
466
|
+
x: x,
|
|
467
|
+
y: y,
|
|
468
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
469
|
+
referenceHeight: touchFrame.referenceHeight,
|
|
470
|
+
identifier: matched.identifier.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
471
|
+
)
|
|
472
|
+
)
|
|
473
|
+
case .mouseClick:
|
|
474
|
+
guard let x = command.x, let y = command.y else {
|
|
475
|
+
return Response(ok: false, error: ErrorPayload(message: "mouseClick requires x and y"))
|
|
476
|
+
}
|
|
477
|
+
let touchFrame = resolvedTouchVisualizationFrame(app: activeApp, x: x, y: y)
|
|
478
|
+
do {
|
|
479
|
+
var clickError: Error?
|
|
480
|
+
let timing = measureGesture {
|
|
481
|
+
do {
|
|
482
|
+
try mouseClickAt(app: activeApp, x: x, y: y, button: command.button ?? "primary")
|
|
483
|
+
} catch {
|
|
484
|
+
clickError = error
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if let clickError {
|
|
488
|
+
throw clickError
|
|
489
|
+
}
|
|
490
|
+
return Response(
|
|
491
|
+
ok: true,
|
|
492
|
+
data: DataPayload(
|
|
493
|
+
message: "clicked",
|
|
494
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
495
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
496
|
+
x: touchFrame.x,
|
|
497
|
+
y: touchFrame.y,
|
|
498
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
499
|
+
referenceHeight: touchFrame.referenceHeight
|
|
500
|
+
)
|
|
501
|
+
)
|
|
502
|
+
} catch {
|
|
503
|
+
return Response(ok: false, error: ErrorPayload(message: error.localizedDescription))
|
|
504
|
+
}
|
|
505
|
+
case .tapSeries:
|
|
506
|
+
guard let x = command.x, let y = command.y else {
|
|
507
|
+
return Response(ok: false, error: ErrorPayload(message: "tapSeries requires x and y"))
|
|
508
|
+
}
|
|
509
|
+
let count = max(Int(command.count ?? 1), 1)
|
|
510
|
+
let intervalMs = max(command.intervalMs ?? 0, 0)
|
|
511
|
+
let doubleTap = command.doubleTap ?? false
|
|
512
|
+
let touchFrame = resolvedTouchVisualizationFrame(app: activeApp, x: x, y: y)
|
|
513
|
+
if doubleTap {
|
|
514
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
515
|
+
let timing = measureGesture {
|
|
516
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
517
|
+
runSeries(count: count, pauseMs: intervalMs) { _ in
|
|
518
|
+
if case .performed = outcome {
|
|
519
|
+
outcome = doubleTapAt(app: activeApp, x: x, y: y)
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
525
|
+
return response
|
|
526
|
+
}
|
|
527
|
+
return Response(
|
|
528
|
+
ok: true,
|
|
529
|
+
data: DataPayload(
|
|
530
|
+
message: "tap series",
|
|
531
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
532
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
533
|
+
x: touchFrame.x,
|
|
534
|
+
y: touchFrame.y,
|
|
535
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
536
|
+
referenceHeight: touchFrame.referenceHeight
|
|
537
|
+
)
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
541
|
+
let timing = measureGesture {
|
|
542
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
543
|
+
runSeries(count: count, pauseMs: intervalMs) { _ in
|
|
544
|
+
if case .performed = outcome {
|
|
545
|
+
outcome = tapAt(app: activeApp, x: x, y: y)
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
551
|
+
return response
|
|
552
|
+
}
|
|
553
|
+
return Response(
|
|
554
|
+
ok: true,
|
|
555
|
+
data: DataPayload(
|
|
556
|
+
message: "tap series",
|
|
557
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
558
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
559
|
+
x: touchFrame.x,
|
|
560
|
+
y: touchFrame.y,
|
|
561
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
562
|
+
referenceHeight: touchFrame.referenceHeight
|
|
563
|
+
)
|
|
564
|
+
)
|
|
565
|
+
case .longPress:
|
|
566
|
+
guard let x = command.x, let y = command.y else {
|
|
567
|
+
return Response(ok: false, error: ErrorPayload(message: "longPress requires x and y"))
|
|
568
|
+
}
|
|
569
|
+
let duration = (command.durationMs ?? 800) / 1000.0
|
|
570
|
+
let touchFrame = resolvedTouchVisualizationFrame(app: activeApp, x: x, y: y)
|
|
571
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
572
|
+
let timing = measureGesture {
|
|
573
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
574
|
+
outcome = longPressAt(app: activeApp, x: x, y: y, duration: duration)
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
578
|
+
return response
|
|
579
|
+
}
|
|
580
|
+
return Response(
|
|
581
|
+
ok: true,
|
|
582
|
+
data: DataPayload(
|
|
583
|
+
message: "long pressed",
|
|
584
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
585
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
586
|
+
x: touchFrame.x,
|
|
587
|
+
y: touchFrame.y,
|
|
588
|
+
referenceWidth: touchFrame.referenceWidth,
|
|
589
|
+
referenceHeight: touchFrame.referenceHeight
|
|
590
|
+
)
|
|
591
|
+
)
|
|
592
|
+
case .drag:
|
|
593
|
+
guard let x = command.x, let y = command.y, let x2 = command.x2, let y2 = command.y2 else {
|
|
594
|
+
return Response(ok: false, error: ErrorPayload(message: "drag requires x, y, x2, and y2"))
|
|
595
|
+
}
|
|
596
|
+
let holdDuration = min(max((command.durationMs ?? 60) / 1000.0, 0.016), 10.0)
|
|
597
|
+
let moveDuration = command.moveDurationMs.map { min(max($0 / 1000.0, 0.05), 30.0) }
|
|
598
|
+
let dragPoints = keyboardAvoidingDragPoints(app: activeApp, x: x, y: y, x2: x2, y2: y2)
|
|
599
|
+
let dragFrame = resolvedDragVisualizationFrame(
|
|
600
|
+
app: activeApp,
|
|
601
|
+
x: dragPoints.x,
|
|
602
|
+
y: dragPoints.y,
|
|
603
|
+
x2: dragPoints.x2,
|
|
604
|
+
y2: dragPoints.y2
|
|
605
|
+
)
|
|
606
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
607
|
+
let timing = measureGesture {
|
|
608
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
609
|
+
outcome = dragAt(
|
|
610
|
+
app: activeApp,
|
|
611
|
+
x: dragPoints.x,
|
|
612
|
+
y: dragPoints.y,
|
|
613
|
+
x2: dragPoints.x2,
|
|
614
|
+
y2: dragPoints.y2,
|
|
615
|
+
holdDuration: holdDuration,
|
|
616
|
+
moveDuration: moveDuration
|
|
617
|
+
)
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
621
|
+
return response
|
|
622
|
+
}
|
|
623
|
+
return Response(
|
|
624
|
+
ok: true,
|
|
625
|
+
data: DataPayload(
|
|
626
|
+
message: "dragged",
|
|
627
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
628
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
629
|
+
x: dragFrame.x,
|
|
630
|
+
y: dragFrame.y,
|
|
631
|
+
x2: dragFrame.x2,
|
|
632
|
+
y2: dragFrame.y2,
|
|
633
|
+
referenceWidth: dragFrame.referenceWidth,
|
|
634
|
+
referenceHeight: dragFrame.referenceHeight
|
|
635
|
+
)
|
|
636
|
+
)
|
|
637
|
+
case .dragSeries:
|
|
638
|
+
guard let x = command.x, let y = command.y, let x2 = command.x2, let y2 = command.y2 else {
|
|
639
|
+
return Response(ok: false, error: ErrorPayload(message: "dragSeries requires x, y, x2, and y2"))
|
|
640
|
+
}
|
|
641
|
+
let count = max(Int(command.count ?? 1), 1)
|
|
642
|
+
let pauseMs = max(command.pauseMs ?? 0, 0)
|
|
643
|
+
let pattern = command.pattern ?? "one-way"
|
|
644
|
+
if pattern != "one-way" && pattern != "ping-pong" {
|
|
645
|
+
return Response(ok: false, error: ErrorPayload(message: "dragSeries pattern must be one-way or ping-pong"))
|
|
646
|
+
}
|
|
647
|
+
let holdDuration = min(max((command.durationMs ?? 60) / 1000.0, 0.016), 10.0)
|
|
648
|
+
let dragPoints = keyboardAvoidingDragPoints(app: activeApp, x: x, y: y, x2: x2, y2: y2)
|
|
649
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
650
|
+
let timing = measureGesture {
|
|
651
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
652
|
+
runSeries(count: count, pauseMs: pauseMs) { idx in
|
|
653
|
+
guard case .performed = outcome else {
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
let reverse = pattern == "ping-pong" && (idx % 2 == 1)
|
|
657
|
+
if reverse {
|
|
658
|
+
outcome = dragAt(
|
|
659
|
+
app: activeApp,
|
|
660
|
+
x: dragPoints.x2,
|
|
661
|
+
y: dragPoints.y2,
|
|
662
|
+
x2: dragPoints.x,
|
|
663
|
+
y2: dragPoints.y,
|
|
664
|
+
holdDuration: holdDuration
|
|
665
|
+
)
|
|
666
|
+
} else {
|
|
667
|
+
outcome = dragAt(
|
|
668
|
+
app: activeApp,
|
|
669
|
+
x: dragPoints.x,
|
|
670
|
+
y: dragPoints.y,
|
|
671
|
+
x2: dragPoints.x2,
|
|
672
|
+
y2: dragPoints.y2,
|
|
673
|
+
holdDuration: holdDuration
|
|
674
|
+
)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
680
|
+
return response
|
|
681
|
+
}
|
|
682
|
+
return Response(
|
|
683
|
+
ok: true,
|
|
684
|
+
data: DataPayload(
|
|
685
|
+
message: "drag series",
|
|
686
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
687
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs
|
|
688
|
+
)
|
|
689
|
+
)
|
|
690
|
+
case .remotePress:
|
|
691
|
+
guard let button = tvRemoteButton(from: command.remoteButton) else {
|
|
692
|
+
return Response(ok: false, error: ErrorPayload(message: "remotePress requires remoteButton"))
|
|
693
|
+
}
|
|
694
|
+
let duration = (command.durationMs ?? 0) / 1000.0
|
|
695
|
+
guard pressTvRemote(button, duration: duration) else {
|
|
696
|
+
return Response(
|
|
697
|
+
ok: false,
|
|
698
|
+
error: ErrorPayload(code: "UNSUPPORTED_OPERATION", message: "remotePress is only supported on tvOS")
|
|
699
|
+
)
|
|
700
|
+
}
|
|
701
|
+
return Response(ok: true, data: DataPayload(message: "remote pressed"))
|
|
702
|
+
case .type:
|
|
703
|
+
var response: Response?
|
|
704
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
705
|
+
response = executeTypeCommand(activeApp: activeApp, command: command)
|
|
706
|
+
}
|
|
707
|
+
return response ?? Response(ok: false, error: ErrorPayload(message: "type produced no response"))
|
|
708
|
+
case .interactionFrame:
|
|
709
|
+
let frame = resolvedTouchReferenceFrame(app: activeApp, appFrame: activeApp.frame)
|
|
710
|
+
return Response(
|
|
711
|
+
ok: true,
|
|
712
|
+
data: DataPayload(
|
|
713
|
+
x: frame.minX,
|
|
714
|
+
y: frame.minY,
|
|
715
|
+
referenceWidth: frame.width,
|
|
716
|
+
referenceHeight: frame.height
|
|
717
|
+
)
|
|
718
|
+
)
|
|
719
|
+
case .swipe:
|
|
720
|
+
guard let direction = command.direction else {
|
|
721
|
+
return Response(ok: false, error: ErrorPayload(message: "swipe requires direction"))
|
|
722
|
+
}
|
|
723
|
+
var executedFrame: DragVisualizationFrame?
|
|
724
|
+
let timing = measureGesture {
|
|
725
|
+
withTemporaryScrollIdleTimeoutIfSupported(activeApp) {
|
|
726
|
+
executedFrame = swipe(
|
|
727
|
+
app: activeApp,
|
|
728
|
+
direction: direction
|
|
729
|
+
)
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
guard let dragFrame = executedFrame else {
|
|
733
|
+
return Response(ok: false, error: ErrorPayload(message: "swipe is only supported on tvOS"))
|
|
734
|
+
}
|
|
735
|
+
return Response(
|
|
736
|
+
ok: true,
|
|
737
|
+
data: DataPayload(
|
|
738
|
+
message: "swiped",
|
|
739
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
740
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs,
|
|
741
|
+
x: dragFrame.x,
|
|
742
|
+
y: dragFrame.y,
|
|
743
|
+
x2: dragFrame.x2,
|
|
744
|
+
y2: dragFrame.y2,
|
|
745
|
+
referenceWidth: dragFrame.referenceWidth,
|
|
746
|
+
referenceHeight: dragFrame.referenceHeight
|
|
747
|
+
)
|
|
748
|
+
)
|
|
749
|
+
case .findText:
|
|
750
|
+
guard let text = command.text else {
|
|
751
|
+
return Response(ok: false, error: ErrorPayload(message: "findText requires text"))
|
|
752
|
+
}
|
|
753
|
+
let found = findElement(app: activeApp, text: text) != nil
|
|
754
|
+
return Response(ok: true, data: DataPayload(found: found))
|
|
755
|
+
case .querySelector:
|
|
756
|
+
guard let selectorKey = command.selectorKey, let selectorValue = command.selectorValue else {
|
|
757
|
+
return Response(ok: false, error: ErrorPayload(message: "querySelector requires selectorKey and selectorValue"))
|
|
758
|
+
}
|
|
759
|
+
return queryElement(app: activeApp, selectorKey: selectorKey, selectorValue: selectorValue)
|
|
760
|
+
case .readText:
|
|
761
|
+
guard let x = command.x, let y = command.y else {
|
|
762
|
+
return Response(ok: false, error: ErrorPayload(message: "readText requires x and y"))
|
|
763
|
+
}
|
|
764
|
+
guard let text = readTextAt(app: activeApp, x: x, y: y) else {
|
|
765
|
+
return Response(ok: false, error: ErrorPayload(message: "readText did not resolve text"))
|
|
766
|
+
}
|
|
767
|
+
return Response(ok: true, data: DataPayload(text: text))
|
|
768
|
+
case .snapshot:
|
|
769
|
+
let options = SnapshotOptions(
|
|
770
|
+
interactiveOnly: command.interactiveOnly ?? false,
|
|
771
|
+
compact: command.compact ?? false,
|
|
772
|
+
depth: command.depth,
|
|
773
|
+
scope: command.scope,
|
|
774
|
+
raw: command.raw ?? false
|
|
775
|
+
)
|
|
776
|
+
if options.raw {
|
|
777
|
+
needsPostSnapshotInteractionDelay = true
|
|
778
|
+
return Response(ok: true, data: snapshotRaw(app: activeApp, options: options))
|
|
779
|
+
}
|
|
780
|
+
needsPostSnapshotInteractionDelay = true
|
|
781
|
+
return Response(ok: true, data: snapshotFast(app: activeApp, options: options))
|
|
782
|
+
case .screenshot:
|
|
783
|
+
let screenshot: XCUIScreenshot
|
|
784
|
+
#if os(macOS)
|
|
785
|
+
// macOS keeps the app-targeted capture behavior for window-level screenshots.
|
|
786
|
+
if let bundleId = command.appBundleId, !bundleId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
787
|
+
let targetApp = XCUIApplication(bundleIdentifier: bundleId)
|
|
788
|
+
targetApp.activate()
|
|
789
|
+
activeApp = targetApp
|
|
790
|
+
// Brief wait for the app transition animation to complete
|
|
791
|
+
sleepFor(0.5)
|
|
792
|
+
}
|
|
793
|
+
if command.fullscreen == true {
|
|
794
|
+
screenshot = XCUIScreen.main.screenshot()
|
|
795
|
+
} else if let bundleId = command.appBundleId, !bundleId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
796
|
+
screenshot = screenshotRoot(app: activeApp).screenshot()
|
|
797
|
+
} else {
|
|
798
|
+
screenshot = XCUIScreen.main.screenshot()
|
|
799
|
+
}
|
|
800
|
+
#else
|
|
801
|
+
screenshot = XCUIScreen.main.screenshot()
|
|
802
|
+
#endif
|
|
803
|
+
guard let pngData = runnerPngData(for: screenshot.image) else {
|
|
804
|
+
return Response(ok: false, error: ErrorPayload(message: "Failed to encode screenshot as PNG"))
|
|
805
|
+
}
|
|
806
|
+
// Local edit: return PNG bytes inline (base64). Upstream writes
|
|
807
|
+
// the file and returns its path so the TS daemon can read it from
|
|
808
|
+
// the sim's tmp container; maestro-runner needs the bytes back on
|
|
809
|
+
// the host without an extra simctl roundtrip. We skip the file
|
|
810
|
+
// write entirely.
|
|
811
|
+
let base64 = pngData.base64EncodedString()
|
|
812
|
+
return Response(ok: true, data: DataPayload(message: "screenshot", pngBase64: base64))
|
|
813
|
+
case .back, .backInApp:
|
|
814
|
+
if tapInAppBackControl(app: activeApp) {
|
|
815
|
+
let message = command.command == .back ? "back" : "backInApp"
|
|
816
|
+
return Response(ok: true, data: DataPayload(message: message))
|
|
817
|
+
}
|
|
818
|
+
return Response(ok: false, error: ErrorPayload(message: "in-app back control is not available"))
|
|
819
|
+
case .backSystem:
|
|
820
|
+
if performSystemBackAction(app: activeApp) {
|
|
821
|
+
return Response(ok: true, data: DataPayload(message: "backSystem"))
|
|
822
|
+
}
|
|
823
|
+
return Response(ok: false, error: ErrorPayload(message: "system back is not available"))
|
|
824
|
+
case .home:
|
|
825
|
+
pressHomeButton()
|
|
826
|
+
return Response(ok: true, data: DataPayload(message: "home"))
|
|
827
|
+
case .rotate:
|
|
828
|
+
guard let orientation = command.orientation?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
829
|
+
!orientation.isEmpty
|
|
830
|
+
else {
|
|
831
|
+
return Response(ok: false, error: ErrorPayload(message: "rotate requires orientation"))
|
|
832
|
+
}
|
|
833
|
+
if rotateDevice(to: orientation) {
|
|
834
|
+
return Response(
|
|
835
|
+
ok: true,
|
|
836
|
+
data: DataPayload(message: "rotate", orientation: orientation)
|
|
837
|
+
)
|
|
838
|
+
}
|
|
839
|
+
return Response(
|
|
840
|
+
ok: false,
|
|
841
|
+
error: ErrorPayload(message: "unsupported rotate orientation: \(orientation)")
|
|
842
|
+
)
|
|
843
|
+
case .appearance:
|
|
844
|
+
return Response(
|
|
845
|
+
ok: true,
|
|
846
|
+
data: DataPayload(message: "appearance", appearance: appearanceName(XCUIDevice.shared.appearance))
|
|
847
|
+
)
|
|
848
|
+
case .setAppearance:
|
|
849
|
+
guard let wanted = command.appearance?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
850
|
+
!wanted.isEmpty
|
|
851
|
+
else {
|
|
852
|
+
return Response(ok: false, error: ErrorPayload(message: "setAppearance requires appearance"))
|
|
853
|
+
}
|
|
854
|
+
guard let style = appearanceValue(wanted) else {
|
|
855
|
+
return Response(
|
|
856
|
+
ok: false,
|
|
857
|
+
error: ErrorPayload(message: "unsupported appearance: \(wanted)")
|
|
858
|
+
)
|
|
859
|
+
}
|
|
860
|
+
XCUIDevice.shared.appearance = style
|
|
861
|
+
// Read back rather than echoing the request: the setter is a request to
|
|
862
|
+
// the system, and reporting what actually took effect is what makes the
|
|
863
|
+
// host's assertDarkMode meaningful.
|
|
864
|
+
return Response(
|
|
865
|
+
ok: true,
|
|
866
|
+
data: DataPayload(message: "setAppearance", appearance: appearanceName(XCUIDevice.shared.appearance))
|
|
867
|
+
)
|
|
868
|
+
case .appSwitcher:
|
|
869
|
+
performAppSwitcherGesture(app: activeApp)
|
|
870
|
+
return Response(ok: true, data: DataPayload(message: "appSwitcher"))
|
|
871
|
+
case .keyboardDismiss:
|
|
872
|
+
let result = dismissKeyboard(app: activeApp)
|
|
873
|
+
if result.wasVisible && !result.dismissed {
|
|
874
|
+
return Response(
|
|
875
|
+
ok: false,
|
|
876
|
+
error: ErrorPayload(
|
|
877
|
+
code: "UNSUPPORTED_OPERATION",
|
|
878
|
+
message: "Unable to dismiss the iOS keyboard without a native dismiss gesture or control"
|
|
879
|
+
)
|
|
880
|
+
)
|
|
881
|
+
}
|
|
882
|
+
return Response(
|
|
883
|
+
ok: true,
|
|
884
|
+
data: DataPayload(
|
|
885
|
+
message: "keyboardDismiss",
|
|
886
|
+
visible: result.visible,
|
|
887
|
+
wasVisible: result.wasVisible,
|
|
888
|
+
dismissed: result.dismissed
|
|
889
|
+
)
|
|
890
|
+
)
|
|
891
|
+
case .alert:
|
|
892
|
+
let action = (command.action ?? "get").lowercased()
|
|
893
|
+
guard let alert = resolveAlert(app: activeApp) else {
|
|
894
|
+
return Response(ok: false, error: ErrorPayload(message: "alert not found"))
|
|
895
|
+
}
|
|
896
|
+
return handleAlert(alert, action: action)
|
|
897
|
+
case .pinch:
|
|
898
|
+
guard let scale = command.scale, scale > 0 else {
|
|
899
|
+
return Response(ok: false, error: ErrorPayload(message: "pinch requires scale > 0"))
|
|
900
|
+
}
|
|
901
|
+
var outcome = RunnerInteractionOutcome.performed
|
|
902
|
+
let timing = measureGesture {
|
|
903
|
+
outcome = pinch(app: activeApp, scale: scale, x: command.x, y: command.y)
|
|
904
|
+
}
|
|
905
|
+
if let response = unsupportedResponse(for: outcome) {
|
|
906
|
+
return response
|
|
907
|
+
}
|
|
908
|
+
return Response(
|
|
909
|
+
ok: true,
|
|
910
|
+
data: DataPayload(
|
|
911
|
+
message: "pinched",
|
|
912
|
+
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
913
|
+
gestureEndUptimeMs: timing.gestureEndUptimeMs
|
|
914
|
+
)
|
|
915
|
+
)
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
private func executeTypeCommand(activeApp: XCUIApplication, command: Command) -> Response {
|
|
920
|
+
guard let text = command.text else {
|
|
921
|
+
return Response(ok: false, error: ErrorPayload(message: "type requires text"))
|
|
922
|
+
}
|
|
923
|
+
let delaySeconds = Double(max(command.delayMs ?? 0, 0)) / 1000.0
|
|
924
|
+
let textEntryMode = resolveTextEntryMode(command)
|
|
925
|
+
// Local edit: pass the `id` selector value as an identifier hint so
|
|
926
|
+
// focusTextInputForTextEntry can resolve the target via XCTest's
|
|
927
|
+
// query DSL instead of walking the full descendant tree.
|
|
928
|
+
let identifierHint = command.selectorKey == "id" ? command.selectorValue : nil
|
|
929
|
+
let target = focusTextInputForTextEntry(
|
|
930
|
+
app: activeApp, x: command.x, y: command.y, identifier: identifierHint
|
|
931
|
+
)
|
|
932
|
+
if textEntryMode == .replacement {
|
|
933
|
+
guard target.element != nil else {
|
|
934
|
+
let message =
|
|
935
|
+
(command.x != nil && command.y != nil)
|
|
936
|
+
? "no text input found at the provided coordinates to clear"
|
|
937
|
+
: "no focused text input to clear"
|
|
938
|
+
return Response(ok: false, error: ErrorPayload(message: message))
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
let textResult = typeTextReliably(
|
|
942
|
+
app: activeApp,
|
|
943
|
+
target: target,
|
|
944
|
+
text: text,
|
|
945
|
+
delaySeconds: delaySeconds,
|
|
946
|
+
repairMode: textEntryMode
|
|
947
|
+
)
|
|
948
|
+
if textResult.verified == false {
|
|
949
|
+
let expected = textResult.expectedText ?? ""
|
|
950
|
+
let observed = textResult.observedText ?? ""
|
|
951
|
+
return Response(
|
|
952
|
+
ok: false,
|
|
953
|
+
error: ErrorPayload(
|
|
954
|
+
code: "TEXT_ENTRY_MISMATCH",
|
|
955
|
+
message: "text entry verification failed: expected \"\(expected)\", observed \"\(observed)\""
|
|
956
|
+
)
|
|
957
|
+
)
|
|
958
|
+
}
|
|
959
|
+
return Response(ok: true, data: DataPayload(message: textResult.repaired ? "typed after repair" : "typed"))
|
|
960
|
+
}
|
|
961
|
+
}
|