agent-device 0.21.14 → 0.21.15
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/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.14.apk → agent-device-android-ime-helper-0.21.15.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.15.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.14.manifest.json → agent-device-android-ime-helper-0.21.15.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.15.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.15.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.14.manifest.json → agent-device-android-snapshot-helper-0.21.15.manifest.json} +6 -6
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +87 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerMainOwnedState.swift +27 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +8 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +26 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +40 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +179 -91
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -49
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +11 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +136 -29
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +6 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +8 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +56 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +18 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +9 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +2 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +78 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +32 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +7 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +23 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +17 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +8 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +12 -11
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +7 -4
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +15 -8
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +1 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +26 -9
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -0
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +1 -1
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.d.ts +1 -8
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android-snapshot-quality.js +1 -0
- package/dist/src/android-system-chrome.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-runtime2.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/capture-disclosure.js +1 -1
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +102 -95
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +3 -3
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +15 -2
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor2.js +1 -1
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/format.js +1 -1
- package/dist/src/gesture-plan-types.d.ts +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact-facade.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -1
- package/dist/src/interactor.js +4 -4
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-engine.js +1 -0
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-download-file.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +16 -3
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +17 -17
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/native-build-cache.js +1 -1
- package/dist/src/observation.js +1 -1
- package/dist/src/overlay.js +3 -0
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-size.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/provider-session-ownership.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +36 -36
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +1 -1
- package/dist/src/reporting.js +1 -1
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/runner-cache-metadata.js +1 -1
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +2 -2
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +1 -3
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.d.ts +13 -6
- package/dist/src/scroll-command.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch-runner.js +1 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +38 -10
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +2 -2
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +4 -4
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -1
- package/dist/src/snapshot-desktop-projection.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src4.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/string-enum.js +1 -1
- package/dist/src/surface-snapshot.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/transport.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.14.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk.sha256 +0 -1
- package/dist/src/absence-observation-errors.js +0 -1
- package/dist/src/runner-presentation.js +0 -1
- package/dist/src/semantic-index.js +0 -1
- package/dist/src/snapshot-scope.js +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2f8d38e6705542b327057b059c77cf3a6358fa2fc9a53e4bf5ecfb6279c441bf agent-device-android-ime-helper-0.21.15.apk
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-ime-helper",
|
|
3
|
-
"version": "0.21.
|
|
4
|
-
"assetName": "agent-device-android-ime-helper-0.21.
|
|
5
|
-
"sha256": "
|
|
3
|
+
"version": "0.21.15",
|
|
4
|
+
"assetName": "agent-device-android-ime-helper-0.21.15.apk",
|
|
5
|
+
"sha256": "2f8d38e6705542b327057b059c77cf3a6358fa2fc9a53e4bf5ecfb6279c441bf",
|
|
6
6
|
"packageName": "com.callstack.agentdevice.imehelper",
|
|
7
|
-
"versionCode":
|
|
7
|
+
"versionCode": 21015,
|
|
8
8
|
"serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
|
|
9
9
|
"broadcastProtocol": "android-ime-helper-v1"
|
|
10
10
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
af733a540d518ede88f0336564d6d4d03b05191732130b65a3094228fa1bed54 agent-device-android-snapshot-helper-0.21.15.apk
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-snapshot-helper",
|
|
3
|
-
"version": "0.21.
|
|
4
|
-
"releaseTag": "v0.21.
|
|
5
|
-
"assetName": "agent-device-android-snapshot-helper-0.21.
|
|
3
|
+
"version": "0.21.15",
|
|
4
|
+
"releaseTag": "v0.21.15",
|
|
5
|
+
"assetName": "agent-device-android-snapshot-helper-0.21.15.apk",
|
|
6
6
|
"apkUrl": null,
|
|
7
|
-
"sha256": "
|
|
8
|
-
"checksumName": "agent-device-android-snapshot-helper-0.21.
|
|
7
|
+
"sha256": "af733a540d518ede88f0336564d6d4d03b05191732130b65a3094228fa1bed54",
|
|
8
|
+
"checksumName": "agent-device-android-snapshot-helper-0.21.15.apk.sha256",
|
|
9
9
|
"packageName": "com.callstack.agentdevice.snapshothelper",
|
|
10
|
-
"versionCode":
|
|
10
|
+
"versionCode": 21015,
|
|
11
11
|
"instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
|
|
12
12
|
"minSdk": 23,
|
|
13
13
|
"targetSdk": 36,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
NSString *const kProtocolVersionKey = @"protocolVersion";
|
|
19
19
|
NSString *const kSourceVersionKey = @"sourceVersion";
|
|
20
20
|
NSString *const kRequestIdKey = @"requestId";
|
|
21
|
-
NSString *const kSourceVersion = @"agent-device-simulator-ax-v1.
|
|
21
|
+
NSString *const kSourceVersion = @"agent-device-simulator-ax-v1.8.0";
|
|
22
22
|
const NSUInteger kProtocolVersion = 1;
|
|
23
23
|
const uint32_t kMaximumFrameBytes = 16 * 1024 * 1024;
|
|
24
24
|
const NSUInteger kMaximumDepth = 128;
|
|
@@ -29,6 +29,7 @@ static NSString *const kAttributeElementType = @"XC_kAXXCAttributeElementType";
|
|
|
29
29
|
static NSString *const kAttributeElementBaseType = @"XC_kAXXCAttributeElementBaseType";
|
|
30
30
|
static NSString *const kAttributeLabel = @"XC_kAXXCAttributeLabel";
|
|
31
31
|
static NSString *const kAttributeValue = @"XC_kAXXCAttributeValue";
|
|
32
|
+
static NSString *const kAttributePlaceholderValue = @"XC_kAXXCAttributePlaceholderValue";
|
|
32
33
|
static NSString *const kAttributeIdentifier = @"XC_kAXXCAttributeIdentifier";
|
|
33
34
|
static NSString *const kAttributeFrame = @"XC_kAXXCAttributeFrame";
|
|
34
35
|
static NSString *const kAttributeAutomationType = @"XC_kAXXCAttributeAutomationType";
|
|
@@ -330,6 +331,7 @@ static void finishRequestWatchdog(dispatch_source_t watchdog, SnapshotWatchdogSt
|
|
|
330
331
|
kAttributeElementBaseType,
|
|
331
332
|
kAttributeLabel,
|
|
332
333
|
kAttributeValue,
|
|
334
|
+
kAttributePlaceholderValue,
|
|
333
335
|
kAttributeIdentifier,
|
|
334
336
|
kAttributeFrame,
|
|
335
337
|
kAttributeAutomationType,
|
|
@@ -337,6 +339,14 @@ static void finishRequestWatchdog(dispatch_source_t watchdog, SnapshotWatchdogSt
|
|
|
337
339
|
kAttributeChildren,
|
|
338
340
|
];
|
|
339
341
|
NSArray<NSNumber *> *numbers = _attributeNumbersForNames(names);
|
|
342
|
+
if (![numbers isKindOfClass:NSArray.class] || numbers.count != names.count) {
|
|
343
|
+
// The placeholder attribute is optional: a runtime whose vocabulary lacks it serves the capture
|
|
344
|
+
// without placeholders rather than failing every capture over a fact no consumer depends on.
|
|
345
|
+
NSMutableArray<NSString *> *required = [names mutableCopy];
|
|
346
|
+
[required removeObject:kAttributePlaceholderValue];
|
|
347
|
+
names = required;
|
|
348
|
+
numbers = _attributeNumbersForNames(names);
|
|
349
|
+
}
|
|
340
350
|
if (![numbers isKindOfClass:NSArray.class] || numbers.count != names.count) {
|
|
341
351
|
if (error) *error = failureResponse(requestId, @"reader_unavailable", @"attribute-vocabulary-mismatch", @"AX attribute vocabulary is incompatible");
|
|
342
352
|
finishRequestWatchdog(watchdog, watchdogState);
|
|
@@ -65,6 +65,15 @@ int main(int argc, const char *argv[]) {
|
|
|
65
65
|
@property(nonatomic, strong) UILabel *alertActivationBusyAnswer;
|
|
66
66
|
@property(nonatomic, assign) NSUInteger firstAlertActions;
|
|
67
67
|
@property(nonatomic, assign) NSUInteger replacementAlertActions;
|
|
68
|
+
@property(nonatomic, strong) UILabel *textEntryWriteBackStatus;
|
|
69
|
+
@property(nonatomic, assign) NSUInteger textEntryRenderedEdits;
|
|
70
|
+
@property(nonatomic, assign) NSUInteger textEntryWriteBacks;
|
|
71
|
+
@property(nonatomic, copy, nullable) NSString *textEntryRenderedValue;
|
|
72
|
+
@property(nonatomic, assign) NSTimeInterval textEntryLastEditTime;
|
|
73
|
+
@property(nonatomic, assign) NSTimeInterval textEntryBurstStartTime;
|
|
74
|
+
@property(nonatomic, assign) NSUInteger textEntryBurstEdits;
|
|
75
|
+
@property(nonatomic, assign) NSTimeInterval textEntryBurstMinGap;
|
|
76
|
+
@property(nonatomic, assign) NSTimeInterval textEntryAcknowledgeWindowSeconds;
|
|
68
77
|
@property(nonatomic, assign) BOOL alertFixtureStarted;
|
|
69
78
|
@property(nonatomic, strong) NSTimer *alertActivationBusyBackstop;
|
|
70
79
|
@property(nonatomic, strong) NSTimer *alertBannerRepost;
|
|
@@ -175,6 +184,17 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
|
|
|
175
184
|
(unsigned long)self.replacementAlertActions];
|
|
176
185
|
}
|
|
177
186
|
|
|
187
|
+
- (void)updateTextEntryWriteBackStatus {
|
|
188
|
+
NSTimeInterval burstSpan = self.textEntryLastEditTime - self.textEntryBurstStartTime;
|
|
189
|
+
self.textEntryWriteBackStatus.text = [NSString
|
|
190
|
+
stringWithFormat:@"edits=%lu write-backs=%lu burst-edits=%lu burst-ms=%lu min-gap-ms=%lu",
|
|
191
|
+
(unsigned long)self.textEntryRenderedEdits,
|
|
192
|
+
(unsigned long)self.textEntryWriteBacks,
|
|
193
|
+
(unsigned long)self.textEntryBurstEdits,
|
|
194
|
+
(unsigned long)llround(burstSpan * 1000),
|
|
195
|
+
(unsigned long)llround(self.textEntryBurstMinGap * 1000)];
|
|
196
|
+
}
|
|
197
|
+
|
|
178
198
|
- (void)presentAlertFixtureReplacement:(BOOL)replacement {
|
|
179
199
|
NSArray<NSString *> *arguments = NSProcessInfo.processInfo.arguments;
|
|
180
200
|
BOOL sameTitle = [arguments containsObject:@"--agent-device-alert-same-title"];
|
|
@@ -230,14 +250,58 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
|
|
|
230
250
|
}
|
|
231
251
|
}
|
|
232
252
|
}
|
|
233
|
-
|
|
253
|
+
|
|
254
|
+
// How fast an app that owns this field's value can acknowledge edits: one render per window, passed
|
|
255
|
+
// by the test as `--agent-device-text-entry-acknowledge-window <seconds>`. An edit that arrives
|
|
256
|
+
// inside that window overtook the render still in flight, so the value that render commits predates
|
|
257
|
+
// it and writing it erases the characters that got ahead of the app. The app then reads its own
|
|
258
|
+
// erasure back into its model, which is why the field stays wrong instead of healing when the burst
|
|
259
|
+
// finishes. The window is decided at the edit rather than scheduled, so a loaded host, which
|
|
260
|
+
// stretches the gaps between characters, can only make this app keep up better.
|
|
261
|
+
static NSTimeInterval AgentDeviceTextEntryAcknowledgeWindow(void) {
|
|
262
|
+
NSArray<NSString *> *arguments = NSProcessInfo.processInfo.arguments;
|
|
263
|
+
NSUInteger index = [arguments indexOfObject:@"--agent-device-text-entry-acknowledge-window"];
|
|
264
|
+
return index == NSNotFound || index + 1 >= arguments.count ? 0 : [arguments[index + 1] doubleValue];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Edits further apart than this belong to different bursts: one runner command's characters arrive
|
|
268
|
+
// well inside it, and two commands are separated by at least a commit-wait poll and a status read.
|
|
269
|
+
static const NSTimeInterval AgentDeviceTextEntryBurstBreakSeconds = 1.0;
|
|
234
270
|
|
|
235
271
|
- (void)agentDeviceTextEntryDidChange:(UITextField *)textField {
|
|
272
|
+
// A field whose app owns its value, the way a controlled React Native `TextInput` does. A burst
|
|
273
|
+
// typed faster than the app renders loses the characters that arrived while a render was in
|
|
274
|
+
// flight, and the field settles stable short of the request.
|
|
275
|
+
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-text-entry-app-owned-value"]) {
|
|
276
|
+
NSTimeInterval now = NSProcessInfo.processInfo.systemUptime;
|
|
277
|
+
NSTimeInterval gap = now - self.textEntryLastEditTime;
|
|
278
|
+
BOOL overtookARender = self.textEntryRenderedValue != nil && gap < self.textEntryAcknowledgeWindowSeconds;
|
|
279
|
+
if (self.textEntryBurstEdits == 0 || gap > AgentDeviceTextEntryBurstBreakSeconds) {
|
|
280
|
+
self.textEntryBurstStartTime = now;
|
|
281
|
+
self.textEntryBurstEdits = 0;
|
|
282
|
+
self.textEntryBurstMinGap = 0;
|
|
283
|
+
} else if (self.textEntryBurstEdits == 1 || gap < self.textEntryBurstMinGap) {
|
|
284
|
+
self.textEntryBurstMinGap = gap;
|
|
285
|
+
}
|
|
286
|
+
self.textEntryBurstEdits += 1;
|
|
287
|
+
self.textEntryLastEditTime = now;
|
|
288
|
+
if (overtookARender) {
|
|
289
|
+
if (![textField.text isEqualToString:self.textEntryRenderedValue]) {
|
|
290
|
+
textField.text = self.textEntryRenderedValue;
|
|
291
|
+
self.textEntryWriteBacks += 1;
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
self.textEntryRenderedValue = [textField.text copy];
|
|
295
|
+
self.textEntryRenderedEdits += 1;
|
|
296
|
+
}
|
|
297
|
+
[self updateTextEntryWriteBackStatus];
|
|
298
|
+
}
|
|
236
299
|
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-text-entry-disappear-after-input"] &&
|
|
237
300
|
textField.text.length > 0) {
|
|
238
301
|
[textField removeFromSuperview];
|
|
239
302
|
}
|
|
240
303
|
}
|
|
304
|
+
#endif
|
|
241
305
|
|
|
242
306
|
- (void)viewDidLoad {
|
|
243
307
|
[super viewDidLoad];
|
|
@@ -281,7 +345,13 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
|
|
|
281
345
|
UITextField *textField = [[UITextField alloc] init];
|
|
282
346
|
textField.accessibilityIdentifier = @"agent-device-hardware-keyboard-input";
|
|
283
347
|
textField.borderStyle = UITextBorderStyleRoundedRect;
|
|
284
|
-
|
|
348
|
+
// An empty input view keeps the software keyboard down, which is the hardware-keyboard responder
|
|
349
|
+
// these routes are addressed to. `--agent-device-text-entry-soft-keyboard` leaves the real input
|
|
350
|
+
// view in place, so a lane test can reach the branch that requires a visible keyboard.
|
|
351
|
+
if (![NSProcessInfo.processInfo.arguments
|
|
352
|
+
containsObject:@"--agent-device-text-entry-soft-keyboard"]) {
|
|
353
|
+
textField.inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
|
|
354
|
+
}
|
|
285
355
|
[textField addTarget:self
|
|
286
356
|
action:@selector(agentDeviceTextEntryDidChange:)
|
|
287
357
|
forControlEvents:UIControlEventEditingChanged];
|
|
@@ -293,6 +363,21 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
|
|
|
293
363
|
[textField.widthAnchor constraintEqualToConstant:240],
|
|
294
364
|
[textField.heightAnchor constraintEqualToConstant:44],
|
|
295
365
|
]];
|
|
366
|
+
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-text-entry-app-owned-value"]) {
|
|
367
|
+
self.textEntryAcknowledgeWindowSeconds = AgentDeviceTextEntryAcknowledgeWindow();
|
|
368
|
+
// Reports how many edits this app rendered and how many writes it had to make because a
|
|
369
|
+
// character overtook one, so a lane test can tell a burst the app kept up with from an inert
|
|
370
|
+
// fixture. Counts only: no field content crosses into the test.
|
|
371
|
+
self.textEntryWriteBackStatus = [[UILabel alloc] init];
|
|
372
|
+
self.textEntryWriteBackStatus.accessibilityIdentifier = @"agent-device-text-entry-write-backs";
|
|
373
|
+
self.textEntryWriteBackStatus.translatesAutoresizingMaskIntoConstraints = NO;
|
|
374
|
+
[self.view addSubview:self.textEntryWriteBackStatus];
|
|
375
|
+
[NSLayoutConstraint activateConstraints:@[
|
|
376
|
+
[self.textEntryWriteBackStatus.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
|
|
377
|
+
[self.textEntryWriteBackStatus.topAnchor constraintEqualToAnchor:textField.bottomAnchor constant:12],
|
|
378
|
+
]];
|
|
379
|
+
[self updateTextEntryWriteBackStatus];
|
|
380
|
+
}
|
|
296
381
|
}
|
|
297
382
|
|
|
298
383
|
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-crowded-screen"]) {
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m
CHANGED
|
@@ -365,6 +365,7 @@ typedef id (*RunnerAXSnapshotMsgSend)(id, SEL, id, id, id, NSError **);
|
|
|
365
365
|
@"identifier",
|
|
366
366
|
@"label",
|
|
367
367
|
@"value",
|
|
368
|
+
@"placeholderValue",
|
|
368
369
|
@"frame",
|
|
369
370
|
@"enabled",
|
|
370
371
|
@"selected",
|
|
@@ -388,8 +389,8 @@ typedef id (*RunnerAXSnapshotMsgSend)(id, SEL, id, id, id, NSError **);
|
|
|
388
389
|
// The mapper expands keypaths with extra attributes (automation type, window display
|
|
389
390
|
// id, base type) that are disproportionately expensive for the AX server to compute
|
|
390
391
|
// on large React Native trees. Keep only the attributes we actually consume.
|
|
391
|
-
NSArray *needed = @[ @"ElementType", @"Identifier", @"Label", @"Value", @"
|
|
392
|
-
@"Enabled", @"Selected", @"Focus" ];
|
|
392
|
+
NSArray *needed = @[ @"ElementType", @"Identifier", @"Label", @"Value", @"PlaceholderValue",
|
|
393
|
+
@"Frame", @"Enabled", @"Selected", @"Focus" ];
|
|
393
394
|
NSMutableArray *filtered = [NSMutableArray array];
|
|
394
395
|
for (id attribute in (NSArray *)mapped) {
|
|
395
396
|
NSString *name = [attribute description];
|
|
@@ -764,6 +765,7 @@ typedef id (*RunnerAXSnapshotMsgSend)(id, SEL, id, id, id, NSError **);
|
|
|
764
765
|
result[@"identifier"] = [self stringValueForKey:@"identifier" snapshot:snapshot] ?: @"";
|
|
765
766
|
result[@"label"] = [self stringValueForKey:@"label" snapshot:snapshot] ?: @"";
|
|
766
767
|
result[@"value"] = [self stringValueForKey:@"value" snapshot:snapshot] ?: @"";
|
|
768
|
+
result[@"placeholder"] = [self stringValueForKey:@"placeholderValue" snapshot:snapshot] ?: @"";
|
|
767
769
|
result[@"frame"] = [self frameValueForSnapshot:snapshot];
|
|
768
770
|
result[@"enabled"] = [self boolNumberForKey:@"enabled" snapshot:snapshot defaultValue:YES];
|
|
769
771
|
result[@"selected"] = [self boolNumberForKey:@"selected" snapshot:snapshot defaultValue:NO];
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerMainOwnedState.swift
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@MainActor
|
|
6
|
+
final class RunnerMainOwnedState {
|
|
7
|
+
var app: XCUIApplication?
|
|
8
|
+
var bundleId: String?
|
|
9
|
+
var processIdentifier: Int?
|
|
10
|
+
var accessibilityHealth: RunnerAccessibilityHealth = .unknown
|
|
11
|
+
var needsPostSnapshotInteractionDelay = false
|
|
12
|
+
|
|
13
|
+
nonisolated init() {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
func runOnMainActor<T>(_ work: @MainActor () throws -> T) -> Result<T, Error> {
|
|
22
|
+
var result: Result<T, Error>?
|
|
23
|
+
MainActor.assumeIsolated {
|
|
24
|
+
result = Result { try work() }
|
|
25
|
+
}
|
|
26
|
+
return result!
|
|
27
|
+
}
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h
CHANGED
|
@@ -17,13 +17,19 @@ typedef NS_ENUM(NSInteger, RunnerSynthesizedTextEntryStatus) {
|
|
|
17
17
|
|
|
18
18
|
@interface RunnerSynthesizedTextEntry : NSObject
|
|
19
19
|
|
|
20
|
+
// Characters per second the synthesized text-input records are typed at. Declared here, where the
|
|
21
|
+
// typing happens, so the delivery budget that bounds a burst is charged the same pace the app sees.
|
|
22
|
+
// The edit-acknowledge window that pace is sized for is a separate assumption about the app
|
|
23
|
+
// (TextEntryTiming.synthesizedAcknowledgeWindowSeconds), not a value derived from this one.
|
|
24
|
+
+ (NSUInteger)typingSpeedCharactersPerSecond;
|
|
25
|
+
|
|
20
26
|
// Synthesizes keyboard input for the current first responder without resolving an
|
|
21
27
|
// XCUIElement or serializing the application's accessibility tree.
|
|
22
28
|
+ (RunnerSynthesizedTextEntryResult *)synthesizeTextWithApplication:(id)application
|
|
23
29
|
text:(NSString *)text;
|
|
24
30
|
|
|
25
|
-
// Replaces the current first responder's contents
|
|
26
|
-
//
|
|
31
|
+
// Replaces the current first responder's contents with one synthesized Command-A record
|
|
32
|
+
// followed by a text-input record, typed at the bounded pace declared in the implementation.
|
|
27
33
|
+ (RunnerSynthesizedTextEntryResult *)replaceTextWithApplication:(id)application
|
|
28
34
|
text:(NSString *)text;
|
|
29
35
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m
CHANGED
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
static NSString *const RunnerTextSynthesisSurface = @"text";
|
|
7
7
|
|
|
8
|
+
// XCTest's `typingSpeed:` argument is characters per second. At 60 the 11 characters of a `fill`
|
|
9
|
+
// arrived at a fixture field across 131 ms (~13 ms per gap), which is faster than an app that owns
|
|
10
|
+
// its field's value and re-applies it after the edit (a controlled React Native `TextInput`, an
|
|
11
|
+
// async validator) can acknowledge: such a write lands between two characters of the burst and
|
|
12
|
+
// erases what was typed while it was in flight, leaving a value that is stable short of the
|
|
13
|
+
// request. 12 characters/second spaces them ~83 ms apart on average, which reduces that loss but
|
|
14
|
+
// does not remove it: XCTest does not space the characters evenly, and two of them can reach the
|
|
15
|
+
// app a few milliseconds apart. Against a fixture app that acknowledges each edit within 40 ms, 60
|
|
16
|
+
// characters/second left 1 of 11 characters in 20 of 20 bursts, and this pace left 10 or 11. The
|
|
17
|
+
// command refuses a field left short; back-pressure from the field (#2906) is what would prevent
|
|
18
|
+
// it. The app-owned-value lane test pins the average spacing the app sees, and the delivery budget
|
|
19
|
+
// in TextEntryTiming bounds what the pace costs a long text.
|
|
20
|
+
static const NSUInteger RunnerTextEntryTypingSpeedCharactersPerSecond = 12;
|
|
21
|
+
|
|
8
22
|
typedef id (*RunnerTextMsgSendInit)(id, SEL, NSString *);
|
|
9
23
|
typedef id (*RunnerTextMsgSendInitPath)(id, SEL);
|
|
10
24
|
typedef void (*RunnerTextMsgSendType)(id, SEL, NSString *, NSTimeInterval, NSUInteger, BOOL);
|
|
@@ -51,6 +65,10 @@ static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
|
|
|
51
65
|
|
|
52
66
|
@implementation RunnerSynthesizedTextEntry
|
|
53
67
|
|
|
68
|
+
+ (NSUInteger)typingSpeedCharactersPerSecond {
|
|
69
|
+
return RunnerTextEntryTypingSpeedCharactersPerSecond;
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
+ (RunnerSynthesizedTextEntryResult *)synthesizeTextWithApplication:(id)application
|
|
55
73
|
text:(NSString *)text {
|
|
56
74
|
return RunnerSynthesizeTextWithMode(application, text, NO);
|
|
@@ -128,7 +146,14 @@ static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
|
|
|
128
146
|
);
|
|
129
147
|
}
|
|
130
148
|
((RunnerMsgSendSetInteger)objc_msgSend)(record, bridge.core.setTargetProcessIDSelector, targetProcessID);
|
|
131
|
-
((RunnerTextMsgSendType)objc_msgSend)(
|
|
149
|
+
((RunnerTextMsgSendType)objc_msgSend)(
|
|
150
|
+
path,
|
|
151
|
+
bridge.typeTextSelector,
|
|
152
|
+
text,
|
|
153
|
+
0.0,
|
|
154
|
+
RunnerTextEntryTypingSpeedCharactersPerSecond,
|
|
155
|
+
YES
|
|
156
|
+
);
|
|
132
157
|
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.core.addPathSelector, path);
|
|
133
158
|
|
|
134
159
|
NSError *error = nil;
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift
CHANGED
|
@@ -21,6 +21,7 @@ extension RunnerTests {
|
|
|
21
21
|
return max(0.001, timeoutMs / 1000)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
@MainActor
|
|
24
25
|
func resolveAlert(app activeApp: XCUIApplication, deadline: Date) -> RunnerAlert? {
|
|
25
26
|
|
|
26
27
|
|
|
@@ -50,6 +51,7 @@ extension RunnerTests {
|
|
|
50
51
|
return nil
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
@MainActor
|
|
53
55
|
func handleAlert(_ alert: RunnerAlert, action: String, deadline: Date) -> Response {
|
|
54
56
|
if action == "accept" || action == "dismiss" {
|
|
55
57
|
guard let button = chooseAlertButton(alert.buttons, action: action) else {
|
|
@@ -69,6 +71,14 @@ extension RunnerTests {
|
|
|
69
71
|
return alertVerificationResponse(.timedOut, action: action, activated: false)
|
|
70
72
|
}
|
|
71
73
|
let buttonFrame = button.frame
|
|
74
|
+
guard Date() < deadline else {
|
|
75
|
+
return alertVerificationResponse(.timedOut, action: action, activated: false)
|
|
76
|
+
}
|
|
77
|
+
#if !os(tvOS)
|
|
78
|
+
guard !buttonFrame.isEmpty else {
|
|
79
|
+
return alertVerificationResponse(.unconfirmed, action: action, activated: false)
|
|
80
|
+
}
|
|
81
|
+
#endif
|
|
72
82
|
NSLog(
|
|
73
83
|
"AGENT_DEVICE_RUNNER_ALERT_ACTIVATION action=%@ label=%@ frame=(%.1f,%.1f,%.1f,%.1f) point=(%.1f,%.1f)",
|
|
74
84
|
action,
|
|
@@ -82,11 +92,8 @@ extension RunnerTests {
|
|
|
82
92
|
|
|
83
93
|
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
withBoundedInteractionIdleTimeoutIfSupported(alert.ownerApp, waits: .preEventSkipped) {
|
|
88
|
-
outcome = activateElement(app: alert.ownerApp, element: button, action: "alert \(action)")
|
|
89
|
-
}
|
|
95
|
+
guard let outcome = activateAlertButton(alert, button: button, action: action, frame: buttonFrame, deadline: deadline) else {
|
|
96
|
+
return alertVerificationResponse(.timedOut, action: action, activated: false)
|
|
90
97
|
}
|
|
91
98
|
if let response = unsupportedResponse(for: outcome) {
|
|
92
99
|
return response
|
|
@@ -116,6 +123,32 @@ extension RunnerTests {
|
|
|
116
123
|
)
|
|
117
124
|
}
|
|
118
125
|
|
|
126
|
+
@MainActor
|
|
127
|
+
func activateAlertButton(
|
|
128
|
+
_ alert: RunnerAlert,
|
|
129
|
+
button: XCUIElement,
|
|
130
|
+
action: String,
|
|
131
|
+
frame: CGRect,
|
|
132
|
+
deadline: Date
|
|
133
|
+
) -> RunnerInteractionOutcome? {
|
|
134
|
+
var outcome: RunnerInteractionOutcome?
|
|
135
|
+
withUIInterruptionHandlingDisabledIfSupported(alert.ownerApp) {
|
|
136
|
+
withBoundedInteractionIdleTimeoutIfSupported(alert.ownerApp, waits: .preEventSkipped) {
|
|
137
|
+
guard Date() < deadline else { return }
|
|
138
|
+
#if !os(tvOS)
|
|
139
|
+
guard !frame.isEmpty else { return }
|
|
140
|
+
#endif
|
|
141
|
+
outcome = activateElement(
|
|
142
|
+
app: alert.ownerApp,
|
|
143
|
+
element: button,
|
|
144
|
+
action: "alert \(action)",
|
|
145
|
+
resolvedFrame: frame
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return outcome
|
|
150
|
+
}
|
|
151
|
+
|
|
119
152
|
|
|
120
153
|
|
|
121
154
|
|
|
@@ -266,6 +299,7 @@ extension RunnerTests {
|
|
|
266
299
|
|
|
267
300
|
|
|
268
301
|
|
|
302
|
+
@MainActor
|
|
269
303
|
private func waitUntilAlertButtonHittable(_ button: XCUIElement, deadline: Date) -> Bool {
|
|
270
304
|
while Date() < deadline {
|
|
271
305
|
if probeAlertButtonHittable(button, deadline: deadline) {
|
|
@@ -276,6 +310,7 @@ extension RunnerTests {
|
|
|
276
310
|
return false
|
|
277
311
|
}
|
|
278
312
|
|
|
313
|
+
@MainActor
|
|
279
314
|
private func probeAlertButtonHittable(_ button: XCUIElement, deadline: Date) -> Bool {
|
|
280
315
|
|
|
281
316
|
|