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
|
@@ -11,8 +11,8 @@ extension RunnerTests {
|
|
|
11
11
|
private func executeSnapshotDispatchedOnce(command: Command) throws -> Response {
|
|
12
12
|
let preparation: SnapshotCommandPreparation = try runMainThreadWork(
|
|
13
13
|
"command_preparation",
|
|
14
|
-
timeout: mainThreadExecutionTimeout,
|
|
15
|
-
timeoutError: mainThreadExecutionTimeoutError
|
|
14
|
+
timeout: Self.mainThreadExecutionTimeout,
|
|
15
|
+
timeoutError: Self.mainThreadExecutionTimeoutError
|
|
16
16
|
) { () -> SnapshotCommandPreparation in
|
|
17
17
|
switch try self.prepareActiveCommandContextSafely(command: command, routeToSpringboard: false) {
|
|
18
18
|
case .response(let response):
|
|
@@ -36,6 +36,7 @@ extension RunnerTests {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
@MainActor
|
|
39
40
|
private func prepareActiveCommandContextSafely(
|
|
40
41
|
command: Command,
|
|
41
42
|
routeToSpringboard: Bool
|
|
@@ -125,9 +126,9 @@ extension RunnerTests {
|
|
|
125
126
|
try runMainThreadWork(
|
|
126
127
|
"post_snapshot_delay_mark",
|
|
127
128
|
timeout: 1,
|
|
128
|
-
timeoutError: mainThreadExecutionTimeoutError
|
|
129
|
+
timeoutError: Self.mainThreadExecutionTimeoutError
|
|
129
130
|
) {
|
|
130
|
-
self.needsPostSnapshotInteractionDelay = true
|
|
131
|
+
self.mainOwned.needsPostSnapshotInteractionDelay = true
|
|
131
132
|
}
|
|
132
133
|
} catch {
|
|
133
134
|
NSLog("AGENT_DEVICE_RUNNER_POST_SNAPSHOT_DELAY_MARK_FAILED=%@", String(describing: error))
|
|
@@ -24,11 +24,11 @@ enum SnapshotCapturePhase: Equatable {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
struct SnapshotPhaseTimer {
|
|
27
|
-
private let now: () -> Date
|
|
27
|
+
private let now: @Sendable () -> Date
|
|
28
28
|
private var acquisitionSeconds: TimeInterval = 0
|
|
29
29
|
private var presentationSeconds: TimeInterval = 0
|
|
30
30
|
|
|
31
|
-
init(now: @escaping () -> Date = { Date() }) {
|
|
31
|
+
init(now: @escaping @Sendable () -> Date = { Date() }) {
|
|
32
32
|
self.now = now
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -14,15 +14,12 @@ enum RunnerAccessibilityHealth: String, Equatable {
|
|
|
14
14
|
|
|
15
15
|
enum SynthesizedKeyboardPolicy: String, Equatable, Hashable {
|
|
16
16
|
case never
|
|
17
|
-
case whenAccessibilityHealthy
|
|
18
17
|
case requiredWhenAvailable
|
|
19
18
|
|
|
20
19
|
func allowsProbe(accessibilityHealth: RunnerAccessibilityHealth) -> Bool {
|
|
21
20
|
switch self {
|
|
22
21
|
case .never:
|
|
23
22
|
return false
|
|
24
|
-
case .whenAccessibilityHealthy:
|
|
25
|
-
return accessibilityHealth == .healthy
|
|
26
23
|
case .requiredWhenAvailable:
|
|
27
24
|
return accessibilityHealth != .unavailable
|
|
28
25
|
}
|
|
@@ -63,7 +60,6 @@ struct SynthesizedCoordinateContext {
|
|
|
63
60
|
|
|
64
61
|
let resolvedWindow: XCUIElement
|
|
65
62
|
let keyboardPolicy: SynthesizedKeyboardPolicy
|
|
66
|
-
let fallbackPolicy: SynthesizedFallbackPolicy
|
|
67
63
|
let accessibilityHealth: RunnerAccessibilityHealth
|
|
68
64
|
|
|
69
65
|
func withReferenceFrame(_ frame: CGRect) -> SynthesizedCoordinateContext {
|
|
@@ -71,15 +67,10 @@ struct SynthesizedCoordinateContext {
|
|
|
71
67
|
referenceFrame: frame,
|
|
72
68
|
resolvedWindow: resolvedWindow,
|
|
73
69
|
keyboardPolicy: keyboardPolicy,
|
|
74
|
-
fallbackPolicy: fallbackPolicy,
|
|
75
70
|
accessibilityHealth: accessibilityHealth
|
|
76
71
|
)
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
var allowsXCTestCoordinateFallback: Bool {
|
|
80
|
-
fallbackPolicy.allowsXCTestCoordinateFallback(accessibilityHealth: accessibilityHealth)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
74
|
var allowsKeyboardProbe: Bool {
|
|
84
75
|
keyboardPolicy.allowsProbe(accessibilityHealth: accessibilityHealth)
|
|
85
76
|
}
|
|
@@ -115,24 +106,64 @@ func shouldProbeCoordinateTapTextInput(xCTestChannelPenalized: Bool) -> Bool {
|
|
|
115
106
|
!xCTestChannelPenalized
|
|
116
107
|
}
|
|
117
108
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
|
|
110
|
+
func synthesizedPolicyKind(forSequenceStep step: SequenceStep) -> SynthesizedGesturePolicyKind? {
|
|
111
|
+
step.synthesized == true && step.kind == "tap" ? .coordinateTap : nil
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
enum SynthesizedGestureAttempt {
|
|
116
|
+
case performed(timing: (gestureStartUptimeMs: Double, gestureEndUptimeMs: Double))
|
|
117
|
+
|
|
118
|
+
case xctestFallback(message: String, hint: String?)
|
|
119
|
+
|
|
120
|
+
case refused(
|
|
121
|
+
timing: (gestureStartUptimeMs: Double, gestureEndUptimeMs: Double),
|
|
122
|
+
message: String,
|
|
123
|
+
hint: String?
|
|
124
|
+
)
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
extension RunnerTests {
|
|
128
|
+
@MainActor
|
|
125
129
|
func synthesizedSequenceCoordinateContext(
|
|
126
130
|
steps: [SequenceStep],
|
|
127
131
|
app: XCUIApplication
|
|
128
132
|
) -> SynthesizedCoordinateContext? {
|
|
129
|
-
guard
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
guard let kind = steps.lazy.compactMap(synthesizedPolicyKind(forSequenceStep:)).first else {
|
|
134
|
+
return nil
|
|
135
|
+
}
|
|
136
|
+
return synthesizedCoordinateContext(app: app, policy: synthesizedGesturePolicy(kind))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@MainActor
|
|
142
|
+
func performSynthesizedGesture(
|
|
143
|
+
_ app: XCUIApplication,
|
|
144
|
+
kind: SynthesizedGesturePolicyKind,
|
|
145
|
+
context: SynthesizedCoordinateContext?,
|
|
146
|
+
synthesize: () -> RunnerInteractionOutcome
|
|
147
|
+
) -> SynthesizedGestureAttempt {
|
|
148
|
+
let (timing, outcome) = performGesture(app, idleTimeout: false, synthesize)
|
|
149
|
+
guard case .unsupported(let message, let hint) = outcome else {
|
|
150
|
+
logSynthesizedGesturePolicyDecision(kind: kind, context: context, fallbackAttempted: false)
|
|
151
|
+
return .performed(timing: timing)
|
|
152
|
+
}
|
|
153
|
+
let fallbackAllowed = synthesizedGesturePolicy(kind).fallbackPolicy.allowsXCTestCoordinateFallback(
|
|
154
|
+
accessibilityHealth: context?.accessibilityHealth ?? mainOwned.accessibilityHealth
|
|
155
|
+
)
|
|
156
|
+
logSynthesizedGesturePolicyDecision(
|
|
157
|
+
kind: kind,
|
|
158
|
+
context: context,
|
|
159
|
+
fallbackAttempted: fallbackAllowed
|
|
133
160
|
)
|
|
161
|
+
return fallbackAllowed
|
|
162
|
+
? .xctestFallback(message: message, hint: hint)
|
|
163
|
+
: .refused(timing: timing, message: message, hint: hint)
|
|
134
164
|
}
|
|
135
165
|
|
|
166
|
+
@MainActor
|
|
136
167
|
func logSynthesizedGesturePolicyDecision(
|
|
137
168
|
kind: SynthesizedGesturePolicyKind,
|
|
138
169
|
context: SynthesizedCoordinateContext?,
|
|
@@ -162,11 +193,12 @@ extension RunnerTests {
|
|
|
162
193
|
return "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=\(kind.rawValue)"
|
|
163
194
|
+ " context=unavailable fallbackAttempted=\(fallbackAttempted)"
|
|
164
195
|
}
|
|
196
|
+
let fallbackPolicy = synthesizedGesturePolicy(kind).fallbackPolicy
|
|
165
197
|
return "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=\(kind.rawValue)"
|
|
166
198
|
+ " axHealth=\(context.accessibilityHealth.rawValue) frameSource=window"
|
|
167
199
|
+ " keyboardPolicy=\(context.keyboardPolicy.rawValue)"
|
|
168
|
-
+ " fallbackPolicy=\(
|
|
169
|
-
+ " fallbackAllowed=\(context.
|
|
200
|
+
+ " fallbackPolicy=\(fallbackPolicy.rawValue)"
|
|
201
|
+
+ " fallbackAllowed=\(fallbackPolicy.allowsXCTestCoordinateFallback(accessibilityHealth: context.accessibilityHealth))"
|
|
170
202
|
+ " fallbackAttempted=\(fallbackAttempted)"
|
|
171
203
|
}
|
|
172
204
|
}
|
|
@@ -2,6 +2,7 @@ import XCTest
|
|
|
2
2
|
import AgentDeviceSnapshotPresentation
|
|
3
3
|
|
|
4
4
|
extension RunnerTests {
|
|
5
|
+
@MainActor
|
|
5
6
|
func synthesizedDragAt(
|
|
6
7
|
app: XCUIApplication,
|
|
7
8
|
x: Double,
|
|
@@ -89,6 +90,7 @@ extension RunnerTests {
|
|
|
89
90
|
#endif
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
@MainActor
|
|
92
94
|
func synthesizedTapAt(
|
|
93
95
|
app: XCUIApplication,
|
|
94
96
|
x: Double,
|
|
@@ -276,6 +278,7 @@ extension RunnerTests {
|
|
|
276
278
|
#endif
|
|
277
279
|
}
|
|
278
280
|
|
|
281
|
+
@MainActor
|
|
279
282
|
func axFreeSynthesizedDragPlan(
|
|
280
283
|
app: XCUIApplication,
|
|
281
284
|
x: Double,
|
|
@@ -364,12 +367,13 @@ extension RunnerTests {
|
|
|
364
367
|
)
|
|
365
368
|
}
|
|
366
369
|
|
|
370
|
+
@MainActor
|
|
367
371
|
func synthesizedCoordinateContext(
|
|
368
372
|
app: XCUIApplication,
|
|
369
373
|
policy: SynthesizedGesturePolicy
|
|
370
374
|
) -> SynthesizedCoordinateContext? {
|
|
371
375
|
#if os(iOS)
|
|
372
|
-
let health =
|
|
376
|
+
let health = mainOwned.accessibilityHealth
|
|
373
377
|
let resolved = resolveRunnerWindow(app: app)
|
|
374
378
|
guard let window = resolved.window else {
|
|
375
379
|
return nil
|
|
@@ -384,7 +388,6 @@ extension RunnerTests {
|
|
|
384
388
|
referenceFrame: referenceFrame,
|
|
385
389
|
resolvedWindow: window,
|
|
386
390
|
keyboardPolicy: policy.keyboardPolicy,
|
|
387
|
-
fallbackPolicy: policy.fallbackPolicy,
|
|
388
391
|
accessibilityHealth: health
|
|
389
392
|
)
|
|
390
393
|
#else
|
|
@@ -82,11 +82,11 @@ extension RunnerTests {
|
|
|
82
82
|
text: String,
|
|
83
83
|
delaySeconds: Double
|
|
84
84
|
) -> [SynthesizedReplacementStep] {
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
guard synthesizedReplacementIsSpaced(characterCount: text.count, delaySeconds: delaySeconds)
|
|
86
|
+
else {
|
|
87
87
|
return [SynthesizedReplacementStep(text: text, replacesExistingText: true)]
|
|
88
88
|
}
|
|
89
|
-
return
|
|
89
|
+
return Array(text).enumerated().map { index, character in
|
|
90
90
|
SynthesizedReplacementStep(
|
|
91
91
|
text: String(character),
|
|
92
92
|
replacesExistingText: index == 0
|
|
@@ -94,11 +94,86 @@ extension RunnerTests {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
static func synthesizedReplacementIsSpaced(characterCount: Int, delaySeconds: Double) -> Bool {
|
|
100
|
+
delaySeconds > 0 && characterCount > 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
enum SynthesizedDeliveryBudget {
|
|
107
|
+
|
|
108
|
+
static var characterInterval: TimeInterval {
|
|
109
|
+
1.0 / Double(RunnerSynthesizedTextEntry.typingSpeedCharactersPerSecond())
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
static func projectedSeconds(
|
|
118
|
+
textLength: Int,
|
|
119
|
+
delaySeconds: TimeInterval,
|
|
120
|
+
typeWarmup: Bool = false
|
|
121
|
+
) -> TimeInterval {
|
|
122
|
+
let spaced = synthesizedReplacementIsSpaced(characterCount: textLength, delaySeconds: delaySeconds)
|
|
123
|
+
let warmupSplit = typeWarmup && textLength > 1 && !spaced
|
|
124
|
+
let calls = spaced ? textLength : (warmupSplit ? 2 : 1)
|
|
125
|
+
return Double(textLength) * characterInterval
|
|
126
|
+
+ Double(calls) * TextEntryTiming.synthesizeCallOverhead
|
|
127
|
+
+ Double(calls - 1) * delaySeconds
|
|
128
|
+
+ (warmupSplit ? TextEntryTiming.pollInterval : 0)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static func exceeds(
|
|
132
|
+
textLength: Int,
|
|
133
|
+
delaySeconds: TimeInterval,
|
|
134
|
+
typeWarmup: Bool = false
|
|
135
|
+
) -> Bool {
|
|
136
|
+
projectedSeconds(textLength: textLength, delaySeconds: delaySeconds, typeWarmup: typeWarmup)
|
|
137
|
+
> TextEntryTiming.synthesizedDeliveryCeiling
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
static func maxTextLength(delaySeconds: TimeInterval) -> Int {
|
|
142
|
+
var length = 1
|
|
143
|
+
while !exceeds(textLength: length + 1, delaySeconds: delaySeconds) {
|
|
144
|
+
length += 1
|
|
145
|
+
}
|
|
146
|
+
return length
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@MainActor
|
|
97
151
|
func runSynthesizedReplacementRoute(
|
|
98
152
|
_ request: SynthesizedReplacementRequest
|
|
99
153
|
) -> SynthesizedReplacementRouteOutcome {
|
|
100
154
|
#if os(iOS)
|
|
101
155
|
NSLog("AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder-replacement")
|
|
156
|
+
if SynthesizedDeliveryBudget.exceeds(
|
|
157
|
+
textLength: request.text.count,
|
|
158
|
+
delaySeconds: request.delaySeconds
|
|
159
|
+
) {
|
|
160
|
+
NSLog(
|
|
161
|
+
"AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder-replacement "
|
|
162
|
+
+ "reason=delivery-budget-refused chars=%d budgetChars=%d",
|
|
163
|
+
request.text.count,
|
|
164
|
+
SynthesizedDeliveryBudget.maxTextLength(delaySeconds: request.delaySeconds)
|
|
165
|
+
)
|
|
166
|
+
return .completed(
|
|
167
|
+
TextEntryResult(
|
|
168
|
+
verified: nil,
|
|
169
|
+
repaired: false,
|
|
170
|
+
expectedText: request.text,
|
|
171
|
+
observedText: nil,
|
|
172
|
+
textEntryRoute: "synthesized-first-responder-replacement",
|
|
173
|
+
failure: .synthesisBudgetExceeded
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
}
|
|
102
177
|
let steps = Self.synthesizedReplacementSteps(
|
|
103
178
|
text: request.text,
|
|
104
179
|
delaySeconds: request.delaySeconds
|
|
@@ -270,11 +345,4 @@ extension RunnerTests {
|
|
|
270
345
|
) -> Bool {
|
|
271
346
|
repairMode == .replacement && hasX && hasY && xCTestChannelPenalized
|
|
272
347
|
}
|
|
273
|
-
|
|
274
|
-
static func shouldFallbackFromSynthesizedTextEntryFocus(
|
|
275
|
-
_ outcome: RunnerInteractionOutcome
|
|
276
|
-
) -> Bool {
|
|
277
|
-
if case .unsupported = outcome { return true }
|
|
278
|
-
return false
|
|
279
|
-
}
|
|
280
348
|
}
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift
CHANGED
|
@@ -8,6 +8,7 @@ extension RunnerTests {
|
|
|
8
8
|
case notFocused = "TEXT_INPUT_NOT_FOCUSED"
|
|
9
9
|
case synthesisUnavailable = "TEXT_INPUT_SYNTHESIS_UNAVAILABLE"
|
|
10
10
|
case commitNotObserved = "TEXT_INPUT_COMMIT_NOT_OBSERVED"
|
|
11
|
+
case synthesisBudgetExceeded = "TEXT_INPUT_SYNTHESIS_BUDGET_EXCEEDED"
|
|
11
12
|
|
|
12
13
|
var message: String {
|
|
13
14
|
switch self {
|
|
@@ -17,6 +18,8 @@ extension RunnerTests {
|
|
|
17
18
|
return "Reliable text synthesis is unavailable while the software keyboard is hidden."
|
|
18
19
|
case .commitNotObserved:
|
|
19
20
|
return "The runner could not confirm the typed text reached the field."
|
|
21
|
+
case .synthesisBudgetExceeded:
|
|
22
|
+
return "The text is longer than one runner command can type at this pace."
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -27,7 +30,13 @@ extension RunnerTests {
|
|
|
27
30
|
case .synthesisUnavailable:
|
|
28
31
|
return "Show the software keyboard, then retry type."
|
|
29
32
|
case .commitNotObserved:
|
|
30
|
-
return "The field may hold none, part, or all of the text. Run snapshot -i and inspect the field: if it already matches, continue; otherwise retry fill with the full text quoted and --delay-ms
|
|
33
|
+
return "The field may hold none, part, or all of the text. Run snapshot -i and inspect the field: if it already matches, continue; otherwise retry fill with the full text quoted and --delay-ms \(TextEntryTiming.recoveryDelayMilliseconds). Do not use type, which appends to whatever committed."
|
|
34
|
+
case .synthesisBudgetExceeded:
|
|
35
|
+
let recoveryDelay = TextEntryTiming.recoveryDelayMilliseconds
|
|
36
|
+
let recoveryBudget = SynthesizedDeliveryBudget.maxTextLength(
|
|
37
|
+
delaySeconds: Double(recoveryDelay) / 1000
|
|
38
|
+
)
|
|
39
|
+
return "Fill at most \(SynthesizedDeliveryBudget.maxTextLength(delaySeconds: 0)) characters at a time without --delay-ms and append the rest with separate type commands, keeping each command inside that budget. --delay-ms lowers the budget, because each character then gets its own synthesize call and each gap between characters pays the delay: \(recoveryBudget) characters at --delay-ms \(recoveryDelay). A longer timeout does not help: this route is chosen when the accessibility channel is already degraded, and the pace is what makes the text long."
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
}
|
|
@@ -51,8 +60,29 @@ extension RunnerTests {
|
|
|
51
60
|
static let synthesizedCommitStallTimeout: TimeInterval = 3.0
|
|
52
61
|
|
|
53
62
|
|
|
54
|
-
|
|
55
63
|
static let synthesizedCommitCeiling: TimeInterval = 10.0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
static let synthesizedReplacementFocusAllowance: TimeInterval = 2.0
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
static let synthesizedDeliveryCeiling: TimeInterval = RunnerTests.mainThreadExecutionTimeout
|
|
72
|
+
- synthesizedReplacementFocusAllowance
|
|
73
|
+
- synthesizedCommitCeiling
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
static let synthesizedAcknowledgeWindowSeconds: TimeInterval = 0.04
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
static let synthesizeCallOverhead: TimeInterval = 0.15
|
|
84
|
+
|
|
85
|
+
static let recoveryDelayMilliseconds = 80
|
|
56
86
|
static let synthesizedCommitPollInterval: TimeInterval = 0.2
|
|
57
87
|
}
|
|
58
88
|
|
|
@@ -6,6 +6,7 @@ import XCTest
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
extension RunnerTests {
|
|
9
|
+
@MainActor
|
|
9
10
|
func rememberTextEntryTap(_ element: XCUIElement?) {
|
|
10
11
|
guard let element, isTextEntryElement(element) else {
|
|
11
12
|
clearRememberedTextEntryTap()
|
|
@@ -13,8 +14,8 @@ extension RunnerTests {
|
|
|
13
14
|
}
|
|
14
15
|
textEntryTapWitness = TextEntryTapWitness(
|
|
15
16
|
element: element,
|
|
16
|
-
bundleId:
|
|
17
|
-
processIdentifier:
|
|
17
|
+
bundleId: mainOwned.bundleId,
|
|
18
|
+
processIdentifier: mainOwned.processIdentifier
|
|
18
19
|
)
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -22,6 +23,7 @@ extension RunnerTests {
|
|
|
22
23
|
textEntryTapWitness = nil
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
@MainActor
|
|
25
27
|
private func rememberedTextEntryTarget() -> TextEntryTarget? {
|
|
26
28
|
guard let witness = textEntryTapWitness else {
|
|
27
29
|
return nil
|
|
@@ -30,8 +32,8 @@ extension RunnerTests {
|
|
|
30
32
|
|
|
31
33
|
clearRememberedTextEntryTap()
|
|
32
34
|
guard witness.matches(
|
|
33
|
-
bundleId:
|
|
34
|
-
processIdentifier:
|
|
35
|
+
bundleId: mainOwned.bundleId,
|
|
36
|
+
processIdentifier: mainOwned.processIdentifier
|
|
35
37
|
) else {
|
|
36
38
|
return nil
|
|
37
39
|
}
|
|
@@ -80,6 +82,7 @@ extension RunnerTests {
|
|
|
80
82
|
#endif
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
@MainActor
|
|
83
86
|
func focusTextInputForTextEntry(app: XCUIApplication, x: Double?, y: Double?) -> TextEntryTarget {
|
|
84
87
|
guard let x, let y else {
|
|
85
88
|
let softwareKeyboardVisible = isKeyboardVisible(app: app)
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift
CHANGED
|
@@ -3,6 +3,7 @@ import XCTest
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
extension RunnerTests {
|
|
6
|
+
@MainActor
|
|
6
7
|
func typeTextReliably(
|
|
7
8
|
app: XCUIApplication,
|
|
8
9
|
target: TextEntryTarget,
|
|
@@ -162,6 +163,28 @@ extension RunnerTests {
|
|
|
162
163
|
return (currentTarget, nil)
|
|
163
164
|
} else if activeTarget.prefersFocusedElement && isKeyboardVisible(app: app) {
|
|
164
165
|
#if os(iOS)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if SynthesizedDeliveryBudget.exceeds(
|
|
175
|
+
textLength: text.count,
|
|
176
|
+
delaySeconds: delaySeconds,
|
|
177
|
+
typeWarmup: repairMode != .none
|
|
178
|
+
) {
|
|
179
|
+
textEntryRoute = "xctest-application-fallback"
|
|
180
|
+
NSLog(
|
|
181
|
+
"AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=xctest-application-fallback "
|
|
182
|
+
+ "reason=delivery-budget chars=%d",
|
|
183
|
+
value.count
|
|
184
|
+
)
|
|
185
|
+
app.typeText(value)
|
|
186
|
+
return (resolveTextEntryElement(app: app, target: activeTarget), nil)
|
|
187
|
+
}
|
|
165
188
|
textEntryRoute = "synthesized-first-responder"
|
|
166
189
|
NSLog("AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder")
|
|
167
190
|
let action = synthesizer.enterText(
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift
CHANGED
|
@@ -33,11 +33,7 @@ extension RunnerTests {
|
|
|
33
33
|
let combined = buffer + data
|
|
34
34
|
if let body = self.parseRequest(data: combined) {
|
|
35
35
|
self.handleRequestBody(body) { [weak self] result in
|
|
36
|
-
self?.
|
|
37
|
-
if result.shouldFinish {
|
|
38
|
-
self?.finish()
|
|
39
|
-
}
|
|
40
|
-
}
|
|
36
|
+
self?.sendResult(result, over: connection)
|
|
41
37
|
}
|
|
42
38
|
} else {
|
|
43
39
|
self.receiveRequest(connection: connection, buffer: combined)
|
|
@@ -45,10 +41,21 @@ extension RunnerTests {
|
|
|
45
41
|
}
|
|
46
42
|
}
|
|
47
43
|
|
|
44
|
+
private func sendResult(
|
|
45
|
+
_ result: (data: Data, shouldFinish: Bool),
|
|
46
|
+
over connection: NWConnection
|
|
47
|
+
) {
|
|
48
|
+
sendResponse(result.data, over: connection) { [weak self] in
|
|
49
|
+
if result.shouldFinish {
|
|
50
|
+
self?.finish()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
private func sendResponse(
|
|
49
56
|
_ response: Data,
|
|
50
57
|
over connection: NWConnection,
|
|
51
|
-
afterSend: @escaping () -> Void = {}
|
|
58
|
+
afterSend: @escaping @Sendable () -> Void = {}
|
|
52
59
|
) {
|
|
53
60
|
connection.send(content: response, isComplete: true, completion: .contentProcessed { error in
|
|
54
61
|
if let error {
|
|
@@ -89,7 +96,7 @@ extension RunnerTests {
|
|
|
89
96
|
|
|
90
97
|
private func handleRequestBody(
|
|
91
98
|
_ body: Data,
|
|
92
|
-
completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
|
|
99
|
+
completion: @escaping @Sendable ((data: Data, shouldFinish: Bool)) -> Void
|
|
93
100
|
) {
|
|
94
101
|
guard String(data: body, encoding: .utf8) != nil else {
|
|
95
102
|
completion((
|
|
@@ -187,7 +194,7 @@ extension RunnerTests {
|
|
|
187
194
|
|
|
188
195
|
func enqueueAccepted(
|
|
189
196
|
command: Command,
|
|
190
|
-
completion: @escaping (Result<Response, Error>) -> Void
|
|
197
|
+
completion: @escaping @Sendable (Result<Response, Error>) -> Void
|
|
191
198
|
) {
|
|
192
199
|
commandJournal.accept(command: command)
|
|
193
200
|
commandExecutionQueue.async {
|
|
@@ -202,7 +209,7 @@ extension RunnerTests {
|
|
|
202
209
|
|
|
203
210
|
func attachToInFlightCommandIfNeeded(
|
|
204
211
|
command: Command,
|
|
205
|
-
completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
|
|
212
|
+
completion: @escaping @Sendable ((data: Data, shouldFinish: Bool)) -> Void
|
|
206
213
|
) -> Bool {
|
|
207
214
|
guard let commandId = command.commandId?.trimmedNonEmpty else { return false }
|
|
208
215
|
inFlightCommandLock.lock()
|
|
@@ -226,7 +233,7 @@ extension RunnerTests {
|
|
|
226
233
|
result: (data: Data, shouldFinish: Bool),
|
|
227
234
|
completion: ((data: Data, shouldFinish: Bool)) -> Void
|
|
228
235
|
) {
|
|
229
|
-
var waiters: [((data: Data, shouldFinish: Bool)) -> Void] = []
|
|
236
|
+
var waiters: [@Sendable ((data: Data, shouldFinish: Bool)) -> Void] = []
|
|
230
237
|
if let commandId = command.commandId?.trimmedNonEmpty {
|
|
231
238
|
inFlightCommandLock.lock()
|
|
232
239
|
inFlightCommandIds.remove(commandId)
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift
CHANGED
|
@@ -52,23 +52,22 @@ extension RunnerTests {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
func elementHasFocus(_ element: XCUIElement) -> Bool {
|
|
55
|
-
|
|
56
|
-
_ = RunnerObjCExceptionCatcher.catchException({
|
|
57
|
-
if let value = (element as NSObject).value(forKey: "hasFocus") as? Bool {
|
|
58
|
-
focused = value
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
return focused
|
|
55
|
+
return focusBool(element as NSObject)
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
func activateElement(
|
|
58
|
+
func activateElement(
|
|
59
|
+
app: XCUIApplication,
|
|
60
|
+
element: XCUIElement,
|
|
61
|
+
action: String,
|
|
62
|
+
resolvedFrame: CGRect? = nil
|
|
63
|
+
) -> RunnerInteractionOutcome {
|
|
65
64
|
if let outcome = selectFocusedTvElement(app: app, element: element, action: action) {
|
|
66
65
|
return outcome
|
|
67
66
|
}
|
|
68
67
|
#if os(tvOS)
|
|
69
68
|
return performElementTap(element)
|
|
70
69
|
#else
|
|
71
|
-
let frame = element.frame
|
|
70
|
+
let frame = resolvedFrame ?? element.frame
|
|
72
71
|
if !frame.isEmpty {
|
|
73
72
|
|
|
74
73
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift
CHANGED
|
@@ -2,6 +2,7 @@ import XCTest
|
|
|
2
2
|
import AgentDeviceSnapshotPresentation
|
|
3
3
|
|
|
4
4
|
extension RunnerTests {
|
|
5
|
+
@MainActor
|
|
5
6
|
func executeTypeCommand(activeApp: XCUIApplication, command: Command) -> Response {
|
|
6
7
|
guard let text = command.text else {
|
|
7
8
|
return Response(ok: false, error: ErrorPayload(message: "type requires text"))
|
|
@@ -18,7 +19,7 @@ extension RunnerTests {
|
|
|
18
19
|
: nil
|
|
19
20
|
let focusStartedAt = Date()
|
|
20
21
|
#if os(iOS)
|
|
21
|
-
let xCTestChannelPenalized = isSnapshotXCTestChannelPenalized(bundleId:
|
|
22
|
+
let xCTestChannelPenalized = isSnapshotXCTestChannelPenalized(bundleId: mainOwned.bundleId)
|
|
22
23
|
var resolvedCoordinateTarget: TextEntryTarget?
|
|
23
24
|
if Self.shouldUseResolvedCoordinateTextEntryRoute(
|
|
24
25
|
repairMode: textEntryMode,
|
|
@@ -31,27 +32,20 @@ extension RunnerTests {
|
|
|
31
32
|
app: activeApp,
|
|
32
33
|
policy: synthesizedGesturePolicy(policyKind)
|
|
33
34
|
)
|
|
34
|
-
|
|
35
|
+
switch performSynthesizedGesture(activeApp, kind: policyKind, context: context, synthesize: {
|
|
35
36
|
synthesizedTapAt(app: activeApp, x: x, y: y, context: context)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
logSynthesizedGesturePolicyDecision(
|
|
39
|
-
kind: policyKind,
|
|
40
|
-
context: context,
|
|
41
|
-
fallbackAttempted: true
|
|
42
|
-
)
|
|
43
|
-
} else {
|
|
44
|
-
logSynthesizedGesturePolicyDecision(
|
|
45
|
-
kind: policyKind,
|
|
46
|
-
context: context,
|
|
47
|
-
fallbackAttempted: false
|
|
48
|
-
)
|
|
37
|
+
}) {
|
|
38
|
+
case .performed:
|
|
49
39
|
resolvedCoordinateContext = context
|
|
50
40
|
resolvedCoordinateTarget = TextEntryTarget(
|
|
51
41
|
element: nil,
|
|
52
42
|
refreshPoint: CGPoint(x: x, y: y),
|
|
53
43
|
prefersFocusedElement: false
|
|
54
44
|
)
|
|
45
|
+
case .xctestFallback:
|
|
46
|
+
break
|
|
47
|
+
case .refused(_, let message, let hint):
|
|
48
|
+
return unsupportedResponse(message: message, hint: hint)
|
|
55
49
|
}
|
|
56
50
|
}
|
|
57
51
|
#else
|