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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import XCTest
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
5
|
extension RunnerTests {
|
|
6
6
|
enum SynthesizedReplacementRouteOutcome {
|
|
7
7
|
case notApplicable
|
|
@@ -40,9 +40,14 @@ extension RunnerTests {
|
|
|
40
40
|
replacingExistingText: Bool
|
|
41
41
|
) -> SynthesizedTextEntryAction {
|
|
42
42
|
#if os(iOS)
|
|
43
|
+
let postStartedAt = Date()
|
|
43
44
|
let result = replacingExistingText
|
|
44
45
|
? RunnerSynthesizedTextEntry.replaceText(withApplication: app, text: text)
|
|
45
46
|
: RunnerSynthesizedTextEntry.synthesizeText(withApplication: app, text: text)
|
|
47
|
+
NSLog(
|
|
48
|
+
"[DEBUG-1874] synthesize posted %d chars status=%d tookMs=%.0f",
|
|
49
|
+
text.count, result.status.rawValue, postStartedAt.timeIntervalSinceNow * -1000
|
|
50
|
+
)
|
|
46
51
|
return Self.action(status: result.status, message: result.message)
|
|
47
52
|
#else
|
|
48
53
|
return .fallback
|
|
@@ -122,6 +127,17 @@ extension RunnerTests {
|
|
|
122
127
|
sleepFor(request.delaySeconds)
|
|
123
128
|
}
|
|
124
129
|
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
let commit = awaitSynthesizedReplacementCommit(
|
|
137
|
+
app: request.app,
|
|
138
|
+
target: request.target,
|
|
139
|
+
expectedText: request.text
|
|
140
|
+
)
|
|
125
141
|
logTextEntryPhase(
|
|
126
142
|
commandId: request.commandId,
|
|
127
143
|
phase: "total",
|
|
@@ -135,7 +151,8 @@ extension RunnerTests {
|
|
|
135
151
|
repaired: false,
|
|
136
152
|
expectedText: request.text,
|
|
137
153
|
observedText: nil,
|
|
138
|
-
textEntryRoute: "synthesized-first-responder-replacement"
|
|
154
|
+
textEntryRoute: "synthesized-first-responder-replacement",
|
|
155
|
+
failure: Self.textEntryFailure(forCommitOutcome: commit)
|
|
139
156
|
)
|
|
140
157
|
)
|
|
141
158
|
#else
|
|
@@ -165,12 +182,12 @@ extension RunnerTests {
|
|
|
165
182
|
case diverged
|
|
166
183
|
}
|
|
167
184
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
174
191
|
static func synthesizedTextCommitProgress(
|
|
175
192
|
observedText: String?,
|
|
176
193
|
expectedText: String
|
|
@@ -184,35 +201,140 @@ extension RunnerTests {
|
|
|
184
201
|
return expectedText.hasPrefix(observedText) ? .pending : .diverged
|
|
185
202
|
}
|
|
186
203
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
app: XCUIApplication,
|
|
196
|
-
target: TextEntryTarget,
|
|
197
|
-
textBefore: String?,
|
|
198
|
-
typedText: String
|
|
199
|
-
) {
|
|
200
|
-
guard let textBefore, !typedText.contains("\n"), !typedText.contains("\r") else {
|
|
201
|
-
return
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
static func commonPrefixLength(_ lhs: String, _ rhs: String) -> Int {
|
|
208
|
+
var length = 0
|
|
209
|
+
for (l, r) in zip(lhs, rhs) {
|
|
210
|
+
if l != r { break }
|
|
211
|
+
length += 1
|
|
202
212
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
return length
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
enum SynthesizedTextCommitOutcome: Equatable {
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
case settled
|
|
228
|
+
|
|
229
|
+
case unobservable
|
|
230
|
+
|
|
231
|
+
case notObserved
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
static func awaitSynthesizedCommitOutcome(
|
|
243
|
+
expectedText: String,
|
|
244
|
+
placeholder: String?,
|
|
245
|
+
stallBudget: TimeInterval = TextEntryTiming.synthesizedCommitStallTimeout,
|
|
246
|
+
ceiling: TimeInterval = TextEntryTiming.synthesizedCommitCeiling,
|
|
247
|
+
now: () -> Date = { Date() },
|
|
248
|
+
observe: () -> String?,
|
|
249
|
+
waitForNextObservation: () -> Void
|
|
250
|
+
) -> SynthesizedTextCommitOutcome {
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
if Self.textMatchesPlaceholder(expectedText, placeholder: placeholder) {
|
|
255
|
+
return .notObserved
|
|
256
|
+
}
|
|
257
|
+
var deadline = SynthesizedCommitDeadline(startedAt: now(), stallBudget: stallBudget, ceiling: ceiling)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
while true {
|
|
262
|
+
let observedText = observe()
|
|
263
|
+
switch synthesizedTextCommitProgress(observedText: observedText, expectedText: expectedText) {
|
|
211
264
|
case .committed, .diverged:
|
|
212
|
-
return
|
|
265
|
+
return .settled
|
|
213
266
|
case .pending:
|
|
214
|
-
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
let sampledAt = now()
|
|
270
|
+
deadline.record(
|
|
271
|
+
expectedPrefixLength: Self.commonPrefixLength(observedText ?? "", expectedText),
|
|
272
|
+
at: sampledAt
|
|
273
|
+
)
|
|
274
|
+
if deadline.isExpired(at: sampledAt) { return .notObserved }
|
|
275
|
+
waitForNextObservation()
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
static func textEntryFailure(
|
|
284
|
+
forCommitOutcome outcome: SynthesizedTextCommitOutcome
|
|
285
|
+
) -> TextEntryFailure? {
|
|
286
|
+
switch outcome {
|
|
287
|
+
case .settled, .unobservable:
|
|
288
|
+
return nil
|
|
289
|
+
case .notObserved:
|
|
290
|
+
return .commitNotObserved
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
static func awaitSynthesizedReplacementCommitOutcome(
|
|
311
|
+
expectedText: String,
|
|
312
|
+
placeholder: String?,
|
|
313
|
+
stallBudget: TimeInterval = TextEntryTiming.synthesizedCommitStallTimeout,
|
|
314
|
+
ceiling: TimeInterval = TextEntryTiming.synthesizedCommitCeiling,
|
|
315
|
+
now: () -> Date = { Date() },
|
|
316
|
+
observe: () -> String?,
|
|
317
|
+
waitForNextObservation: () -> Void
|
|
318
|
+
) -> SynthesizedTextCommitOutcome {
|
|
319
|
+
if Self.textMatchesPlaceholder(expectedText, placeholder: placeholder) {
|
|
320
|
+
return .notObserved
|
|
321
|
+
}
|
|
322
|
+
var deadline = SynthesizedCommitDeadline(startedAt: now(), stallBudget: stallBudget, ceiling: ceiling)
|
|
323
|
+
while true {
|
|
324
|
+
let observedText = observe()
|
|
325
|
+
if observedText == expectedText {
|
|
326
|
+
return .settled
|
|
215
327
|
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
let sampledAt = now()
|
|
332
|
+
deadline.record(
|
|
333
|
+
expectedPrefixLength: Self.commonPrefixLength(observedText ?? "", expectedText),
|
|
334
|
+
at: sampledAt
|
|
335
|
+
)
|
|
336
|
+
if deadline.isExpired(at: sampledAt) { return .notObserved }
|
|
337
|
+
waitForNextObservation()
|
|
216
338
|
}
|
|
217
339
|
}
|
|
218
340
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import XCTest
|
|
2
|
+
import AgentDeviceSnapshotPresentation
|
|
2
3
|
|
|
3
4
|
extension RunnerTests {
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
|
|
6
7
|
func blockingSystemAlertSnapshot(deadline: Date = .distantFuture) -> DataPayload? {
|
|
7
8
|
#if os(macOS)
|
|
@@ -41,8 +42,8 @@ extension RunnerTests {
|
|
|
41
42
|
nodes.append(actionNode)
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
|
|
46
47
|
let contentDeadline = deadline.addingTimeInterval(-0.5)
|
|
47
48
|
for content in informativeElements(in: modal, deadline: contentDeadline) {
|
|
48
49
|
guard Date() < contentDeadline,
|
|
@@ -85,7 +86,7 @@ extension RunnerTests {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
|
|
89
90
|
if Date() >= deadline {
|
|
90
91
|
NSLog("AGENT_DEVICE_RUNNER_SYSTEM_MODAL_PROBE_DEADLINE stage=sheets")
|
|
91
92
|
return nil
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import XCTest
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
6
|
extension RunnerTests {
|
|
7
7
|
enum TextEntryFailure: String {
|
|
8
8
|
case notFocused = "TEXT_INPUT_NOT_FOCUSED"
|
|
9
9
|
case synthesisUnavailable = "TEXT_INPUT_SYNTHESIS_UNAVAILABLE"
|
|
10
|
+
case commitNotObserved = "TEXT_INPUT_COMMIT_NOT_OBSERVED"
|
|
10
11
|
|
|
11
12
|
var message: String {
|
|
12
13
|
switch self {
|
|
@@ -14,6 +15,8 @@ extension RunnerTests {
|
|
|
14
15
|
return "No focused text input was available for typing."
|
|
15
16
|
case .synthesisUnavailable:
|
|
16
17
|
return "Reliable text synthesis is unavailable while the software keyboard is hidden."
|
|
18
|
+
case .commitNotObserved:
|
|
19
|
+
return "The runner could not confirm the typed text reached the field."
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -23,6 +26,8 @@ extension RunnerTests {
|
|
|
23
26
|
return "Focus a visible text input, then retry type or fill. If the input is not exposed by accessibility, use a coordinate focus command before typing."
|
|
24
27
|
case .synthesisUnavailable:
|
|
25
28
|
return "Show the software keyboard, then retry type or fill."
|
|
29
|
+
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 80. Do not use type, which appends to whatever committed."
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
}
|
|
@@ -40,7 +45,15 @@ extension RunnerTests {
|
|
|
40
45
|
static let pollInterval: TimeInterval = 0.02
|
|
41
46
|
static let warmupValueTimeout: TimeInterval = 0.4
|
|
42
47
|
static let verificationStabilityWindow: TimeInterval = 0.2
|
|
43
|
-
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
static let synthesizedCommitStallTimeout: TimeInterval = 3.0
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
static let synthesizedCommitCeiling: TimeInterval = 10.0
|
|
56
|
+
static let synthesizedCommitPollInterval: TimeInterval = 0.2
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
struct TextEntryResult {
|
|
@@ -101,14 +114,14 @@ extension RunnerTests {
|
|
|
101
114
|
}
|
|
102
115
|
|
|
103
116
|
func clearTextInput(_ element: XCUIElement) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
112
125
|
if let existing = editableTextValue(for: element, treatingPlaceholderAsEmpty: true),
|
|
113
126
|
existing.isEmpty {
|
|
114
127
|
return
|
|
@@ -121,211 +134,6 @@ extension RunnerTests {
|
|
|
121
134
|
element.typeText(deletes)
|
|
122
135
|
}
|
|
123
136
|
|
|
124
|
-
func focusedTextInput(app: XCUIApplication) -> XCUIElement? {
|
|
125
|
-
#if os(iOS)
|
|
126
|
-
// iOS focus predicates can return stale or misleading text-input matches
|
|
127
|
-
// under XCUITest, so text entry readiness is driven by tap/keyboard state.
|
|
128
|
-
return nil
|
|
129
|
-
#else
|
|
130
|
-
return safely("FOCUSED_INPUT_QUERY") {
|
|
131
|
-
let candidates = app
|
|
132
|
-
.descendants(matching: .any)
|
|
133
|
-
.matching(NSPredicate(format: "hasKeyboardFocus == 1"))
|
|
134
|
-
.allElementsBoundByIndex
|
|
135
|
-
for candidate in candidates where candidate.exists {
|
|
136
|
-
switch candidate.elementType {
|
|
137
|
-
case .textField, .secureTextField, .searchField, .textView:
|
|
138
|
-
return candidate
|
|
139
|
-
default:
|
|
140
|
-
continue
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return nil
|
|
144
|
-
}
|
|
145
|
-
#endif
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
func rememberTextEntryTap(_ element: XCUIElement?) {
|
|
149
|
-
guard let element, isTextEntryElement(element) else {
|
|
150
|
-
clearRememberedTextEntryTap()
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
textEntryTapWitness = TextEntryTapWitness(
|
|
154
|
-
element: element,
|
|
155
|
-
bundleId: currentBundleId,
|
|
156
|
-
processIdentifier: currentAppProcessIdentifier
|
|
157
|
-
)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
func clearRememberedTextEntryTap() {
|
|
161
|
-
textEntryTapWitness = nil
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private func rememberedTextEntryTarget() -> TextEntryTarget? {
|
|
165
|
-
guard let witness = textEntryTapWitness else {
|
|
166
|
-
return nil
|
|
167
|
-
}
|
|
168
|
-
// The tap is proof for one immediately-following bare type only. Consume it before checking
|
|
169
|
-
// the element so a failed or interrupted type cannot reuse stale focus evidence.
|
|
170
|
-
clearRememberedTextEntryTap()
|
|
171
|
-
guard witness.matches(
|
|
172
|
-
bundleId: currentBundleId,
|
|
173
|
-
processIdentifier: currentAppProcessIdentifier
|
|
174
|
-
) else {
|
|
175
|
-
return nil
|
|
176
|
-
}
|
|
177
|
-
let element = witness.element
|
|
178
|
-
// XCUIElement is query-backed rather than a stable node identity. A same-identifier field
|
|
179
|
-
// introduced by app-side navigation between tap and this immediate type can therefore
|
|
180
|
-
// re-resolve here; keep the witness one-shot and fail closed on every observable identity
|
|
181
|
-
// boundary instead of using frame equality, which would reject legitimate layout changes.
|
|
182
|
-
guard safely("LAST_TAPPED_TEXT_INPUT_EXISTS", false, { element.exists }) else {
|
|
183
|
-
return nil
|
|
184
|
-
}
|
|
185
|
-
// Keep the target scoped to the element that the preceding tap actually selected. Do not
|
|
186
|
-
// attach a refresh point: if that element disappeared, bare type must fail closed rather
|
|
187
|
-
// than rediscovering a different field or dispatching unscoped app.typeText.
|
|
188
|
-
return TextEntryTarget(
|
|
189
|
-
element: element,
|
|
190
|
-
refreshPoint: nil,
|
|
191
|
-
prefersFocusedElement: false,
|
|
192
|
-
fromTapWitness: true
|
|
193
|
-
)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
func stabilizeTextInputBeforeTyping(
|
|
197
|
-
app: XCUIApplication,
|
|
198
|
-
target: XCUIElement?,
|
|
199
|
-
keyboardVisibleBeforeTap: Bool? = nil
|
|
200
|
-
) -> TextEntryStabilization {
|
|
201
|
-
#if os(tvOS)
|
|
202
|
-
return TextEntryStabilization(element: target, focusConfirmed: true)
|
|
203
|
-
#else
|
|
204
|
-
let latest = target
|
|
205
|
-
let keyboardVisibleAtEntry = keyboardVisibleBeforeTap ?? isKeyboardVisible(app: app)
|
|
206
|
-
let deadline = Date().addingTimeInterval(TextEntryTiming.focusTimeout)
|
|
207
|
-
while Date() < deadline {
|
|
208
|
-
if let focused = focusedTextInput(app: app) {
|
|
209
|
-
return TextEntryStabilization(element: focused, focusConfirmed: true)
|
|
210
|
-
}
|
|
211
|
-
// focusedTextInput is intentionally nil on iOS; treat the keyboard transitioning to
|
|
212
|
-
// visible after our tap as the focus-moved signal. Don't fast-path when it was already up.
|
|
213
|
-
if keyboardBecameVisible(app: app, wasVisibleAtEntry: keyboardVisibleAtEntry) {
|
|
214
|
-
return TextEntryStabilization(element: latest, focusConfirmed: true)
|
|
215
|
-
}
|
|
216
|
-
sleepFor(TextEntryTiming.pollInterval)
|
|
217
|
-
}
|
|
218
|
-
return TextEntryStabilization(element: latest, focusConfirmed: false)
|
|
219
|
-
#endif
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
func focusTextInputForTextEntry(app: XCUIApplication, x: Double?, y: Double?) -> TextEntryTarget {
|
|
223
|
-
guard let x, let y else {
|
|
224
|
-
let softwareKeyboardVisible = isKeyboardVisible(app: app)
|
|
225
|
-
if !softwareKeyboardVisible, let rememberedTarget = rememberedTextEntryTarget() {
|
|
226
|
-
return rememberedTarget
|
|
227
|
-
}
|
|
228
|
-
// Bare `type` targets the current first responder. On iOS we intentionally do not trust
|
|
229
|
-
// `hasKeyboardFocus`, but an already-visible software keyboard is sufficient evidence that
|
|
230
|
-
// app.typeText has a receiver; waiting the full readiness timeout cannot prove a stronger
|
|
231
|
-
// target because there is no selector/coordinate focus move to validate.
|
|
232
|
-
if softwareKeyboardVisible {
|
|
233
|
-
return TextEntryTarget(
|
|
234
|
-
element: focusedTextInput(app: app),
|
|
235
|
-
refreshPoint: nil,
|
|
236
|
-
prefersFocusedElement: true
|
|
237
|
-
)
|
|
238
|
-
}
|
|
239
|
-
let focused = waitForTextEntryReadiness(
|
|
240
|
-
app: app,
|
|
241
|
-
target: TextEntryTarget(
|
|
242
|
-
element: focusedTextInput(app: app),
|
|
243
|
-
refreshPoint: nil,
|
|
244
|
-
prefersFocusedElement: true
|
|
245
|
-
)
|
|
246
|
-
)
|
|
247
|
-
return TextEntryTarget(element: focused, refreshPoint: nil, prefersFocusedElement: true)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
let keyboardVisibleBeforeTap = isKeyboardVisible(app: app)
|
|
251
|
-
let target = textInputAt(app: app, x: x, y: y)
|
|
252
|
-
let requestedPoint = CGPoint(x: x, y: y)
|
|
253
|
-
if let target {
|
|
254
|
-
let frame = target.frame
|
|
255
|
-
if !frame.isEmpty {
|
|
256
|
-
_ = tapAt(app: app, x: frame.midX, y: frame.midY)
|
|
257
|
-
} else {
|
|
258
|
-
_ = tapAt(app: app, x: x, y: y)
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
_ = tapAt(app: app, x: x, y: y)
|
|
262
|
-
}
|
|
263
|
-
// A visible keyboard is not enough evidence for app.typeText, because focus may still
|
|
264
|
-
// belong to a previous field. With a concrete target we type through XCUIElement.typeText,
|
|
265
|
-
// so after tapping it the iOS readiness timeout cannot prove anything stronger.
|
|
266
|
-
if keyboardVisibleBeforeTap, let target {
|
|
267
|
-
return TextEntryTarget(
|
|
268
|
-
element: target,
|
|
269
|
-
refreshPoint: textEntryRefreshPoint(for: target) ?? requestedPoint,
|
|
270
|
-
prefersFocusedElement: false
|
|
271
|
-
)
|
|
272
|
-
}
|
|
273
|
-
let stabilized = stabilizeTextInputBeforeTyping(
|
|
274
|
-
app: app,
|
|
275
|
-
target: target,
|
|
276
|
-
keyboardVisibleBeforeTap: keyboardVisibleBeforeTap
|
|
277
|
-
)
|
|
278
|
-
let readyTarget = TextEntryTarget(
|
|
279
|
-
element: stabilized.element ?? target,
|
|
280
|
-
refreshPoint: requestedPoint,
|
|
281
|
-
prefersFocusedElement: false
|
|
282
|
-
)
|
|
283
|
-
let concreteTargetReady = keyboardVisibleBeforeTap && readyTarget.element != nil
|
|
284
|
-
let element = stabilized.focusConfirmed || concreteTargetReady
|
|
285
|
-
? (stabilized.element ?? target)
|
|
286
|
-
: (waitForTextEntryReadiness(app: app, target: readyTarget) ?? stabilized.element ?? target)
|
|
287
|
-
return TextEntryTarget(
|
|
288
|
-
element: element,
|
|
289
|
-
refreshPoint: textEntryRefreshPoint(for: element) ?? requestedPoint,
|
|
290
|
-
prefersFocusedElement: false
|
|
291
|
-
)
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
func focusTextInputForTextEntry(app: XCUIApplication, element: XCUIElement) -> TextEntryTarget {
|
|
295
|
-
let point = textEntryRefreshPoint(for: element)
|
|
296
|
-
let keyboardVisibleBeforeTap = isKeyboardVisible(app: app)
|
|
297
|
-
if let point {
|
|
298
|
-
_ = tapAt(app: app, x: point.x, y: point.y)
|
|
299
|
-
}
|
|
300
|
-
// See the coordinate-target path above: direct element typing keeps this scoped to the
|
|
301
|
-
// tapped target, while the first-character warmup and final verify still catch dropped input.
|
|
302
|
-
if keyboardVisibleBeforeTap {
|
|
303
|
-
return TextEntryTarget(
|
|
304
|
-
element: element,
|
|
305
|
-
refreshPoint: textEntryRefreshPoint(for: element) ?? point,
|
|
306
|
-
prefersFocusedElement: false
|
|
307
|
-
)
|
|
308
|
-
}
|
|
309
|
-
let stabilized = stabilizeTextInputBeforeTyping(
|
|
310
|
-
app: app,
|
|
311
|
-
target: element,
|
|
312
|
-
keyboardVisibleBeforeTap: keyboardVisibleBeforeTap
|
|
313
|
-
)
|
|
314
|
-
let readyTarget = TextEntryTarget(
|
|
315
|
-
element: stabilized.element ?? element,
|
|
316
|
-
refreshPoint: point,
|
|
317
|
-
prefersFocusedElement: false
|
|
318
|
-
)
|
|
319
|
-
let resolved = stabilized.focusConfirmed
|
|
320
|
-
? (stabilized.element ?? element)
|
|
321
|
-
: (waitForTextEntryReadiness(app: app, target: readyTarget) ?? stabilized.element ?? element)
|
|
322
|
-
return TextEntryTarget(
|
|
323
|
-
element: resolved,
|
|
324
|
-
refreshPoint: textEntryRefreshPoint(for: resolved) ?? point,
|
|
325
|
-
prefersFocusedElement: false
|
|
326
|
-
)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
137
|
func isTextEntryElement(_ element: XCUIElement) -> Bool {
|
|
330
138
|
switch element.elementType {
|
|
331
139
|
case .textField, .secureTextField, .searchField, .textView:
|
|
@@ -369,103 +177,6 @@ extension RunnerTests {
|
|
|
369
177
|
return nil
|
|
370
178
|
}
|
|
371
179
|
|
|
372
|
-
private func waitForTextEntryReadiness(
|
|
373
|
-
app: XCUIApplication,
|
|
374
|
-
target: TextEntryTarget,
|
|
375
|
-
timeout: TimeInterval = TextEntryTiming.readinessTimeout
|
|
376
|
-
) -> XCUIElement? {
|
|
377
|
-
#if os(iOS)
|
|
378
|
-
var latest = resolveTextEntryElement(app: app, target: target)
|
|
379
|
-
let keyboardVisibleAtEntry = isKeyboardVisible(app: app)
|
|
380
|
-
let deadline = Date().addingTimeInterval(timeout)
|
|
381
|
-
let hardwareKeyboardFallback = Date().addingTimeInterval(
|
|
382
|
-
min(TextEntryTiming.hardwareKeyboardFallbackTimeout, timeout)
|
|
383
|
-
)
|
|
384
|
-
var sawSoftwareKeyboard = false
|
|
385
|
-
while Date() < deadline {
|
|
386
|
-
if let focused = focusedTextInput(app: app) {
|
|
387
|
-
latest = focused
|
|
388
|
-
if isKeyboardVisible(app: app) {
|
|
389
|
-
return focused
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
// Fast-path on a keyboard hidden->visible transition: our tapped field gained focus, so
|
|
393
|
-
// return immediately instead of burning the full readinessTimeout (warmup-first-char echo
|
|
394
|
-
// + post-type verify/repair remain as drop safety nets). When the keyboard was ALREADY up
|
|
395
|
-
// (back-to-back fills), this isn't a focus signal — fall through to the settle/timeout so
|
|
396
|
-
// text isn't sent to the previously-focused field.
|
|
397
|
-
if keyboardBecameVisible(app: app, wasVisibleAtEntry: keyboardVisibleAtEntry) {
|
|
398
|
-
return latest
|
|
399
|
-
}
|
|
400
|
-
sawSoftwareKeyboard = sawSoftwareKeyboard || keyboardElementExists(app: app)
|
|
401
|
-
if !sawSoftwareKeyboard && Date() >= hardwareKeyboardFallback && latest != nil {
|
|
402
|
-
return latest
|
|
403
|
-
}
|
|
404
|
-
sleepFor(TextEntryTiming.pollInterval)
|
|
405
|
-
}
|
|
406
|
-
return focusedTextInput(app: app) ?? latest
|
|
407
|
-
#else
|
|
408
|
-
return resolveTextEntryElement(app: app, target: target)
|
|
409
|
-
#endif
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
func waitForTextEntryReadinessAfterTap(app: XCUIApplication, element: XCUIElement) {
|
|
413
|
-
#if os(iOS)
|
|
414
|
-
switch element.elementType {
|
|
415
|
-
case .textField, .secureTextField, .searchField, .textView:
|
|
416
|
-
if waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout) != nil {
|
|
417
|
-
return
|
|
418
|
-
}
|
|
419
|
-
let frame = element.frame
|
|
420
|
-
if !frame.isEmpty {
|
|
421
|
-
_ = tapAt(app: app, x: frame.midX, y: frame.midY)
|
|
422
|
-
_ = waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout)
|
|
423
|
-
}
|
|
424
|
-
default:
|
|
425
|
-
return
|
|
426
|
-
}
|
|
427
|
-
#endif
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
private func waitForFocusedTextInput(app: XCUIApplication, timeout: TimeInterval) -> XCUIElement? {
|
|
431
|
-
let deadline = Date().addingTimeInterval(timeout)
|
|
432
|
-
while Date() < deadline {
|
|
433
|
-
if let focused = focusedTextInput(app: app) {
|
|
434
|
-
return focused
|
|
435
|
-
}
|
|
436
|
-
sleepFor(TextEntryTiming.pollInterval)
|
|
437
|
-
}
|
|
438
|
-
return focusedTextInput(app: app)
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
private func textEntryRefreshPoint(for element: XCUIElement?) -> CGPoint? {
|
|
442
|
-
guard let element else {
|
|
443
|
-
return nil
|
|
444
|
-
}
|
|
445
|
-
let frame = element.frame
|
|
446
|
-
guard !frame.isEmpty else {
|
|
447
|
-
return nil
|
|
448
|
-
}
|
|
449
|
-
return CGPoint(x: frame.midX, y: frame.midY)
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/// A focus-moved signal for iOS text entry, where `focusedTextInput` is intentionally nil.
|
|
453
|
-
/// The software keyboard TRANSITIONING from hidden (at entry) to visible means the field we
|
|
454
|
-
/// just tapped gained first-responder. If the keyboard was ALREADY up (e.g. back-to-back
|
|
455
|
-
/// fills into different fields), its visibility is not evidence focus moved to the new field,
|
|
456
|
-
/// so callers must keep waiting rather than typing into the previously-focused field.
|
|
457
|
-
private func keyboardBecameVisible(app: XCUIApplication, wasVisibleAtEntry: Bool) -> Bool {
|
|
458
|
-
return !wasVisibleAtEntry && isKeyboardVisible(app: app)
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
private func keyboardElementExists(app: XCUIApplication) -> Bool {
|
|
462
|
-
#if os(iOS)
|
|
463
|
-
return safely("KEYBOARD_EXISTS", false) { app.keyboards.firstMatch.exists }
|
|
464
|
-
#else
|
|
465
|
-
return false
|
|
466
|
-
#endif
|
|
467
|
-
}
|
|
468
|
-
|
|
469
180
|
private func moveCaretToEnd(element: XCUIElement) {
|
|
470
181
|
#if os(tvOS)
|
|
471
182
|
return
|
|
@@ -516,14 +227,13 @@ extension RunnerTests {
|
|
|
516
227
|
}
|
|
517
228
|
|
|
518
229
|
private func isPlaceholderValue(_ value: String, for element: XCUIElement) -> Bool {
|
|
230
|
+
if Self.textMatchesPlaceholder(value, placeholder: element.placeholderValue) {
|
|
231
|
+
return true
|
|
232
|
+
}
|
|
519
233
|
let normalizedValue = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
520
234
|
guard !normalizedValue.isEmpty else {
|
|
521
235
|
return false
|
|
522
236
|
}
|
|
523
|
-
let placeholder = element.placeholderValue?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
524
|
-
if !placeholder.isEmpty && normalizedValue == placeholder {
|
|
525
|
-
return true
|
|
526
|
-
}
|
|
527
237
|
if isGenericTextInputLabel(normalizedValue) {
|
|
528
238
|
return true
|
|
529
239
|
}
|
|
@@ -531,6 +241,13 @@ extension RunnerTests {
|
|
|
531
241
|
return normalizedLabel == normalizedValue && isGenericTextInputLabel(normalizedLabel)
|
|
532
242
|
}
|
|
533
243
|
|
|
244
|
+
static func textMatchesPlaceholder(_ text: String, placeholder: String?) -> Bool {
|
|
245
|
+
let normalizedText = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
246
|
+
guard !normalizedText.isEmpty else { return false }
|
|
247
|
+
let normalizedPlaceholder = placeholder?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
248
|
+
return !normalizedPlaceholder.isEmpty && normalizedText == normalizedPlaceholder
|
|
249
|
+
}
|
|
250
|
+
|
|
534
251
|
private func isGenericTextInputLabel(_ value: String) -> Bool {
|
|
535
252
|
switch value {
|
|
536
253
|
case "Text input field":
|