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
|
@@ -27,6 +27,7 @@ extension RunnerTests {
|
|
|
27
27
|
)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
@MainActor
|
|
30
31
|
func executeScrollDragGesture(
|
|
31
32
|
activeApp: XCUIApplication,
|
|
32
33
|
x: Double,
|
|
@@ -65,6 +66,7 @@ extension RunnerTests {
|
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
|
|
69
|
+
@MainActor
|
|
68
70
|
func executeDragGesture(
|
|
69
71
|
activeApp: XCUIApplication,
|
|
70
72
|
x: Double,
|
|
@@ -125,6 +127,7 @@ extension RunnerTests {
|
|
|
125
127
|
return gestureResponse(message: message, timing: timing, frame: .drag(dragFrame))
|
|
126
128
|
}
|
|
127
129
|
|
|
130
|
+
@MainActor
|
|
128
131
|
private func executeSynthesizedDragGesture(
|
|
129
132
|
activeApp: XCUIApplication,
|
|
130
133
|
x: Double,
|
|
@@ -149,19 +152,6 @@ extension RunnerTests {
|
|
|
149
152
|
context: context
|
|
150
153
|
)
|
|
151
154
|
else {
|
|
152
|
-
if context?.allowsXCTestCoordinateFallback == true {
|
|
153
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: context, fallbackAttempted: true)
|
|
154
|
-
return executeCoordinateDragFallback(
|
|
155
|
-
activeApp: activeApp,
|
|
156
|
-
x: x,
|
|
157
|
-
y: y,
|
|
158
|
-
x2: x2,
|
|
159
|
-
y2: y2,
|
|
160
|
-
durationMs: durationMs,
|
|
161
|
-
message: message,
|
|
162
|
-
fallback: nil
|
|
163
|
-
)
|
|
164
|
-
}
|
|
165
155
|
logSynthesizedGesturePolicyDecision(kind: policyKind, context: context, fallbackAttempted: false)
|
|
166
156
|
return Response(
|
|
167
157
|
ok: false,
|
|
@@ -179,7 +169,7 @@ extension RunnerTests {
|
|
|
179
169
|
y2: plan.points.y2,
|
|
180
170
|
referenceFrame: plan.referenceFrame
|
|
181
171
|
)
|
|
182
|
-
|
|
172
|
+
switch performSynthesizedGesture(activeApp, kind: policyKind, context: plan.context, synthesize: {
|
|
183
173
|
synthesizedDragAt(
|
|
184
174
|
app: activeApp,
|
|
185
175
|
x: plan.points.x,
|
|
@@ -190,13 +180,10 @@ extension RunnerTests {
|
|
|
190
180
|
profile: profile,
|
|
191
181
|
context: plan.context
|
|
192
182
|
)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: false)
|
|
183
|
+
}) {
|
|
184
|
+
case .performed(let timing):
|
|
196
185
|
return gestureResponse(message: message, timing: timing, frame: .drag(dragFrame))
|
|
197
|
-
|
|
198
|
-
if plan.context.allowsXCTestCoordinateFallback {
|
|
199
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: true)
|
|
186
|
+
case .xctestFallback(let fallbackMessage, let hint):
|
|
200
187
|
return executeCoordinateDragFallback(
|
|
201
188
|
activeApp: activeApp,
|
|
202
189
|
x: plan.points.x,
|
|
@@ -205,16 +192,17 @@ extension RunnerTests {
|
|
|
205
192
|
y2: plan.points.y2,
|
|
206
193
|
durationMs: durationMs,
|
|
207
194
|
message: message,
|
|
208
|
-
fallback:
|
|
195
|
+
fallback: GestureFallback(strategy: "xctest-coordinate-drag", message: fallbackMessage, hint: hint)
|
|
209
196
|
)
|
|
197
|
+
case .refused(_, let refusalMessage, let hint):
|
|
198
|
+
return unsupportedResponse(message: refusalMessage, hint: hint)
|
|
210
199
|
}
|
|
211
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: false)
|
|
212
|
-
return unsupportedResponse(for: outcome)
|
|
213
200
|
#else
|
|
214
201
|
return nil
|
|
215
202
|
#endif
|
|
216
203
|
}
|
|
217
204
|
|
|
205
|
+
@MainActor
|
|
218
206
|
private func executeCoordinateDragFallback(
|
|
219
207
|
activeApp: XCUIApplication,
|
|
220
208
|
x: Double,
|
|
@@ -223,7 +211,7 @@ extension RunnerTests {
|
|
|
223
211
|
y2: Double,
|
|
224
212
|
durationMs: Double,
|
|
225
213
|
message: String,
|
|
226
|
-
fallback: GestureFallback
|
|
214
|
+
fallback: GestureFallback
|
|
227
215
|
) -> Response {
|
|
228
216
|
let dragPoints = keyboardAvoidingDragPoints(app: activeApp, x: x, y: y, x2: x2, y2: y2)
|
|
229
217
|
let dragFrame = resolvedDragVisualizationFrame(
|
|
@@ -19,6 +19,7 @@ extension RunnerTests {
|
|
|
19
19
|
let gestureEndUptimeMs: Double
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
@MainActor
|
|
22
23
|
func executeSequence(command: Command, activeApp: XCUIApplication) -> Response {
|
|
23
24
|
guard let steps = command.steps, !steps.isEmpty else {
|
|
24
25
|
return sequenceInvalidArgs("sequence requires at least one step")
|
|
@@ -136,6 +137,7 @@ extension RunnerTests {
|
|
|
136
137
|
return nil
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
@MainActor
|
|
139
141
|
private func performSequenceStep(
|
|
140
142
|
_ step: SequenceStep,
|
|
141
143
|
activeApp: XCUIApplication,
|
|
@@ -143,51 +145,21 @@ extension RunnerTests {
|
|
|
143
145
|
) -> SequenceStepOutcome {
|
|
144
146
|
let x = step.x ?? 0
|
|
145
147
|
let y = step.y ?? 0
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if step.kind == "tap", step.synthesized == true {
|
|
150
|
-
let policyKind = SynthesizedGesturePolicyKind.synthesizedDrag
|
|
151
|
-
#if os(iOS)
|
|
152
|
-
guard let synthesizedContext else {
|
|
153
|
-
let nowMs = ProcessInfo.processInfo.systemUptime * 1000
|
|
154
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: nil, fallbackAttempted: false)
|
|
155
|
-
return SequenceStepOutcome(
|
|
156
|
-
outcome: .unsupported(
|
|
157
|
-
message: "synthesized coordinate tap could not resolve a finite coordinate frame",
|
|
158
|
-
hint: "Retry after the app is foregrounded, or use a plain screenshot to choose coordinates."
|
|
159
|
-
),
|
|
160
|
-
gestureStartUptimeMs: nowMs,
|
|
161
|
-
gestureEndUptimeMs: nowMs
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
#endif
|
|
165
|
-
let (timing, outcome) = performGesture(activeApp, idleTimeout: false) {
|
|
148
|
+
if let policyKind = synthesizedPolicyKind(forSequenceStep: step) {
|
|
149
|
+
switch performSynthesizedGesture(activeApp, kind: policyKind, context: synthesizedContext, synthesize: {
|
|
166
150
|
synthesizedTapAt(app: activeApp, x: x, y: y, context: synthesizedContext)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
outcome:
|
|
175
|
-
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
176
|
-
gestureEndUptimeMs: timing.gestureEndUptimeMs
|
|
151
|
+
}) {
|
|
152
|
+
case .performed(let timing):
|
|
153
|
+
return finishedSequenceStep(step, timing: timing, outcome: .performed)
|
|
154
|
+
case .refused(let timing, let message, let hint):
|
|
155
|
+
return finishedSequenceStep(
|
|
156
|
+
step,
|
|
157
|
+
timing: timing,
|
|
158
|
+
outcome: .unsupported(message: message, hint: hint)
|
|
177
159
|
)
|
|
160
|
+
case .xctestFallback:
|
|
161
|
+
break
|
|
178
162
|
}
|
|
179
|
-
#if os(iOS)
|
|
180
|
-
guard synthesizedContext.allowsXCTestCoordinateFallback else {
|
|
181
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: synthesizedContext, fallbackAttempted: false)
|
|
182
|
-
return SequenceStepOutcome(
|
|
183
|
-
outcome: outcome,
|
|
184
|
-
gestureStartUptimeMs: timing.gestureStartUptimeMs,
|
|
185
|
-
gestureEndUptimeMs: timing.gestureEndUptimeMs
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
logSynthesizedGesturePolicyDecision(kind: policyKind, context: synthesizedContext, fallbackAttempted: true)
|
|
189
|
-
#endif
|
|
190
|
-
|
|
191
163
|
}
|
|
192
164
|
let (timing, outcome) = performGesture(activeApp) {
|
|
193
165
|
switch step.kind {
|
|
@@ -201,6 +173,14 @@ extension RunnerTests {
|
|
|
201
173
|
return tapAt(app: activeApp, x: x, y: y)
|
|
202
174
|
}
|
|
203
175
|
}
|
|
176
|
+
return finishedSequenceStep(step, timing: timing, outcome: outcome)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private func finishedSequenceStep(
|
|
180
|
+
_ step: SequenceStep,
|
|
181
|
+
timing: (gestureStartUptimeMs: Double, gestureEndUptimeMs: Double),
|
|
182
|
+
outcome: RunnerInteractionOutcome
|
|
183
|
+
) -> SequenceStepOutcome {
|
|
204
184
|
|
|
205
185
|
|
|
206
186
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift
CHANGED
|
@@ -21,9 +21,8 @@ extension RunnerTests {
|
|
|
21
21
|
struct SnapshotTraversalContext {
|
|
22
22
|
let queryRoot: XCUIElement
|
|
23
23
|
let rootSnapshot: XCUIElementSnapshot
|
|
24
|
-
let viewport: CGRect
|
|
25
24
|
|
|
26
|
-
let
|
|
25
|
+
let viewport: SnapshotViewport
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
|
|
@@ -36,6 +35,7 @@ extension RunnerTests {
|
|
|
36
35
|
let label: String
|
|
37
36
|
let identifier: String
|
|
38
37
|
let valueText: String?
|
|
38
|
+
let placeholder: String?
|
|
39
39
|
let focused: Bool
|
|
40
40
|
let selected: Bool
|
|
41
41
|
}
|
|
@@ -176,6 +176,7 @@ extension RunnerTests {
|
|
|
176
176
|
)
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
@MainActor
|
|
179
180
|
func recursiveTreeSnapshotAcquisition(
|
|
180
181
|
context: SnapshotTraversalContext,
|
|
181
182
|
hint: CaptureHint
|
|
@@ -278,8 +279,7 @@ extension RunnerTests {
|
|
|
278
279
|
nodes: nodes,
|
|
279
280
|
truncated: false,
|
|
280
281
|
effectiveDepth: nil,
|
|
281
|
-
viewport: context.viewport
|
|
282
|
-
interfaceOrientation: context.interfaceOrientation
|
|
282
|
+
viewport: context.viewport
|
|
283
283
|
)
|
|
284
284
|
}
|
|
285
285
|
|
|
@@ -329,7 +329,7 @@ extension RunnerTests {
|
|
|
329
329
|
private func boundedBlockingSystemAlertSnapshotBody(
|
|
330
330
|
deadline: Date,
|
|
331
331
|
penaltyTarget: SnapshotProbePenaltyTarget,
|
|
332
|
-
probe: @escaping (Date) -> DataPayload?
|
|
332
|
+
probe: @escaping @MainActor (Date) -> DataPayload?
|
|
333
333
|
) -> DataPayload? {
|
|
334
334
|
#if os(macOS)
|
|
335
335
|
return nil
|
|
@@ -363,7 +363,7 @@ extension RunnerTests {
|
|
|
363
363
|
)
|
|
364
364
|
}
|
|
365
365
|
) {
|
|
366
|
-
penaltyIdentity.captureFromMain(bundleId: self.
|
|
366
|
+
penaltyIdentity.captureFromMain(bundleId: self.mainOwned.bundleId)
|
|
367
367
|
return probe(probeDeadline)
|
|
368
368
|
}
|
|
369
369
|
} catch {
|
|
@@ -435,11 +435,11 @@ extension RunnerTests {
|
|
|
435
435
|
nodes: nodes,
|
|
436
436
|
truncated: false,
|
|
437
437
|
effectiveDepth: nil,
|
|
438
|
-
viewport: context.viewport
|
|
439
|
-
interfaceOrientation: context.interfaceOrientation
|
|
438
|
+
viewport: context.viewport
|
|
440
439
|
)
|
|
441
440
|
}
|
|
442
441
|
|
|
442
|
+
@MainActor
|
|
443
443
|
func querySweepSnapshotAcquisition(
|
|
444
444
|
app: XCUIApplication,
|
|
445
445
|
hint: CaptureHint,
|
|
@@ -455,14 +455,13 @@ extension RunnerTests {
|
|
|
455
455
|
nodes: nodes,
|
|
456
456
|
truncated: false,
|
|
457
457
|
effectiveDepth: nil,
|
|
458
|
-
viewport: .
|
|
459
|
-
interfaceOrientation: RunnerInterfaceOrientation.unknown
|
|
458
|
+
viewport: .missing(reason: .notProvided)
|
|
460
459
|
),
|
|
461
460
|
.completed
|
|
462
461
|
)
|
|
463
462
|
}
|
|
464
463
|
|
|
465
|
-
let viewport = safeSnapshotViewport(app: app)
|
|
464
|
+
let viewport = safeSnapshotViewport(app: app, readingOrientation: false)
|
|
466
465
|
var seen = Set<String>()
|
|
467
466
|
var candidates: [RawAXNode] = []
|
|
468
467
|
let flatElements = flatInteractiveElements(app: app, deadline: deadline)
|
|
@@ -494,9 +493,7 @@ extension RunnerTests {
|
|
|
494
493
|
|
|
495
494
|
|
|
496
495
|
|
|
497
|
-
let rootRect = viewport.
|
|
498
|
-
? interactiveRootFrame(for: candidates)
|
|
499
|
-
: viewport
|
|
496
|
+
let rootRect = viewport.rect ?? interactiveRootFrame(for: candidates)
|
|
500
497
|
nodes[0] = interactiveRootNode(rect: rootRect)
|
|
501
498
|
for candidate in candidates {
|
|
502
499
|
nodes.append(
|
|
@@ -506,6 +503,7 @@ extension RunnerTests {
|
|
|
506
503
|
label: candidate.label,
|
|
507
504
|
identifier: candidate.identifier,
|
|
508
505
|
value: candidate.value,
|
|
506
|
+
placeholder: candidate.placeholder,
|
|
509
507
|
rect: candidate.rect,
|
|
510
508
|
enabled: candidate.enabled,
|
|
511
509
|
focused: candidate.focused,
|
|
@@ -524,8 +522,7 @@ extension RunnerTests {
|
|
|
524
522
|
nodes: nodes,
|
|
525
523
|
truncated: outcome == .deadlineExhausted,
|
|
526
524
|
effectiveDepth: nil,
|
|
527
|
-
viewport: viewport
|
|
528
|
-
interfaceOrientation: RunnerInterfaceOrientation.unknown
|
|
525
|
+
viewport: viewport
|
|
529
526
|
),
|
|
530
527
|
outcome
|
|
531
528
|
)
|
|
@@ -534,7 +531,7 @@ extension RunnerTests {
|
|
|
534
531
|
func snapshotAccessibilityUnavailable(failure: SnapshotCaptureFailure) -> DataPayload {
|
|
535
532
|
NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_AX_UNAVAILABLE=%@", failure.message)
|
|
536
533
|
applyMainOwnedSnapshotState("ax_unavailable_invalidation") {
|
|
537
|
-
self.
|
|
534
|
+
self.mainOwned.accessibilityHealth = .unavailable
|
|
538
535
|
self.invalidateCachedTarget(reason: Self.axSnapshotUnavailableReason)
|
|
539
536
|
}
|
|
540
537
|
|
|
@@ -542,7 +539,7 @@ extension RunnerTests {
|
|
|
542
539
|
return sparseTruncatedSnapshotPayload(
|
|
543
540
|
message: recoveredSnapshotMessage(failure),
|
|
544
541
|
snapshotQuality: SnapshotQuality(
|
|
545
|
-
state:
|
|
542
|
+
state: .sparse,
|
|
546
543
|
backend: SnapshotBackendKind.recursiveTree.rawValue,
|
|
547
544
|
reason: failure.message,
|
|
548
545
|
reasonCode: "ax-rejected",
|
|
@@ -38,27 +38,22 @@ extension RunnerTests {
|
|
|
38
38
|
captureDeadline: Date = .distantFuture,
|
|
39
39
|
treeCaptureSliceBudgetOverride: TimeInterval? = nil
|
|
40
40
|
) throws -> SnapshotTraversalContext? {
|
|
41
|
+
let treeSliceBudget = treeCaptureSliceBudgetOverride ?? treeCaptureSliceBudget
|
|
42
|
+
let slice = min(treeSliceBudget, max(0.5, captureDeadline.timeIntervalSinceNow))
|
|
43
|
+
guard let rootSnapshot = try captureSnapshotRootBounded(app, sliceSeconds: slice) else {
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
|
|
42
48
|
|
|
43
49
|
|
|
44
|
-
let
|
|
50
|
+
let viewport = try runMainThreadWork(
|
|
45
51
|
"snapshot_viewport",
|
|
46
52
|
timeout: min(1.0, max(0.1, captureDeadline.timeIntervalSinceNow)),
|
|
47
|
-
timeoutError: snapshotMainThreadTimeoutError("
|
|
53
|
+
timeoutError: snapshotMainThreadTimeoutError("reading snapshot viewport")
|
|
48
54
|
) {
|
|
49
|
-
(
|
|
50
|
-
viewport: self.safeSnapshotViewport(app: app),
|
|
51
|
-
interfaceOrientation: self.capturedInterfaceOrientation(app: app)
|
|
52
|
-
)
|
|
55
|
+
self.safeSnapshotViewport(app: app, readingOrientation: true)
|
|
53
56
|
}
|
|
54
|
-
let viewport = geometry.viewport
|
|
55
|
-
let interfaceOrientation = geometry.interfaceOrientation
|
|
56
|
-
let treeSliceBudget = treeCaptureSliceBudgetOverride ?? treeCaptureSliceBudget
|
|
57
|
-
let slice = min(treeSliceBudget, max(0.5, captureDeadline.timeIntervalSinceNow))
|
|
58
|
-
guard let rootSnapshot = try captureSnapshotRootBounded(app, sliceSeconds: slice) else {
|
|
59
|
-
return nil
|
|
60
|
-
}
|
|
61
|
-
|
|
62
57
|
|
|
63
58
|
|
|
64
59
|
|
|
@@ -70,7 +65,6 @@ extension RunnerTests {
|
|
|
70
65
|
queryRoot: app,
|
|
71
66
|
rootSnapshot: rootSnapshot,
|
|
72
67
|
viewport: viewport,
|
|
73
|
-
interfaceOrientation: interfaceOrientation,
|
|
74
68
|
keyboardBand: keyboardBand
|
|
75
69
|
)
|
|
76
70
|
}
|
|
@@ -99,7 +93,7 @@ extension RunnerTests {
|
|
|
99
93
|
}
|
|
100
94
|
}
|
|
101
95
|
|
|
102
|
-
private func treeCaptureTimeoutError(sliceSeconds: TimeInterval) -> () -> Error {
|
|
96
|
+
private func treeCaptureTimeoutError(sliceSeconds: TimeInterval) -> @Sendable () -> Error {
|
|
103
97
|
{
|
|
104
98
|
SnapshotCaptureFailure(
|
|
105
99
|
code: Self.xCTestSnapshotTimeoutCode,
|
|
@@ -109,7 +103,7 @@ extension RunnerTests {
|
|
|
109
103
|
}
|
|
110
104
|
}
|
|
111
105
|
|
|
112
|
-
func snapshotMainThreadTimeoutError(_ operation: String) -> () -> Error {
|
|
106
|
+
func snapshotMainThreadTimeoutError(_ operation: String) -> @Sendable () -> Error {
|
|
113
107
|
{
|
|
114
108
|
SnapshotCaptureFailure(
|
|
115
109
|
code: Self.xCTestSnapshotTimeoutCode,
|
|
@@ -140,8 +134,18 @@ extension RunnerTests {
|
|
|
140
134
|
return nil
|
|
141
135
|
}
|
|
142
136
|
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
func safeSnapshotViewport(app: XCUIApplication, readingOrientation: Bool) -> SnapshotViewport {
|
|
141
|
+
safely("SNAPSHOT_VIEWPORT", .missing(reason: .notProvided)) {
|
|
142
|
+
.reported(
|
|
143
|
+
box: snapshotAppFrame(app: app),
|
|
144
|
+
interfaceOrientation: readingOrientation
|
|
145
|
+
? capturedInterfaceOrientation(app: app)
|
|
146
|
+
: RunnerInterfaceOrientation.unknown
|
|
147
|
+
)
|
|
148
|
+
}
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
private func describeSnapshotError(_ error: Error) -> String {
|
|
@@ -185,6 +189,7 @@ extension RunnerTests {
|
|
|
185
189
|
label: label,
|
|
186
190
|
identifier: identifier,
|
|
187
191
|
valueText: valueText,
|
|
192
|
+
placeholder: placeholderText(snapshot.placeholderValue),
|
|
188
193
|
focused: snapshotHasFocus(snapshot),
|
|
189
194
|
selected: snapshotIsSelected(snapshot)
|
|
190
195
|
)
|
|
@@ -205,6 +210,7 @@ extension RunnerTests {
|
|
|
205
210
|
label: evaluation.label.isEmpty ? nil : evaluation.label,
|
|
206
211
|
identifier: evaluation.identifier.isEmpty ? nil : evaluation.identifier,
|
|
207
212
|
value: evaluation.valueText,
|
|
213
|
+
placeholder: evaluation.placeholder,
|
|
208
214
|
rect: SnapshotRect(snapshot.frame),
|
|
209
215
|
enabled: snapshot.isEnabled,
|
|
210
216
|
focused: evaluation.focused ? true : nil,
|
|
@@ -231,16 +237,32 @@ extension RunnerTests {
|
|
|
231
237
|
return text.isEmpty ? nil : text
|
|
232
238
|
}
|
|
233
239
|
|
|
234
|
-
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
func placeholderText(_ placeholderValue: String?) -> String? {
|
|
244
|
+
let text = placeholderValue?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
245
|
+
return text.isEmpty ? nil : text
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
static let placeholderElementTypes: Set<XCUIElement.ElementType> = [
|
|
252
|
+
.textField, .secureTextField, .searchField, .textView,
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
func elementPlaceholderText(_ element: XCUIElement, type: XCUIElement.ElementType) -> String? {
|
|
256
|
+
guard Self.placeholderElementTypes.contains(type) else { return nil }
|
|
257
|
+
return placeholderText(element.placeholderValue)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private func snapshotAppFrame(app: XCUIApplication) -> CGRect {
|
|
235
261
|
#if os(iOS)
|
|
236
|
-
|
|
262
|
+
return onScreenWindowFrame(app: app)
|
|
237
263
|
#else
|
|
238
|
-
|
|
264
|
+
return app.frame
|
|
239
265
|
#endif
|
|
240
|
-
if !appFrame.isNull && !appFrame.isEmpty {
|
|
241
|
-
return appFrame
|
|
242
|
-
}
|
|
243
|
-
return .infinite
|
|
244
266
|
}
|
|
245
267
|
|
|
246
268
|
static func snapshotTraversalIdentity(
|
|
@@ -341,6 +363,7 @@ extension RunnerTests {
|
|
|
341
363
|
label: node.label,
|
|
342
364
|
identifier: node.identifier,
|
|
343
365
|
value: node.value,
|
|
366
|
+
placeholder: node.placeholder,
|
|
344
367
|
rect: node.rect,
|
|
345
368
|
enabled: node.enabled,
|
|
346
369
|
focused: node.focused,
|
|
@@ -376,7 +399,8 @@ extension RunnerTests {
|
|
|
376
399
|
let label = element.label.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
377
400
|
let identifier = element.identifier.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
378
401
|
let valueText = snapshotValueText(element)
|
|
379
|
-
let
|
|
402
|
+
let placeholder = elementPlaceholderText(element, type: elementType)
|
|
403
|
+
let hasContent = !label.isEmpty || !identifier.isEmpty || valueText != nil || placeholder != nil
|
|
380
404
|
if !hasContent { return }
|
|
381
405
|
if sameSemanticElement(
|
|
382
406
|
containerSnapshot: containerSnapshot,
|
|
@@ -395,6 +419,7 @@ extension RunnerTests {
|
|
|
395
419
|
label: label.isEmpty ? nil : label,
|
|
396
420
|
identifier: identifier.isEmpty ? nil : identifier,
|
|
397
421
|
value: valueText,
|
|
422
|
+
placeholder: placeholder,
|
|
398
423
|
rect: SnapshotRect(frame),
|
|
399
424
|
enabled: element.isEnabled,
|
|
400
425
|
focused: elementHasFocus(element) ? true : nil,
|
|
@@ -417,13 +442,27 @@ extension RunnerTests {
|
|
|
417
442
|
}
|
|
418
443
|
|
|
419
444
|
private func snapshotHasFocus(_ snapshot: XCUIElementSnapshot) -> Bool {
|
|
420
|
-
|
|
445
|
+
return focusBool(snapshot as! NSObject)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
func focusBool(_ object: NSObject) -> Bool {
|
|
455
|
+
return kvcBool(object, forKey: "hasKeyboardFocus") || kvcBool(object, forKey: "hasFocus")
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
private func kvcBool(_ object: NSObject, forKey key: String) -> Bool {
|
|
459
|
+
var result = false
|
|
421
460
|
_ = RunnerObjCExceptionCatcher.catchException({
|
|
422
|
-
if let value =
|
|
423
|
-
|
|
461
|
+
if let value = object.value(forKey: key) as? Bool {
|
|
462
|
+
result = value
|
|
424
463
|
}
|
|
425
464
|
})
|
|
426
|
-
return
|
|
465
|
+
return result
|
|
427
466
|
}
|
|
428
467
|
|
|
429
468
|
private func snapshotIsSelected(_ snapshot: XCUIElementSnapshot) -> Bool {
|
|
@@ -461,6 +500,7 @@ extension RunnerTests {
|
|
|
461
500
|
return containerLabel == label && containerIdentifier == identifier
|
|
462
501
|
}
|
|
463
502
|
|
|
503
|
+
@MainActor
|
|
464
504
|
func flatInteractiveElements(
|
|
465
505
|
app: XCUIApplication,
|
|
466
506
|
deadline: Date
|
|
@@ -519,6 +559,7 @@ extension RunnerTests {
|
|
|
519
559
|
return (elements, .completed)
|
|
520
560
|
}
|
|
521
561
|
|
|
562
|
+
@MainActor
|
|
522
563
|
func snapshotElementsQuery(
|
|
523
564
|
_ fetch: () -> [XCUIElement]
|
|
524
565
|
) -> (elements: [XCUIElement], axUnavailable: Bool) {
|
|
@@ -558,6 +599,7 @@ extension RunnerTests {
|
|
|
558
599
|
label: label.isEmpty ? nil : label,
|
|
559
600
|
identifier: identifier.isEmpty ? nil : identifier,
|
|
560
601
|
value: valueText,
|
|
602
|
+
placeholder: elementPlaceholderText(element, type: elementType),
|
|
561
603
|
rect: SnapshotRect(frame),
|
|
562
604
|
enabled: enabled,
|
|
563
605
|
focused: elementHasFocus(element) ? true : nil,
|
|
@@ -9,10 +9,20 @@ import AgentDeviceSnapshotPresentation
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
struct SnapshotQuality: Codable {
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
enum SnapshotQualityState: String, Codable, CaseIterable {
|
|
15
|
+
|
|
16
|
+
case healthy
|
|
17
|
+
|
|
18
|
+
case recovered
|
|
19
|
+
|
|
20
|
+
case sparse
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
struct SnapshotQuality: Codable {
|
|
25
|
+
let state: SnapshotQualityState
|
|
16
26
|
|
|
17
27
|
let backend: String
|
|
18
28
|
|
|
@@ -391,7 +401,7 @@ extension RunnerTests {
|
|
|
391
401
|
return stampedSnapshotPayload(
|
|
392
402
|
capture,
|
|
393
403
|
backend: kind,
|
|
394
|
-
state: recovered ?
|
|
404
|
+
state: recovered ? .recovered : .healthy,
|
|
395
405
|
reason: recovered || firstFailure?.code == "requested-backend" ? firstFailure : nil
|
|
396
406
|
)
|
|
397
407
|
}
|
|
@@ -416,11 +426,11 @@ extension RunnerTests {
|
|
|
416
426
|
}
|
|
417
427
|
|
|
418
428
|
let fallbackPayload =
|
|
419
|
-
best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state:
|
|
429
|
+
best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state: .sparse, reason: firstFailure) }
|
|
420
430
|
?? stampedSnapshotPayload(
|
|
421
431
|
SnapshotBackendCapture(payload: sparseTruncatedSnapshotPayload(), effectiveDepth: nil),
|
|
422
432
|
backend: effectivePlan.last ?? plan.last ?? .recursiveTree,
|
|
423
|
-
state:
|
|
433
|
+
state: .sparse,
|
|
424
434
|
reason: firstFailure
|
|
425
435
|
)
|
|
426
436
|
return fallbackPayload
|
|
@@ -513,8 +523,7 @@ extension RunnerTests {
|
|
|
513
523
|
let normalizedAcquisition = acquisition.replacingNodes(
|
|
514
524
|
SnapshotGeometrySpace.normalized(
|
|
515
525
|
nodes: acquisition.nodes,
|
|
516
|
-
viewport: acquisition.viewport
|
|
517
|
-
interfaceOrientation: acquisition.interfaceOrientation
|
|
526
|
+
viewport: acquisition.viewport
|
|
518
527
|
)
|
|
519
528
|
)
|
|
520
529
|
|
|
@@ -641,7 +650,7 @@ extension RunnerTests {
|
|
|
641
650
|
guard Self.structuralOnlyNodeTypes.contains(node.type) else { return false }
|
|
642
651
|
guard !isRootContainer else { return true }
|
|
643
652
|
|
|
644
|
-
let isFullScreenContainer =
|
|
653
|
+
let isFullScreenContainer = node.hittable != true && rootRects.contains { rootRect in
|
|
645
654
|
rootRect.x == node.rect.x && rootRect.y == node.rect.y
|
|
646
655
|
&& rootRect.width == node.rect.width && rootRect.height == node.rect.height
|
|
647
656
|
}
|
|
@@ -680,12 +689,12 @@ extension RunnerTests {
|
|
|
680
689
|
func stampedSnapshotPayload(
|
|
681
690
|
_ capture: SnapshotBackendCapture,
|
|
682
691
|
backend: SnapshotBackendKind,
|
|
683
|
-
state:
|
|
692
|
+
state: SnapshotQualityState,
|
|
684
693
|
reason: (reason: String, code: String)?
|
|
685
694
|
) -> DataPayload {
|
|
686
695
|
let health: RunnerAccessibilityHealth = reason?.code == "ax-rejected" ? .unavailable : .healthy
|
|
687
696
|
applyMainOwnedSnapshotState("accessibility_health") {
|
|
688
|
-
self.
|
|
697
|
+
self.mainOwned.accessibilityHealth = health
|
|
689
698
|
}
|
|
690
699
|
let payload = capture.payload
|
|
691
700
|
let quality = SnapshotQuality(
|
|
@@ -705,7 +714,7 @@ extension RunnerTests {
|
|
|
705
714
|
|
|
706
715
|
|
|
707
716
|
|
|
708
|
-
truncated: payload.truncated == true || state ==
|
|
717
|
+
truncated: payload.truncated == true || state == .sparse || capture.effectiveDepth != nil,
|
|
709
718
|
qualityPayload: capture.qualityPayload.flatMap { quality in
|
|
710
719
|
guard let nodes = quality.nodes else { return nil }
|
|
711
720
|
return SnapshotQualityPayload(nodes: nodes, truncated: quality.truncated == true)
|
|
@@ -8,7 +8,6 @@ import XCTest
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
struct SnapshotCaptureTarget {
|
|
13
12
|
let app: XCUIApplication
|
|
14
13
|
let bundleId: String?
|
|
@@ -67,32 +66,35 @@ final class SnapshotProbePenaltyIdentity {
|
|
|
67
66
|
|
|
68
67
|
extension RunnerTests {
|
|
69
68
|
|
|
69
|
+
@MainActor
|
|
70
70
|
func takeSnapshotCaptureTarget(app: XCUIApplication) -> SnapshotCaptureTarget {
|
|
71
71
|
SnapshotCaptureTarget(
|
|
72
72
|
app: app,
|
|
73
|
-
bundleId:
|
|
74
|
-
processIdentifier:
|
|
73
|
+
bundleId: mainOwned.bundleId,
|
|
74
|
+
processIdentifier: mainOwned.processIdentifier
|
|
75
75
|
)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
func applyMainOwnedSnapshotState(_ operation: String, _ write: @escaping () -> Void) {
|
|
81
|
+
func applyMainOwnedSnapshotState(_ operation: String, _ write: @escaping @MainActor () -> Void) {
|
|
82
82
|
if Thread.isMainThread {
|
|
83
|
-
write
|
|
83
|
+
_ = runOnMainActor(write)
|
|
84
84
|
return
|
|
85
85
|
}
|
|
86
86
|
guard !hasAbandonedMainThreadWork() else {
|
|
87
87
|
NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_STATE_DEFERRED_XCTEST_OCCUPIED operation=%@", operation)
|
|
88
|
-
DispatchQueue.main.async
|
|
88
|
+
DispatchQueue.main.async {
|
|
89
|
+
_ = runOnMainActor(write)
|
|
90
|
+
}
|
|
89
91
|
return
|
|
90
92
|
}
|
|
91
93
|
do {
|
|
92
94
|
try runMainThreadWork(
|
|
93
95
|
operation,
|
|
94
96
|
timeout: 1,
|
|
95
|
-
timeoutError: mainThreadExecutionTimeoutError,
|
|
97
|
+
timeoutError: Self.mainThreadExecutionTimeoutError,
|
|
96
98
|
write
|
|
97
99
|
)
|
|
98
100
|
} catch {
|