agent-device 0.21.13 → 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.13.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.13.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.13.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 +110 -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+AXSnapshotFallback.swift +12 -19
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +59 -20
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +2 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +179 -91
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +21 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +9 -13
- 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 +20 -21
- 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 +12 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +22 -42
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +15 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +73 -31
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +20 -11
- 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 +51 -19
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +5 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +78 -10
- 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 +9 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +12 -11
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +16 -19
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +24 -9
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +66 -10
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +12 -10
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +1 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +27 -5
- 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-help.js +2 -2
- package/dist/src/cli.js +4 -4
- 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 -0
- 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 +2 -2
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-host.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 +1 -1
- 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 +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +59 -12
- 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 +1 -1
- 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/simctl.js +1 -1
- package/dist/src/simulator-state.js +1 -1
- 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-binding.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 +1 -1
- 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-facade.js +1 -1
- package/dist/src/tool-provider.js +2 -2
- 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.13.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.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-process.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,39 @@ 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
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-crowded-screen"]) {
|
|
384
|
+
for (NSUInteger row = 0; row < 500; row++) {
|
|
385
|
+
UILabel *rowLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 60 + (row % 30) * 24, 400, 16)];
|
|
386
|
+
rowLabel.text = [NSString stringWithFormat:@"Crowded row %lu", (unsigned long)row];
|
|
387
|
+
rowLabel.accessibilityIdentifier = [NSString stringWithFormat:@"agent-device-crowded-row-%lu", (unsigned long)row];
|
|
388
|
+
[self.view addSubview:rowLabel];
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
BOOL markedButton = [NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-dismiss-popup"];
|
|
393
|
+
if (markedButton || [NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-dismiss-popup-window"]) {
|
|
394
|
+
UIButton *dismissRegion = [UIButton buttonWithType:UIButtonTypeSystem];
|
|
395
|
+
dismissRegion.accessibilityIdentifier = markedButton ? @" Dismiss Popup " : @"agent-device-close-popover";
|
|
396
|
+
[dismissRegion setTitle:@"Close popover" forState:UIControlStateNormal];
|
|
397
|
+
dismissRegion.frame = CGRectMake(40, 40, 200, 44);
|
|
398
|
+
[self.view addSubview:dismissRegion];
|
|
296
399
|
}
|
|
297
400
|
|
|
298
401
|
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-selector-read-regression"]) {
|
|
@@ -338,6 +441,11 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
|
|
|
338
441
|
|
|
339
442
|
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
|
|
340
443
|
self.window.rootViewController = [[AgentDeviceRunnerViewController alloc] init];
|
|
444
|
+
#if TARGET_OS_IOS
|
|
445
|
+
if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-dismiss-popup-window"]) {
|
|
446
|
+
self.window.accessibilityIdentifier = @"Dismiss popup";
|
|
447
|
+
}
|
|
448
|
+
#endif
|
|
341
449
|
[self.window makeKeyAndVisible];
|
|
342
450
|
}
|
|
343
451
|
|
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;
|
|
@@ -217,12 +217,11 @@ extension RunnerTests {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
let rootFrame = privateAXRect(root["frame"])
|
|
220
|
-
let
|
|
220
|
+
let viewport = privateAXSnapshotViewport(
|
|
221
221
|
app: app,
|
|
222
222
|
bundleId: target.bundleId,
|
|
223
223
|
rootFrame: rootFrame
|
|
224
224
|
)
|
|
225
|
-
let viewport = geometry.viewport
|
|
226
225
|
let nodes = privateAXAcquisition(
|
|
227
226
|
rawRoot: root,
|
|
228
227
|
hint: hint
|
|
@@ -259,8 +258,7 @@ extension RunnerTests {
|
|
|
259
258
|
customActions: Self.privateAXCustomActionCoverage(
|
|
260
259
|
response[RunnerAXSnapshotCustomActionsKey]
|
|
261
260
|
),
|
|
262
|
-
viewport: viewport
|
|
263
|
-
interfaceOrientation: geometry.interfaceOrientation
|
|
261
|
+
viewport: viewport
|
|
264
262
|
)
|
|
265
263
|
#else
|
|
266
264
|
return nil
|
|
@@ -277,35 +275,30 @@ extension RunnerTests {
|
|
|
277
275
|
|
|
278
276
|
|
|
279
277
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
private func privateAXSnapshotGeometry(
|
|
278
|
+
private func privateAXSnapshotViewport(
|
|
283
279
|
app: XCUIApplication,
|
|
284
280
|
bundleId: String?,
|
|
285
281
|
rootFrame: CGRect
|
|
286
|
-
) ->
|
|
287
|
-
let fallback =
|
|
282
|
+
) -> SnapshotViewport {
|
|
283
|
+
let fallback = SnapshotViewport.derived(box: rootFrame)
|
|
288
284
|
guard shouldReadPrivateAXViewportViaXCTest(bundleId: bundleId) else {
|
|
289
|
-
return
|
|
285
|
+
return fallback
|
|
290
286
|
}
|
|
291
287
|
do {
|
|
292
|
-
let
|
|
288
|
+
let reported = try runMainThreadWork(
|
|
293
289
|
"private_ax_viewport",
|
|
294
290
|
timeout: 1,
|
|
295
291
|
timeoutError: snapshotMainThreadTimeoutError("reading private AX viewport")
|
|
296
292
|
) {
|
|
297
|
-
(
|
|
298
|
-
viewport: self.safeSnapshotViewport(app: app),
|
|
299
|
-
interfaceOrientation: self.capturedInterfaceOrientation(app: app)
|
|
300
|
-
)
|
|
293
|
+
self.safeSnapshotViewport(app: app, readingOrientation: true)
|
|
301
294
|
}
|
|
302
|
-
if
|
|
303
|
-
return
|
|
295
|
+
if case .missing = reported {
|
|
296
|
+
return fallback
|
|
304
297
|
}
|
|
305
|
-
return
|
|
298
|
+
return reported
|
|
306
299
|
} catch {
|
|
307
300
|
NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_VIEWPORT_FALLBACK=%@", String(describing: error))
|
|
308
|
-
return
|
|
301
|
+
return fallback
|
|
309
302
|
}
|
|
310
303
|
}
|
|
311
304
|
|
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
|
|
|
@@ -161,22 +194,26 @@ extension RunnerTests {
|
|
|
161
194
|
elements.first { isVisibleElement($0) }
|
|
162
195
|
}
|
|
163
196
|
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
164
201
|
private func firstDismissPopupWindow(in app: XCUIApplication) -> XCUIElement? {
|
|
165
|
-
safeElementsQuery {
|
|
166
|
-
app.windows.allElementsBoundByIndex
|
|
167
|
-
}
|
|
168
|
-
if !isVisibleElement(window) { return false }
|
|
169
|
-
if isDismissPopupMarker(window.label) || isDismissPopupMarker(window.identifier) {
|
|
170
|
-
return true
|
|
171
|
-
}
|
|
172
|
-
return safeElementsQuery {
|
|
173
|
-
window.descendants(matching: .any).allElementsBoundByIndex
|
|
174
|
-
}.contains { descendant in
|
|
175
|
-
isDismissPopupMarker(descendant.label) || isDismissPopupMarker(descendant.identifier)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
202
|
+
firstExistingElement(in: safeElementsQuery {
|
|
203
|
+
app.windows.containing(Self.dismissPopupMarker).allElementsBoundByIndex
|
|
204
|
+
})
|
|
178
205
|
}
|
|
179
206
|
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
private static let dismissPopupMarkerPattern = #"\s*dismiss popup\s*"#
|
|
210
|
+
private static let dismissPopupMarker = NSPredicate(
|
|
211
|
+
format: "label MATCHES[c] %@ OR identifier MATCHES[c] %@",
|
|
212
|
+
dismissPopupMarkerPattern,
|
|
213
|
+
dismissPopupMarkerPattern
|
|
214
|
+
)
|
|
215
|
+
private static let dismissPopupMarkerText = NSPredicate(format: "SELF MATCHES[c] %@", dismissPopupMarkerPattern)
|
|
216
|
+
|
|
180
217
|
private func chooseAlertButton(_ buttons: [XCUIElement], action: String) -> XCUIElement? {
|
|
181
218
|
if action == "accept" {
|
|
182
219
|
if let accept = buttons.first(where: { isAcceptButton($0.label) }) {
|
|
@@ -262,6 +299,7 @@ extension RunnerTests {
|
|
|
262
299
|
|
|
263
300
|
|
|
264
301
|
|
|
302
|
+
@MainActor
|
|
265
303
|
private func waitUntilAlertButtonHittable(_ button: XCUIElement, deadline: Date) -> Bool {
|
|
266
304
|
while Date() < deadline {
|
|
267
305
|
if probeAlertButtonHittable(button, deadline: deadline) {
|
|
@@ -272,6 +310,7 @@ extension RunnerTests {
|
|
|
272
310
|
return false
|
|
273
311
|
}
|
|
274
312
|
|
|
313
|
+
@MainActor
|
|
275
314
|
private func probeAlertButtonHittable(_ button: XCUIElement, deadline: Date) -> Bool {
|
|
276
315
|
|
|
277
316
|
|
|
@@ -285,7 +324,7 @@ extension RunnerTests {
|
|
|
285
324
|
return hittable
|
|
286
325
|
}
|
|
287
326
|
|
|
288
|
-
|
|
289
|
-
|
|
327
|
+
func isDismissPopupMarker(_ text: String) -> Bool {
|
|
328
|
+
Self.dismissPopupMarkerText.evaluate(with: text)
|
|
290
329
|
}
|
|
291
330
|
}
|
|
@@ -68,9 +68,8 @@ extension RunnerTests {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
private func containsDismissPopupMarker(_ snapshot: XCUIElementSnapshot) -> Bool {
|
|
71
|
-
[snapshot.label, snapshot.identifier].contains {
|
|
72
|
-
|
|
73
|
-
} || snapshot.children.contains { containsDismissPopupMarker($0) }
|
|
71
|
+
[snapshot.label, snapshot.identifier].contains { isDismissPopupMarker($0) } ||
|
|
72
|
+
snapshot.children.contains { containsDismissPopupMarker($0) }
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
private func alertPresentation(_ snapshot: XCUIElementSnapshot) -> RunnerAlertPresentation {
|