agent-device 0.20.10 → 0.21.1
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/README.md +2 -2
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.apk → agent-device-android-ime-helper-0.21.1.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.1.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.manifest.json → agent-device-android-ime-helper-0.21.1.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.1.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.1.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.10.manifest.json → agent-device-android-snapshot-helper-0.21.1.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +35 -33
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +6 -1
- package/apple/snapshot-bridge/LICENSE.idb +23 -0
- package/apple/snapshot-bridge/README.md +106 -0
- package/apple/snapshot-bridge/SnapshotBridge.m +286 -0
- package/apple/snapshot-bridge/SnapshotBridgeCapture.h +25 -0
- package/apple/snapshot-bridge/SnapshotBridgeCapture.m +138 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +34 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +411 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +58 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +19 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAlertVerification.swift +36 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +15 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerStringNormalization.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +12 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +100 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +72 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +63 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +677 -83
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +35 -92
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +124 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +39 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1058 -213
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +296 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +10 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +309 -149
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +101 -42
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +24 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +124 -199
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +71 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXElementTypes.swift +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +211 -78
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +30 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +254 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +206 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +465 -494
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +168 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +802 -247
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationInvariant.swift +19 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +185 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +206 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +83 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +156 -34
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +35 -318
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +206 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +158 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +101 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +56 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +56 -27
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +30 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +126 -80
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +111 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +47 -86
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +32 -79
- package/dist/apple/snapshot-presentation/Package.swift +21 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +56 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +259 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +153 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationFailure.swift +27 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +91 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +161 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotScopePolicy.swift +53 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +242 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +97 -0
- package/dist/src/adapter.js +1 -0
- package/dist/src/adb-executor.js +2 -0
- package/dist/src/adb-failure.js +1 -0
- package/dist/src/adb-host.js +1 -0
- package/dist/src/adb.js +1 -0
- package/dist/src/agent-browser-lifecycle.js +1 -0
- package/dist/src/agent-browser-process-record.js +1 -0
- package/dist/src/agent-browser-provider.js +1 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-contract.js +1 -0
- package/dist/src/alert-runtime.js +1 -0
- package/dist/src/android-adb.d.ts +27 -19
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -0
- package/dist/src/android-system-chrome.js +1 -0
- package/dist/src/android.js +1 -1
- package/dist/src/api.js +11 -0
- package/dist/src/app-catalog.js +1 -0
- package/dist/src/app-deployment-resolution.js +2 -0
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-inventory-contract.js +1 -0
- package/dist/src/app-inventory.js +1 -0
- package/dist/src/app-launch.js +2 -0
- package/dist/src/app-lifecycle-facade.js +1 -0
- package/dist/src/app-lifecycle.js +3 -6
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-lifecycle3.js +1 -0
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +1 -4
- package/dist/src/app-log-runtime2.js +4 -0
- package/dist/src/app-parsers.js +4 -0
- package/dist/src/app-resolution-cache.js +1 -0
- package/dist/src/app-resolution-facade.js +1 -0
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +1 -2
- package/dist/src/apple-runner-platform.js +1 -0
- package/dist/src/application-lifecycle-interaction.js +1 -0
- package/dist/src/application-lifecycle-runtime.js +1 -0
- package/dist/src/apps-simctl.js +1 -0
- package/dist/src/archive.js +4 -0
- package/dist/src/artifact-download.js +1 -0
- package/dist/src/artifacts.d.ts +6 -2
- package/dist/src/artifacts.js +1 -1
- package/dist/src/async-lifecycle.js +1 -0
- package/dist/src/audio-probe-result.js +1 -0
- package/dist/src/audio-probe-runtime.js +1 -0
- package/dist/src/audio-probe-support.js +1 -0
- 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/{url.js → base-url.js} +1 -1
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/byte-limit-stream.js +1 -1
- package/dist/src/capabilities.js +1 -0
- package/dist/src/capture.js +1 -0
- package/dist/src/catalog.js +1 -0
- package/dist/src/cli-command-aliases.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +74 -51
- package/dist/src/cli-output.js +1 -1
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +4 -6
- package/dist/src/click-button.js +1 -0
- package/dist/src/client-metro-companion.js +1 -0
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +280 -242
- package/dist/src/clipboard.js +1 -0
- package/dist/src/code-signature-cache.js +1 -0
- package/dist/src/code-signature.js +1 -0
- package/dist/src/color.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/command.js +1 -0
- package/dist/src/compatibility-policy.js +1 -0
- package/dist/src/config.js +1 -1
- package/dist/src/config2.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -0
- package/dist/src/daemon-process.js +1 -0
- package/dist/src/daemon-registration.js +1 -0
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +2 -2
- package/dist/src/debug-symbols-facade.js +5 -0
- package/dist/src/deploy-result-target.js +1 -0
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +1 -0
- package/dist/src/device-input-state.d.ts +190 -3
- package/dist/src/device-inventory-context.js +1 -0
- package/dist/src/device-isolation.js +1 -0
- package/dist/src/device-release.js +1 -0
- package/dist/src/device-rotation.js +1 -0
- package/dist/src/device-selection-resolver.js +1 -0
- package/dist/src/device-session.js +1 -0
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +3 -2
- package/dist/src/diagnostics.js +3 -0
- package/dist/src/diagnostics2.js +1 -0
- package/dist/src/dispatch-resolve.js +1 -0
- package/dist/src/doctor-facade.js +1 -0
- package/dist/src/doctor-output.js +1 -0
- package/dist/src/doctor.js +1 -0
- package/dist/src/doctor2.js +1 -0
- package/dist/src/doctor3.js +1 -0
- package/dist/src/durable-resource.js +1 -0
- package/dist/src/entities.js +1 -1
- package/dist/src/error.js +2 -0
- package/dist/src/exec.js +1 -0
- package/dist/src/file.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.js +1 -0
- package/dist/src/gesture-plan-types.js +1 -0
- package/dist/src/gesture-plan.js +1 -0
- package/dist/src/gesture-runtime.js +1 -0
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host-file.js +1 -0
- package/dist/src/human-control-contract.js +1 -0
- package/dist/src/human-control.js +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -4
- package/dist/src/input-actions2.js +2 -1
- package/dist/src/install-artifact-facade.js +1 -0
- package/dist/src/install-source-network-transport.js +1 -0
- package/dist/src/install-source.d.ts +3 -10
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-positionals.js +1 -0
- package/dist/src/interaction-ref-policy.js +1 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-catalog.js +1 -0
- package/dist/src/interactor-types.js +1 -0
- package/dist/src/interactor.js +6 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.d.ts +1 -1
- package/dist/src/internal/bin.js +1 -2
- package/dist/src/internal/companion-tunnel.d.ts +1 -1
- package/dist/src/internal/companion-tunnel.js +1 -1
- package/dist/src/internal/daemon.d.ts +1 -1
- package/dist/src/internal/daemon.js +2 -4
- package/dist/src/internal/png-worker.d.ts +4 -4
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.d.ts +4 -0
- package/dist/src/internal/run-script-http-child.js +1 -0
- package/dist/src/internal/update-check-entry.d.ts +1 -1
- package/dist/src/inventory.js +4 -4
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/inventory6.js +1 -1
- package/dist/src/ios-client.js +16 -0
- package/dist/src/ios-snapshot-acquisition.js +1 -0
- package/dist/src/ios-snapshot-adapter.js +1 -0
- package/dist/src/ios-snapshot-planning.js +1 -0
- package/dist/src/ios-snapshot-runtime.js +1 -0
- package/dist/src/ios-system-surface.js +1 -0
- package/dist/src/json.js +1 -0
- package/dist/src/keyboard-actions.js +1 -0
- package/dist/src/launch-console.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-scope.js +1 -0
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +1610 -7
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -0
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/macos-facade.js +1 -0
- package/dist/src/managed-device-scope.js +1 -0
- package/dist/src/mechanics.js +19 -0
- package/dist/src/metro.d.ts +4 -2
- package/dist/src/metro.js +1 -1
- package/dist/src/metro2.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/multitouch-support.js +1 -0
- package/dist/src/numeric.js +1 -0
- package/dist/src/observability.js +1 -1
- package/dist/src/observation.js +2 -0
- package/dist/src/open-target-resolution.js +1 -0
- package/dist/src/output-path.js +1 -1
- package/dist/src/owner-identity.js +3 -1
- package/dist/src/parameterized-recorded-fill.js +1 -0
- package/dist/src/parser.js +1 -1
- package/dist/src/perf-facade.js +2 -0
- package/dist/src/perf-process-identity.js +1 -0
- package/dist/src/perf-runtime-operation-builder.js +1 -0
- package/dist/src/perf-runtime-plan.js +1 -0
- package/dist/src/perf-runtime.js +1 -0
- package/dist/src/perf.js +1 -4
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/physical-device-facade.js +1 -0
- package/dist/src/platform-request-scope.js +1 -0
- package/dist/src/platform-runtime-android-adb-host.js +1 -0
- package/dist/src/platform-runtime-android-mechanics.js +1 -0
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -0
- package/dist/src/platform-runtime-network-web-transport.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 +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -0
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plist.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/prepare-kind.js +1 -0
- package/dist/src/process-exit.js +1 -1
- package/dist/src/process.js +1 -0
- package/dist/src/provider-device-runtime.js +1 -0
- package/dist/src/provider-session-ownership.js +2 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -1
- package/dist/src/providers.js +1 -0
- package/dist/src/proxy.js +2 -2
- package/dist/src/react-native-overlay.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/rect-center.js +1 -0
- package/dist/src/register-builtins.js +1 -0
- package/dist/src/registry.js +40 -28
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +2 -0
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +8 -7
- package/dist/src/request-admission.js +1 -0
- package/dist/src/request-cancel.js +1 -0
- package/dist/src/request-cancellation.js +1 -0
- package/dist/src/request-progress-protocol.js +1 -0
- package/dist/src/request-providers.js +1 -0
- package/dist/src/request-runtime-binding.js +1 -0
- package/dist/src/request.js +1 -0
- package/dist/src/result-serialization.js +1 -0
- package/dist/src/retry.js +1 -0
- package/dist/src/rolldown-runtime.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -0
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -0
- package/dist/src/runner-owner-facade.js +1 -0
- package/dist/src/runner-owner-state.js +1 -0
- package/dist/src/runner-presentation.js +1 -0
- package/dist/src/runner.js +1 -0
- package/dist/src/{runtime-transport.js → runtime-transport-hints.js} +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -3
- 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/scoped-provider.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -0
- package/dist/src/screen-recording-live-handle.js +1 -0
- package/dist/src/screen-recording-options.js +1 -0
- package/dist/src/screen-recording-resource-recovery.js +1 -0
- package/dist/src/screen-recording-runtime.js +1 -0
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-result.js +1 -6
- package/dist/src/screenshot-runtime.js +1 -0
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot2.js +1 -0
- package/dist/src/screenshot3.js +5 -0
- package/dist/src/script.js +1 -0
- package/dist/src/scroll-command.js +1 -0
- package/dist/src/scroll-gesture.js +1 -0
- package/dist/src/scroll-indicator.js +1 -0
- package/dist/src/sdk-batch-runner.d.ts +23 -6
- package/dist/src/sdk-batch-runner.js +2 -3
- package/dist/src/sdk-batch.js +2 -0
- package/dist/src/sdk-contracts.d.ts +170 -41
- 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-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.d.ts +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +524 -140
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/semantic-index.js +1 -0
- package/dist/src/server.js +4 -4
- package/dist/src/session-allocation.js +1 -0
- package/dist/src/session-artifact-paths.js +1 -0
- package/dist/src/session-observation.js +1 -0
- package/dist/src/session-paths.js +1 -0
- package/dist/src/session-repair-tombstone.js +1 -0
- package/dist/src/session-routing.js +1 -0
- package/dist/src/session-runtime-admission.js +1 -0
- package/dist/src/session-snapshot.js +1 -0
- package/dist/src/session-store.js +4 -0
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session2.js +5 -27
- package/dist/src/settings.js +1 -0
- package/dist/src/shared.js +2 -2
- package/dist/src/simctl-facade.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-facade.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -0
- package/dist/src/snapshot-desktop-projection.js +1 -0
- package/dist/src/snapshot-diagnostics.js +1 -0
- package/dist/src/snapshot-process.js +1 -0
- package/dist/src/snapshot-quality-backend-capabilities.js +1 -0
- package/dist/src/snapshot-quality-verdict.js +1 -0
- package/dist/src/snapshot-runtime-binding.js +1 -0
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -1
- package/dist/src/snapshot-state.js +1 -0
- package/dist/src/snapshot.js +1 -8
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +1 -2
- package/dist/src/src4.js +1 -1
- package/dist/src/src5.js +1 -0
- package/dist/src/src6.js +1 -0
- package/dist/src/src7.js +2 -0
- package/dist/src/src8.js +115 -0
- package/dist/src/startup-recovery-fence.js +1 -0
- package/dist/src/status-markers.js +1 -0
- package/dist/src/string-enum.js +1 -1
- package/dist/src/success-text.js +1 -0
- package/dist/src/surface-snapshot.js +1 -0
- package/dist/src/surface-snapshot2.js +1 -0
- package/dist/src/takeover.js +5 -0
- package/dist/src/tool-provider-facade.js +1 -0
- package/dist/src/tool-provider.js +4 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/toolchain-probe.js +2 -0
- package/dist/src/touch-reference-frame.js +1 -0
- package/dist/src/touch-runtime.js +1 -0
- package/dist/src/transport.js +3 -0
- package/dist/src/tree.js +1 -0
- package/dist/src/ttl-memo.js +1 -0
- package/dist/src/tv-remote.js +1 -0
- package/dist/src/type-text-runtime.js +1 -0
- package/dist/src/undici.js +99 -0
- package/dist/src/update-check.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/web.js +2 -1
- package/dist/src/web2.js +1 -0
- package/dist/src/webdriver-ios-snapshot.js +1 -0
- package/dist/src/webdriver-source.js +1 -0
- package/dist/src/window-state.js +1 -0
- package/linux/atspi-dump.py +54 -9
- package/package.json +58 -35
- package/server.json +9 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +0 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +0 -168
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +0 -183
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +0 -4
- package/dist/src/appearance.js +0 -1
- package/dist/src/apps.js +0 -5
- package/dist/src/audio-probe.js +0 -1
- package/dist/src/cli-grammar.js +0 -1
- package/dist/src/command-catalog.js +0 -1
- package/dist/src/debug-symbols.js +0 -5
- package/dist/src/device-input-state.js +0 -2
- package/dist/src/device-ready.js +0 -1
- package/dist/src/dispatch.js +0 -1
- package/dist/src/handler-utils.js +0 -1
- package/dist/src/helper-package-install.js +0 -1
- package/dist/src/host-process.js +0 -3
- package/dist/src/ime-lifecycle.js +0 -2
- package/dist/src/ime-recovery-marker.js +0 -1
- package/dist/src/input-actions3.js +0 -1
- package/dist/src/install-artifact.js +0 -1
- package/dist/src/install-artifact2.js +0 -1
- package/dist/src/interaction-common.js +0 -1
- package/dist/src/interaction-runtime.js +0 -1
- package/dist/src/interaction-snapshot.js +0 -1
- package/dist/src/manifest.js +0 -1
- package/dist/src/method-scope.js +0 -1
- package/dist/src/png-resize.js +0 -1
- package/dist/src/process-lock.js +0 -1
- package/dist/src/runner-lease.js +0 -1
- package/dist/src/runner-sequence.js +0 -1
- package/dist/src/script-source-bundle.js +0 -16
- package/dist/src/sdk-android-adb.d.ts +0 -245
- package/dist/src/sdk-android-adb.js +0 -4
- package/dist/src/sdk.js +0 -1
- package/dist/src/setting-state.js +0 -1
- package/dist/src/shell-quote.js +0 -1
- package/dist/src/snapshot-session.js +0 -1
- package/dist/src/timing-safe-equal.js +0 -1
- package/dist/src/unsupported-interactor.js +0 -1
- package/dist/src/verdict.js +0 -1
- /package/dist/src/{recording-telemetry.js → telemetry.js} +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
extension RunnerTests {
|
|
9
|
+
func rememberTextEntryTap(_ element: XCUIElement?) {
|
|
10
|
+
guard let element, isTextEntryElement(element) else {
|
|
11
|
+
clearRememberedTextEntryTap()
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
textEntryTapWitness = TextEntryTapWitness(
|
|
15
|
+
element: element,
|
|
16
|
+
bundleId: currentBundleId,
|
|
17
|
+
processIdentifier: currentAppProcessIdentifier
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func clearRememberedTextEntryTap() {
|
|
22
|
+
textEntryTapWitness = nil
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private func rememberedTextEntryTarget() -> TextEntryTarget? {
|
|
26
|
+
guard let witness = textEntryTapWitness else {
|
|
27
|
+
return nil
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
clearRememberedTextEntryTap()
|
|
32
|
+
guard witness.matches(
|
|
33
|
+
bundleId: currentBundleId,
|
|
34
|
+
processIdentifier: currentAppProcessIdentifier
|
|
35
|
+
) else {
|
|
36
|
+
return nil
|
|
37
|
+
}
|
|
38
|
+
let element = witness.element
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
guard safely("LAST_TAPPED_TEXT_INPUT_EXISTS", false, { element.exists }) else {
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
return TextEntryTarget(
|
|
50
|
+
element: element,
|
|
51
|
+
refreshPoint: nil,
|
|
52
|
+
prefersFocusedElement: false,
|
|
53
|
+
fromTapWitness: true
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func stabilizeTextInputBeforeTyping(
|
|
58
|
+
app: XCUIApplication,
|
|
59
|
+
target: XCUIElement?,
|
|
60
|
+
keyboardVisibleBeforeTap: Bool? = nil
|
|
61
|
+
) -> TextEntryStabilization {
|
|
62
|
+
#if os(tvOS)
|
|
63
|
+
return TextEntryStabilization(element: target, focusConfirmed: true)
|
|
64
|
+
#else
|
|
65
|
+
let latest = target
|
|
66
|
+
let keyboardVisibleAtEntry = keyboardVisibleBeforeTap ?? isKeyboardVisible(app: app)
|
|
67
|
+
let deadline = Date().addingTimeInterval(TextEntryTiming.focusTimeout)
|
|
68
|
+
while Date() < deadline {
|
|
69
|
+
if let focused = focusedTextInput(app: app) {
|
|
70
|
+
return TextEntryStabilization(element: focused, focusConfirmed: true)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if keyboardBecameVisible(app: app, wasVisibleAtEntry: keyboardVisibleAtEntry) {
|
|
75
|
+
return TextEntryStabilization(element: latest, focusConfirmed: true)
|
|
76
|
+
}
|
|
77
|
+
sleepFor(TextEntryTiming.pollInterval)
|
|
78
|
+
}
|
|
79
|
+
return TextEntryStabilization(element: latest, focusConfirmed: false)
|
|
80
|
+
#endif
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func focusTextInputForTextEntry(app: XCUIApplication, x: Double?, y: Double?) -> TextEntryTarget {
|
|
84
|
+
guard let x, let y else {
|
|
85
|
+
let softwareKeyboardVisible = isKeyboardVisible(app: app)
|
|
86
|
+
if !softwareKeyboardVisible, let rememberedTarget = rememberedTextEntryTarget() {
|
|
87
|
+
return rememberedTarget
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if softwareKeyboardVisible {
|
|
94
|
+
return TextEntryTarget(
|
|
95
|
+
element: focusedTextInput(app: app),
|
|
96
|
+
refreshPoint: nil,
|
|
97
|
+
prefersFocusedElement: true
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
let focused = waitForTextEntryReadiness(
|
|
101
|
+
app: app,
|
|
102
|
+
target: TextEntryTarget(
|
|
103
|
+
element: focusedTextInput(app: app),
|
|
104
|
+
refreshPoint: nil,
|
|
105
|
+
prefersFocusedElement: true
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
return TextEntryTarget(element: focused, refreshPoint: nil, prefersFocusedElement: true)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let keyboardVisibleBeforeTap = isKeyboardVisible(app: app)
|
|
112
|
+
let target = textInputAt(app: app, x: x, y: y)
|
|
113
|
+
let requestedPoint = CGPoint(x: x, y: y)
|
|
114
|
+
if let target {
|
|
115
|
+
let frame = target.frame
|
|
116
|
+
if !frame.isEmpty {
|
|
117
|
+
_ = tapAt(app: app, x: frame.midX, y: frame.midY)
|
|
118
|
+
} else {
|
|
119
|
+
_ = tapAt(app: app, x: x, y: y)
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
_ = tapAt(app: app, x: x, y: y)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if keyboardVisibleBeforeTap, let target {
|
|
128
|
+
return TextEntryTarget(
|
|
129
|
+
element: target,
|
|
130
|
+
refreshPoint: textEntryRefreshPoint(for: target) ?? requestedPoint,
|
|
131
|
+
prefersFocusedElement: false
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
let stabilized = stabilizeTextInputBeforeTyping(
|
|
135
|
+
app: app,
|
|
136
|
+
target: target,
|
|
137
|
+
keyboardVisibleBeforeTap: keyboardVisibleBeforeTap
|
|
138
|
+
)
|
|
139
|
+
let readyTarget = TextEntryTarget(
|
|
140
|
+
element: stabilized.element ?? target,
|
|
141
|
+
refreshPoint: requestedPoint,
|
|
142
|
+
prefersFocusedElement: false
|
|
143
|
+
)
|
|
144
|
+
let concreteTargetReady = keyboardVisibleBeforeTap && readyTarget.element != nil
|
|
145
|
+
let element = stabilized.focusConfirmed || concreteTargetReady
|
|
146
|
+
? (stabilized.element ?? target)
|
|
147
|
+
: (waitForTextEntryReadiness(app: app, target: readyTarget) ?? stabilized.element ?? target)
|
|
148
|
+
return TextEntryTarget(
|
|
149
|
+
element: element,
|
|
150
|
+
refreshPoint: textEntryRefreshPoint(for: element) ?? requestedPoint,
|
|
151
|
+
prefersFocusedElement: false
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func focusTextInputForTextEntry(app: XCUIApplication, element: XCUIElement) -> TextEntryTarget {
|
|
156
|
+
let point = textEntryRefreshPoint(for: element)
|
|
157
|
+
let keyboardVisibleBeforeTap = isKeyboardVisible(app: app)
|
|
158
|
+
if let point {
|
|
159
|
+
_ = tapAt(app: app, x: point.x, y: point.y)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
if keyboardVisibleBeforeTap {
|
|
164
|
+
return TextEntryTarget(
|
|
165
|
+
element: element,
|
|
166
|
+
refreshPoint: textEntryRefreshPoint(for: element) ?? point,
|
|
167
|
+
prefersFocusedElement: false
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
let stabilized = stabilizeTextInputBeforeTyping(
|
|
171
|
+
app: app,
|
|
172
|
+
target: element,
|
|
173
|
+
keyboardVisibleBeforeTap: keyboardVisibleBeforeTap
|
|
174
|
+
)
|
|
175
|
+
let readyTarget = TextEntryTarget(
|
|
176
|
+
element: stabilized.element ?? element,
|
|
177
|
+
refreshPoint: point,
|
|
178
|
+
prefersFocusedElement: false
|
|
179
|
+
)
|
|
180
|
+
let resolved = stabilized.focusConfirmed
|
|
181
|
+
? (stabilized.element ?? element)
|
|
182
|
+
: (waitForTextEntryReadiness(app: app, target: readyTarget) ?? stabilized.element ?? element)
|
|
183
|
+
return TextEntryTarget(
|
|
184
|
+
element: resolved,
|
|
185
|
+
refreshPoint: textEntryRefreshPoint(for: resolved) ?? point,
|
|
186
|
+
prefersFocusedElement: false
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private func textEntryRefreshPoint(for element: XCUIElement?) -> CGPoint? {
|
|
191
|
+
guard let element else {
|
|
192
|
+
return nil
|
|
193
|
+
}
|
|
194
|
+
let frame = element.frame
|
|
195
|
+
guard !frame.isEmpty else {
|
|
196
|
+
return nil
|
|
197
|
+
}
|
|
198
|
+
return CGPoint(x: frame.midX, y: frame.midY)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
extension RunnerTests {
|
|
8
|
+
func focusedTextInput(app: XCUIApplication) -> XCUIElement? {
|
|
9
|
+
#if os(iOS)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
return nil
|
|
13
|
+
#else
|
|
14
|
+
return safely("FOCUSED_INPUT_QUERY") {
|
|
15
|
+
let candidates = app
|
|
16
|
+
.descendants(matching: .any)
|
|
17
|
+
.matching(NSPredicate(format: "hasKeyboardFocus == 1"))
|
|
18
|
+
.allElementsBoundByIndex
|
|
19
|
+
for candidate in candidates where candidate.exists {
|
|
20
|
+
switch candidate.elementType {
|
|
21
|
+
case .textField, .secureTextField, .searchField, .textView:
|
|
22
|
+
return candidate
|
|
23
|
+
default:
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return nil
|
|
28
|
+
}
|
|
29
|
+
#endif
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func waitForTextEntryReadiness(
|
|
33
|
+
app: XCUIApplication,
|
|
34
|
+
target: TextEntryTarget,
|
|
35
|
+
timeout: TimeInterval = TextEntryTiming.readinessTimeout
|
|
36
|
+
) -> XCUIElement? {
|
|
37
|
+
#if os(iOS)
|
|
38
|
+
var latest = resolveTextEntryElement(app: app, target: target)
|
|
39
|
+
let keyboardVisibleAtEntry = isKeyboardVisible(app: app)
|
|
40
|
+
let deadline = Date().addingTimeInterval(timeout)
|
|
41
|
+
var hardwareKeyboardFallback = Date().addingTimeInterval(
|
|
42
|
+
min(TextEntryTiming.hardwareKeyboardFallbackTimeout, timeout)
|
|
43
|
+
)
|
|
44
|
+
var sawSoftwareKeyboard = false
|
|
45
|
+
while Date() < deadline {
|
|
46
|
+
if let focused = focusedTextInput(app: app) {
|
|
47
|
+
latest = focused
|
|
48
|
+
if isKeyboardVisible(app: app) {
|
|
49
|
+
return focused
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if keyboardBecameVisible(app: app, wasVisibleAtEntry: keyboardVisibleAtEntry) {
|
|
58
|
+
return latest
|
|
59
|
+
}
|
|
60
|
+
sawSoftwareKeyboard = sawSoftwareKeyboard || keyboardElementExists(app: app)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if !sawSoftwareKeyboard, Date() >= hardwareKeyboardFallback, let candidate = latest {
|
|
68
|
+
if keyboardFocusConfirmed(app: app, element: candidate) {
|
|
69
|
+
return candidate
|
|
70
|
+
}
|
|
71
|
+
hardwareKeyboardFallback = Date().addingTimeInterval(
|
|
72
|
+
TextEntryTiming.hardwareKeyboardFallbackTimeout
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
sleepFor(TextEntryTiming.pollInterval)
|
|
76
|
+
}
|
|
77
|
+
return focusedTextInput(app: app) ?? latest
|
|
78
|
+
#else
|
|
79
|
+
return resolveTextEntryElement(app: app, target: target)
|
|
80
|
+
#endif
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func waitForTextEntryReadinessAfterTap(app: XCUIApplication, element: XCUIElement) {
|
|
84
|
+
#if os(iOS)
|
|
85
|
+
switch element.elementType {
|
|
86
|
+
case .textField, .secureTextField, .searchField, .textView:
|
|
87
|
+
if waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout) != nil {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
let frame = element.frame
|
|
91
|
+
if !frame.isEmpty {
|
|
92
|
+
_ = tapAt(app: app, x: frame.midX, y: frame.midY)
|
|
93
|
+
_ = waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout)
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
#endif
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private func waitForFocusedTextInput(app: XCUIApplication, timeout: TimeInterval) -> XCUIElement? {
|
|
102
|
+
let deadline = Date().addingTimeInterval(timeout)
|
|
103
|
+
while Date() < deadline {
|
|
104
|
+
if let focused = focusedTextInput(app: app) {
|
|
105
|
+
return focused
|
|
106
|
+
}
|
|
107
|
+
sleepFor(TextEntryTiming.pollInterval)
|
|
108
|
+
}
|
|
109
|
+
return focusedTextInput(app: app)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
func keyboardBecameVisible(app: XCUIApplication, wasVisibleAtEntry: Bool) -> Bool {
|
|
113
|
+
return !wasVisibleAtEntry && isKeyboardVisible(app: app)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
func keyboardFocusConfirmed(app: XCUIApplication, element: XCUIElement) -> Bool {
|
|
128
|
+
#if os(iOS)
|
|
129
|
+
return safely("TEXT_ENTRY_FOCUS_CONFIRMED", false) {
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
let frame = element.frame
|
|
134
|
+
guard !frame.isEmpty else {
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
let focused = app
|
|
138
|
+
.descendants(matching: .any)
|
|
139
|
+
.matching(NSPredicate(format: "hasKeyboardFocus == 1"))
|
|
140
|
+
.firstMatch
|
|
141
|
+
guard focused.exists else {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
return focused.identifier == element.identifier && focused.frame == frame
|
|
145
|
+
}
|
|
146
|
+
#else
|
|
147
|
+
return false
|
|
148
|
+
#endif
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private func keyboardElementExists(app: XCUIApplication) -> Bool {
|
|
152
|
+
#if os(iOS)
|
|
153
|
+
return safely("KEYBOARD_EXISTS", false) { app.keyboards.firstMatch.exists }
|
|
154
|
+
#else
|
|
155
|
+
return false
|
|
156
|
+
#endif
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
final class TextInputProbeIssues {
|
|
4
|
+
let thread = Thread.current
|
|
5
|
+
var count = 0
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
enum TextInputProbeFailure: String {
|
|
9
|
+
case recordedIssue = "text_input_probe_recorded_issue"
|
|
10
|
+
case exception = "text_input_probe_exception"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
enum TextInputProbeOutcome {
|
|
14
|
+
case matches([XCUIElement])
|
|
15
|
+
case absent
|
|
16
|
+
case unavailable(TextInputProbeFailure)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
extension RunnerTests {
|
|
20
|
+
func textInputAt(app: XCUIApplication, x: Double, y: Double) -> XCUIElement? {
|
|
21
|
+
textInputCandidatesAt(app: app, point: CGPoint(x: x, y: y)).first
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func textInputCandidatesAt(app: XCUIApplication, point: CGPoint) -> [XCUIElement] {
|
|
25
|
+
safely("TEXT_INPUT_AT_POINT", []) {
|
|
26
|
+
queryTextInputs(app: app, point: point, shouldStop: { false })
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func coordinateTapTextInputAt(app: XCUIApplication, x: Double, y: Double) -> XCUIElement? {
|
|
31
|
+
switch probeTextInputs(app: app, point: CGPoint(x: x, y: y)) {
|
|
32
|
+
case .matches(let elements):
|
|
33
|
+
return elements.first
|
|
34
|
+
case .absent:
|
|
35
|
+
return nil
|
|
36
|
+
case .unavailable:
|
|
37
|
+
return nil
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func probeTextInputs(app: XCUIApplication, point: CGPoint) -> TextInputProbeOutcome {
|
|
42
|
+
precondition(Thread.isMainThread)
|
|
43
|
+
let issues = TextInputProbeIssues()
|
|
44
|
+
suppressedIssueLock.lock()
|
|
45
|
+
let previous = textInputProbeIssues
|
|
46
|
+
textInputProbeIssues = issues
|
|
47
|
+
suppressedIssueLock.unlock()
|
|
48
|
+
defer {
|
|
49
|
+
suppressedIssueLock.lock()
|
|
50
|
+
textInputProbeIssues = previous
|
|
51
|
+
suppressedIssueLock.unlock()
|
|
52
|
+
}
|
|
53
|
+
let (elements, exception) = catchingObjCException(fallback: []) {
|
|
54
|
+
queryTextInputs(app: app, point: point, shouldStop: { self.hasTextInputProbeIssues(issues) })
|
|
55
|
+
}
|
|
56
|
+
if hasTextInputProbeIssues(issues) { return .unavailable(.recordedIssue) }
|
|
57
|
+
if exception != nil { return .unavailable(.exception) }
|
|
58
|
+
return elements.isEmpty ? .absent : .matches(elements)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private func hasTextInputProbeIssues(_ scope: TextInputProbeIssues) -> Bool {
|
|
62
|
+
suppressedIssueLock.lock()
|
|
63
|
+
defer { suppressedIssueLock.unlock() }
|
|
64
|
+
return scope.count > 0
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func containTextInputProbeIssue(_ issue: XCTIssue) -> Bool {
|
|
68
|
+
suppressedIssueLock.lock()
|
|
69
|
+
guard let scope = textInputProbeIssues, scope.thread === Thread.current else {
|
|
70
|
+
suppressedIssueLock.unlock()
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
scope.count += 1
|
|
74
|
+
suppressedIssueLock.unlock()
|
|
75
|
+
NSLog("AGENT_DEVICE_RUNNER_TEXT_INPUT_PROBE_UNAVAILABLE issue=%@", issue.compactDescription)
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private func queryTextInputs(
|
|
80
|
+
app: XCUIApplication,
|
|
81
|
+
point: CGPoint,
|
|
82
|
+
shouldStop: () -> Bool
|
|
83
|
+
) -> [XCUIElement] {
|
|
84
|
+
var candidates: [XCUIElement] = []
|
|
85
|
+
for query in [app.textFields, app.secureTextFields, app.searchFields, app.textViews] {
|
|
86
|
+
if shouldStop() { break }
|
|
87
|
+
candidates.append(contentsOf: query.allElementsBoundByIndex)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
guard !shouldStop() else { return [] }
|
|
96
|
+
return candidates.filter { element in
|
|
97
|
+
guard !shouldStop(), element.exists else { return false }
|
|
98
|
+
return isCoordinateTextInputCandidate(enabled: element.isEnabled, frame: element.frame, point: point)
|
|
99
|
+
}.sorted(by: smallestElementFirst)
|
|
100
|
+
}
|
|
101
|
+
}
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import XCTest
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
5
|
extension RunnerTests {
|
|
6
6
|
func typeTextReliably(
|
|
7
7
|
app: XCUIApplication,
|
|
@@ -15,6 +15,36 @@ extension RunnerTests {
|
|
|
15
15
|
) -> TextEntryResult {
|
|
16
16
|
let totalStartedAt = Date()
|
|
17
17
|
guard !text.isEmpty else {
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if repairMode == .replacement {
|
|
23
|
+
guard let clearTarget = resolveTextEntryElement(app: app, target: target) else {
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
28
|
+
return TextEntryResult(
|
|
29
|
+
verified: nil,
|
|
30
|
+
repaired: false,
|
|
31
|
+
expectedText: "",
|
|
32
|
+
observedText: nil,
|
|
33
|
+
failure: .notFocused
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
clearTextInput(clearTarget)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
let observed = editableTextValue(for: clearTarget, treatingPlaceholderAsEmpty: true)
|
|
40
|
+
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
41
|
+
return TextEntryResult(
|
|
42
|
+
verified: observed.map { $0.isEmpty },
|
|
43
|
+
repaired: false,
|
|
44
|
+
expectedText: "",
|
|
45
|
+
observedText: observed
|
|
46
|
+
)
|
|
47
|
+
}
|
|
18
48
|
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
19
49
|
return TextEntryResult(verified: true, repaired: false, expectedText: "", observedText: "")
|
|
20
50
|
}
|
|
@@ -65,9 +95,9 @@ extension RunnerTests {
|
|
|
65
95
|
mode: repairMode
|
|
66
96
|
)
|
|
67
97
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
71
101
|
guard initialTarget != nil || (activeTarget.prefersFocusedElement && isKeyboardVisible(app: app)) else {
|
|
72
102
|
logTextEntryPhase(
|
|
73
103
|
commandId: commandId,
|
|
@@ -104,20 +134,20 @@ extension RunnerTests {
|
|
|
104
134
|
}
|
|
105
135
|
}
|
|
106
136
|
|
|
107
|
-
func typeIntoCurrentTarget(_ value: String) -> (element: XCUIElement?,
|
|
137
|
+
func typeIntoCurrentTarget(_ value: String) -> (element: XCUIElement?, failure: TextEntryFailure?) {
|
|
108
138
|
#if os(iOS)
|
|
109
139
|
if shouldUseSynthesizedFirstResponderType {
|
|
110
140
|
guard let currentTarget = resolveTextEntryElement(app: app, target: activeTarget) else {
|
|
111
|
-
return (nil,
|
|
141
|
+
return (nil, .notFocused)
|
|
112
142
|
}
|
|
113
143
|
textEntryRoute = "synthesized-first-responder"
|
|
114
144
|
NSLog("AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder")
|
|
115
145
|
let textBefore = editableTextValue(for: currentTarget, treatingPlaceholderAsEmpty: true)
|
|
116
146
|
switch synthesizer.enterText(app: app, text: value, replacingExistingText: false) {
|
|
117
147
|
case .continueTyping:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
awaitSynthesizedFirstResponderCommit(
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
let commit = awaitSynthesizedFirstResponderCommit(
|
|
121
151
|
app: app,
|
|
122
152
|
target: TextEntryTarget(
|
|
123
153
|
element: currentTarget,
|
|
@@ -128,9 +158,12 @@ extension RunnerTests {
|
|
|
128
158
|
textBefore: textBefore,
|
|
129
159
|
typedText: value
|
|
130
160
|
)
|
|
131
|
-
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
return (currentTarget, Self.textEntryFailure(forCommitOutcome: commit))
|
|
132
165
|
case .fallback:
|
|
133
|
-
return (nil,
|
|
166
|
+
return (nil, .synthesisUnavailable)
|
|
134
167
|
case .raise(let message):
|
|
135
168
|
NSException(
|
|
136
169
|
name: NSExceptionName.internalInconsistencyException,
|
|
@@ -142,7 +175,7 @@ extension RunnerTests {
|
|
|
142
175
|
if let currentTarget = resolveTextEntryElement(app: app, target: activeTarget) {
|
|
143
176
|
textEntryRoute = "xctest-element"
|
|
144
177
|
currentTarget.typeText(value)
|
|
145
|
-
return (currentTarget,
|
|
178
|
+
return (currentTarget, nil)
|
|
146
179
|
} else if activeTarget.prefersFocusedElement && isKeyboardVisible(app: app) {
|
|
147
180
|
#if os(iOS)
|
|
148
181
|
textEntryRoute = "synthesized-first-responder"
|
|
@@ -167,9 +200,9 @@ extension RunnerTests {
|
|
|
167
200
|
#else
|
|
168
201
|
app.typeText(value)
|
|
169
202
|
#endif
|
|
170
|
-
return (resolveTextEntryElement(app: app, target: activeTarget),
|
|
203
|
+
return (resolveTextEntryElement(app: app, target: activeTarget), nil)
|
|
171
204
|
}
|
|
172
|
-
return (nil,
|
|
205
|
+
return (nil, .notFocused)
|
|
173
206
|
}
|
|
174
207
|
|
|
175
208
|
func dispatchFailureResult(_ failure: TextEntryFailure) -> TextEntryResult {
|
|
@@ -203,8 +236,8 @@ extension RunnerTests {
|
|
|
203
236
|
let delayedTypeStartedAt = Date()
|
|
204
237
|
for (index, character) in characters.enumerated() {
|
|
205
238
|
let dispatch = typeIntoCurrentTarget(String(character))
|
|
206
|
-
|
|
207
|
-
return dispatchFailureResult(
|
|
239
|
+
if let failure = dispatch.failure {
|
|
240
|
+
return dispatchFailureResult(failure)
|
|
208
241
|
}
|
|
209
242
|
typedTarget = dispatch.element ?? typedTarget
|
|
210
243
|
if index + 1 < characters.count {
|
|
@@ -252,8 +285,8 @@ extension RunnerTests {
|
|
|
252
285
|
let firstCharacter = String(characters[0])
|
|
253
286
|
let firstStartedAt = Date()
|
|
254
287
|
let firstDispatch = typeIntoCurrentTarget(firstCharacter)
|
|
255
|
-
|
|
256
|
-
return dispatchFailureResult(
|
|
288
|
+
if let failure = firstDispatch.failure {
|
|
289
|
+
return dispatchFailureResult(failure)
|
|
257
290
|
}
|
|
258
291
|
var firstTypedTarget = firstDispatch.element
|
|
259
292
|
logTextEntryPhase(
|
|
@@ -281,8 +314,8 @@ extension RunnerTests {
|
|
|
281
314
|
let remainingText = String(characters.dropFirst())
|
|
282
315
|
let remainingStartedAt = Date()
|
|
283
316
|
let remainingDispatch = typeIntoCurrentTarget(remainingText)
|
|
284
|
-
|
|
285
|
-
return dispatchFailureResult(
|
|
317
|
+
if let failure = remainingDispatch.failure {
|
|
318
|
+
return dispatchFailureResult(failure)
|
|
286
319
|
}
|
|
287
320
|
firstTypedTarget = remainingDispatch.element ?? firstTypedTarget
|
|
288
321
|
logTextEntryPhase(
|
|
@@ -296,8 +329,8 @@ extension RunnerTests {
|
|
|
296
329
|
} else {
|
|
297
330
|
let typeStartedAt = Date()
|
|
298
331
|
let dispatch = typeIntoCurrentTarget(text)
|
|
299
|
-
|
|
300
|
-
return dispatchFailureResult(
|
|
332
|
+
if let failure = dispatch.failure {
|
|
333
|
+
return dispatchFailureResult(failure)
|
|
301
334
|
}
|
|
302
335
|
typedTarget = dispatch.element
|
|
303
336
|
logTextEntryPhase(
|