agent-device 0.21.23 → 0.21.25

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.
Files changed (435) hide show
  1. package/README.md +6 -6
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.apk → agent-device-android-ime-helper-0.21.25.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.25.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.manifest.json → agent-device-android-ime-helper-0.21.25.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.manifest.json +16 -0
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +12 -6
  9. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/RectResponseTests.swift +21 -0
  10. package/apple/snapshot-bridge/README.md +9 -7
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +159 -4
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerHttpRequestFraming.swift +139 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerPeer.swift +41 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerToken.swift +25 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +56 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +14 -5
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +18 -11
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +12 -0
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -1
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +1 -1
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +29 -5
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +0 -3
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +35 -13
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryConfirmation.swift +59 -26
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +19 -5
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +50 -106
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +142 -54
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +4 -1
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +21 -19
  31. package/dist/src/absence-observation-errors.js +1 -0
  32. package/dist/src/adapter.js +1 -1
  33. package/dist/src/adb-executor.js +2 -2
  34. package/dist/src/adb-failure.js +2 -2
  35. package/dist/src/adb.js +1 -1
  36. package/dist/src/agent-browser-lifecycle.js +1 -1
  37. package/dist/src/agent-browser-process-record.js +1 -1
  38. package/dist/src/agent-browser-provider.js +1 -1
  39. package/dist/src/agent-browser-tool.js +1 -1
  40. package/dist/src/agent-device-client.js +2 -2
  41. package/dist/src/alert.js +1 -1
  42. package/dist/src/android-adb.d.ts +3 -2
  43. package/dist/src/android-adb.js +1 -1
  44. package/dist/src/android-input-ownership.js +1 -1
  45. package/dist/src/android-system-surface-disclosure.js +1 -0
  46. package/dist/src/android-text-entry.js +1 -0
  47. package/dist/src/android.js +1 -1
  48. package/dist/src/app-backend.js +1 -1
  49. package/dist/src/app-helpers.js +1 -1
  50. package/dist/src/app-inventory.d.ts +4 -0
  51. package/dist/src/app-launch.js +1 -1
  52. package/dist/src/app-lifecycle.js +4 -3
  53. package/dist/src/app-lifecycle2.js +2 -2
  54. package/dist/src/app-log-files.js +1 -1
  55. package/dist/src/app-log-reconnect.js +1 -1
  56. package/dist/src/app-log-runtime2.js +3 -3
  57. package/dist/src/app-resolution-facade.js +1 -1
  58. package/dist/src/app-resolution.js +2 -2
  59. package/dist/src/app-state-runtime.d.ts +15 -0
  60. package/dist/src/apple-runner-platform.js +1 -1
  61. package/dist/src/application-lifecycle-interaction.js +1 -1
  62. package/dist/src/artifact-download.js +1 -1
  63. package/dist/src/auth.js +1 -1
  64. package/dist/src/aws-device-farm-connection.js +1 -0
  65. package/dist/src/back-mode.js +1 -1
  66. package/dist/src/backend-snapshot-options.js +1 -1
  67. package/dist/src/boot-diagnostics.js +1 -1
  68. package/dist/src/browserstack-connection.js +1 -0
  69. package/dist/src/capture-disclosure.js +1 -0
  70. package/dist/src/cli-config.js +1 -1
  71. package/dist/src/cli-help.js +36 -17
  72. package/dist/src/cli-output.js +1 -1
  73. package/dist/src/cli-runner.js +3 -1
  74. package/dist/src/cli.js +3 -4
  75. package/dist/src/client-companion-tunnel.js +1 -0
  76. package/dist/src/client-metro.js +1 -1
  77. package/dist/src/client-types.d.ts +15 -7
  78. package/dist/src/cloud-artifacts.d.ts +3 -2
  79. package/dist/src/code-signature-cache.js +1 -1
  80. package/dist/src/code-signature.js +1 -1
  81. package/dist/src/command-metadata.js +73 -1
  82. package/dist/src/command-policy.js +1 -0
  83. package/dist/src/command-schema.js +3 -3
  84. package/dist/src/command-surface.js +1 -1
  85. package/dist/src/command-tools.js +2 -2
  86. package/dist/src/connection-runtime.js +1 -1
  87. package/dist/src/connection-verification.js +1 -0
  88. package/dist/src/connection.js +5 -5
  89. package/dist/src/contracts.d.ts +1 -1
  90. package/dist/src/contracts.js +1 -1
  91. package/dist/src/daemon-client-lease-beat.js +1 -1
  92. package/dist/src/daemon-client-lifecycle.js +1 -1
  93. package/dist/src/daemon-client-liveness-probe.js +1 -1
  94. package/dist/src/daemon-policy-file.js +1 -1
  95. package/dist/src/daemon-registration-owner.js +1 -1
  96. package/dist/src/daemon-registration.js +1 -1
  97. package/dist/src/daemon-resolution.js +3 -1
  98. package/dist/src/debug-symbols-facade.js +1 -1
  99. package/dist/src/device-claim-inspection.js +1 -1
  100. package/dist/src/device-input-state.d.ts +6 -17
  101. package/dist/src/device-inventory-context.js +1 -1
  102. package/dist/src/device-readiness-runtime.js +1 -1
  103. package/dist/src/device-release.js +1 -1
  104. package/dist/src/device-selection-resolver.js +1 -1
  105. package/dist/src/device-shell.js +1 -1
  106. package/dist/src/device.js +3 -1
  107. package/dist/src/devicectl.js +1 -1
  108. package/dist/src/diagnostics.js +1 -1
  109. package/dist/src/doctor-facade.js +1 -1
  110. package/dist/src/durable-capture-resource.js +1 -1
  111. package/dist/src/durable-resource.js +1 -1
  112. package/dist/src/engine-eval-script.js +1 -1
  113. package/dist/src/error.js +1 -1
  114. package/dist/src/exec.js +1 -1
  115. package/dist/src/expo-dev-client-launch.js +1 -0
  116. package/dist/src/file.js +3 -1
  117. package/dist/src/find.js +1 -1
  118. package/dist/src/finders.js +1 -1
  119. package/dist/src/generic-settle.js +1 -1
  120. package/dist/src/generic.js +1 -1
  121. package/dist/src/gesture-admission.js +1 -1
  122. package/dist/src/gesture-plan-types.d.ts +2 -5
  123. package/dist/src/gesture-plan.js +1 -1
  124. package/dist/src/gesture-runtime.js +1 -1
  125. package/dist/src/harmonyos.js +1 -1
  126. package/dist/src/hdc.js +1 -1
  127. package/dist/src/helper.js +2 -2
  128. package/dist/src/human-control.js +1 -1
  129. package/dist/src/ime-rebind.js +1 -1
  130. package/dist/src/ime-state.js +1 -1
  131. package/dist/src/index.d.ts +4 -4
  132. package/dist/src/index.js +1 -1
  133. package/dist/src/input-actions.js +1 -1
  134. package/dist/src/input-actions2.js +2 -2
  135. package/dist/src/install-source-network-transport.js +1 -1
  136. package/dist/src/install-source2.js +1 -1
  137. package/dist/src/interaction-error.js +1 -0
  138. package/dist/src/interaction-positionals.js +1 -1
  139. package/dist/src/interaction.js +1 -1
  140. package/dist/src/interaction2.js +1 -1
  141. package/dist/src/interactor-operation-catalog.js +1 -1
  142. package/dist/src/interactor.js +5 -5
  143. package/dist/src/interactor2.js +1 -1
  144. package/dist/src/interactors.js +1 -1
  145. package/dist/src/internal/bin.js +1 -1
  146. package/dist/src/internal/daemon.js +5 -1
  147. package/dist/src/internal/png-worker.js +1 -1
  148. package/dist/src/inventory.js +2 -2
  149. package/dist/src/inventory2.js +1 -1
  150. package/dist/src/inventory6.js +1 -1
  151. package/dist/src/io.d.ts +2 -2
  152. package/dist/src/ios-client.js +1 -1
  153. package/dist/src/ios-settings.js +1 -1
  154. package/dist/src/ios-snapshot-acquisition.js +1 -1
  155. package/dist/src/ios-snapshot-adapter.js +1 -1
  156. package/dist/src/ios-snapshot-engine.js +1 -1
  157. package/dist/src/ios-snapshot-runtime.js +1 -1
  158. package/dist/src/keyed-lock.js +1 -1
  159. package/dist/src/launch-confirmation.js +1 -1
  160. package/dist/src/lease.js +1 -1
  161. package/dist/src/limrun-runtime-dependencies.js +1 -1
  162. package/dist/src/limrun.d.ts +5 -564
  163. package/dist/src/limrun.js +1 -1
  164. package/dist/src/linux.js +1 -1
  165. package/dist/src/load.js +1 -1
  166. package/dist/src/local-interactor-operation-set.js +1 -1
  167. package/dist/src/log-stream.js +9 -9
  168. package/dist/src/mechanics.js +16 -16
  169. package/dist/src/metro.js +1 -1
  170. package/dist/src/metro2.js +1 -1
  171. package/dist/src/mobile-snapshot-semantics.js +1 -1
  172. package/dist/src/observability.js +1 -1
  173. package/dist/src/observation.js +1 -2
  174. package/dist/src/open-target-resolution.js +1 -1
  175. package/dist/src/output-path.js +1 -1
  176. package/dist/src/overlay.js +1 -3
  177. package/dist/src/perf-facade.js +1 -1
  178. package/dist/src/perf-runtime-operation-builder.js +1 -1
  179. package/dist/src/perf-runtime.js +1 -1
  180. package/dist/src/perf-target.js +1 -1
  181. package/dist/src/physical-device-control.js +1 -1
  182. package/dist/src/platform-request-scope.js +1 -1
  183. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  184. package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
  185. package/dist/src/platform-runtime-apple-resources.js +1 -0
  186. package/dist/src/platform-runtime-claim-recovery.js +1 -0
  187. package/dist/src/platform-runtime-daemon-services.js +1 -0
  188. package/dist/src/platform-runtime-host.js +1 -1
  189. package/dist/src/platform-runtime-network-web-transport.js +1 -1
  190. package/dist/src/platform-runtime-open-target.js +1 -1
  191. package/dist/src/platform-runtime-operation-host.js +4 -4
  192. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  193. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  194. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  195. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  196. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  197. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
  198. package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
  199. package/dist/src/platform-runtime-unavailable.js +1 -1
  200. package/dist/src/platform-runtime.js +1 -1
  201. package/dist/src/platform-runtime2.js +1 -1
  202. package/dist/src/plugin.js +1 -0
  203. package/dist/src/plugins/webdriver.d.ts +111 -0
  204. package/dist/src/plugins/webdriver.js +1 -0
  205. package/dist/src/plugins.d.ts +2 -1
  206. package/dist/src/plugins2.js +1 -1
  207. package/dist/src/png-crop-bytes.js +1 -1
  208. package/dist/src/png-resize.js +1 -0
  209. package/dist/src/png-worker-client.js +1 -1
  210. package/dist/src/png-worker-contract.js +1 -1
  211. package/dist/src/process-entry.js +1 -1
  212. package/dist/src/process-exit.js +1 -1
  213. package/dist/src/process.js +1 -1
  214. package/dist/src/provider-credential-fingerprint.js +1 -1
  215. package/dist/src/provider-device-admission.js +1 -1
  216. package/dist/src/provider-device-runtime.d.ts +556 -0
  217. package/dist/src/provider-policy.js +1 -0
  218. package/dist/src/provider-profile-fields.js +1 -1
  219. package/dist/src/provider-webdriver.js +1 -2
  220. package/dist/src/proxy.js +2 -2
  221. package/dist/src/quality-warnings.js +1 -1
  222. package/dist/src/react-devtools.js +2 -0
  223. package/dist/src/react-native-overlay2.js +3 -0
  224. package/dist/src/react-native.js +1 -1
  225. package/dist/src/record-runtime.js +1 -1
  226. package/dist/src/record-trace.js +1 -1
  227. package/dist/src/recording.js +2 -2
  228. package/dist/src/register-builtins.js +1 -1
  229. package/dist/src/remote-bridge.js +1 -0
  230. package/dist/src/remote-config-core.js +1 -0
  231. package/dist/src/remote-config.js +1 -1
  232. package/dist/src/remote-config2.js +1 -1
  233. package/dist/src/replay-backend-registry.js +1 -0
  234. package/dist/src/replay-divergence.js +1 -1
  235. package/dist/src/replay-maestro-backend.js +117 -0
  236. package/dist/src/replay-script-selection.js +1 -0
  237. package/dist/src/replay.js +1 -3
  238. package/dist/src/replay2.js +1 -0
  239. package/dist/src/reporting.js +3 -3
  240. package/dist/src/request-cancel.js +1 -1
  241. package/dist/src/request-providers.js +1 -1
  242. package/dist/src/request-runtime-binding.js +1 -1
  243. package/dist/src/result-serialization.js +1 -1
  244. package/dist/src/retry.js +1 -1
  245. package/dist/src/retry2.js +1 -0
  246. package/dist/src/runner-artifact-manifest.js +1 -1
  247. package/dist/src/runner-cache-retention.js +1 -0
  248. package/dist/src/runner-cache-trim.js +1 -0
  249. package/dist/src/runner-client.js +1 -1
  250. package/dist/src/runner-dev-tools-security.js +1 -1
  251. package/dist/src/runner-device-readiness.js +1 -1
  252. package/dist/src/runner-device-set.js +1 -0
  253. package/dist/src/runner-error-classification.js +3 -3
  254. package/dist/src/runner-exchange.js +1 -1
  255. package/dist/src/runner-lease.js +1 -0
  256. package/dist/src/runner-operations-facade.js +1 -1
  257. package/dist/src/runner-retention.js +1 -0
  258. package/dist/src/runner-start-budget.js +1 -1
  259. package/dist/src/runner-startup-transport.js +1 -0
  260. package/dist/src/runner-toolchain-probe.js +2 -0
  261. package/dist/src/runner.js +2 -1
  262. package/dist/src/runtime-command-surface.js +1 -0
  263. package/dist/src/runtime-deployment.js +1 -0
  264. package/dist/src/runtime-factory.js +1 -0
  265. package/dist/src/runtime-session.js +1 -0
  266. package/dist/src/runtime-transport-hints.js +1 -1
  267. package/dist/src/runtime.js +2 -1
  268. package/dist/src/runtime10.js +2 -2
  269. package/dist/src/runtime2.js +4 -4
  270. package/dist/src/runtime3.js +1 -1
  271. package/dist/src/runtime4.js +5 -5
  272. package/dist/src/runtime5.js +1 -1
  273. package/dist/src/runtime6.js +1 -1
  274. package/dist/src/runtime7.js +1 -1
  275. package/dist/src/runtime8.js +1 -1
  276. package/dist/src/runtime9.js +1 -1
  277. package/dist/src/screen-recording-transport.js +1 -1
  278. package/dist/src/screenshot-density.js +1 -1
  279. package/dist/src/screenshot-image.js +1 -1
  280. package/dist/src/screenshot-runtime.js +1 -1
  281. package/dist/src/screenshot3.js +5 -5
  282. package/dist/src/sdk-batch-runner.js +2 -2
  283. package/dist/src/sdk-batch.js +2 -2
  284. package/dist/src/sdk-contracts.d.ts +20 -29
  285. package/dist/src/sdk-contracts.js +2 -2
  286. package/dist/src/sdk-device.js +1 -1
  287. package/dist/src/sdk-finders.d.ts +1 -1
  288. package/dist/src/sdk-finders.js +1 -1
  289. package/dist/src/sdk-io.d.ts +4 -2
  290. package/dist/src/sdk-remote-config.d.ts +4 -0
  291. package/dist/src/sdk-remote-config.js +1 -1
  292. package/dist/src/sdk-selectors.d.ts +5 -6
  293. package/dist/src/sdk-selectors.js +1 -1
  294. package/dist/src/selection.js +0 -0
  295. package/dist/src/selector-pipeline-policy.js +1 -1
  296. package/dist/src/selector-runtime.js +1 -1
  297. package/dist/src/selectors.js +1 -1
  298. package/dist/src/server.js +2 -2
  299. package/dist/src/session-allocation.js +1 -1
  300. package/dist/src/session-replay-runtime-failure-response.js +1 -0
  301. package/dist/src/session-runtime-admission.js +1 -1
  302. package/dist/src/session.js +1 -1
  303. package/dist/src/session2.js +5 -5
  304. package/dist/src/settings.js +1 -1
  305. package/dist/src/settings2.js +1 -1
  306. package/dist/src/simctl-settings.js +1 -1
  307. package/dist/src/simctl.js +1 -1
  308. package/dist/src/simulator-boot.js +1 -1
  309. package/dist/src/simulator-state.js +1 -1
  310. package/dist/src/simulator.js +1 -1
  311. package/dist/src/snapshot-capture-annotations.js +1 -1
  312. package/dist/src/snapshot-chrome.js +1 -0
  313. package/dist/src/snapshot-desktop-projection.js +1 -1
  314. package/dist/src/snapshot-evidence.js +1 -0
  315. package/dist/src/snapshot-node-lookup.js +1 -0
  316. package/dist/src/snapshot-occlusion.js +1 -0
  317. package/dist/src/snapshot-quality-verdict.js +1 -0
  318. package/dist/src/snapshot-runtime-binding.js +1 -1
  319. package/dist/src/snapshot-runtime.js +1 -1
  320. package/dist/src/snapshot-state.js +1 -1
  321. package/dist/src/snapshot.js +1 -1
  322. package/dist/src/snapshot2.js +1 -1
  323. package/dist/src/snapshot3.js +1 -1
  324. package/dist/src/src.js +5 -1
  325. package/dist/src/src2.js +1 -1
  326. package/dist/src/src3.js +2 -1
  327. package/dist/src/store.js +1 -1
  328. package/dist/src/surface-snapshot2.js +1 -1
  329. package/dist/src/target-evidence-tree.js +1 -0
  330. package/dist/src/target-evidence.js +1 -1
  331. package/dist/src/text-entry-focus.js +1 -1
  332. package/dist/src/tool-provider2.js +1 -1
  333. package/dist/src/touch-runtime.js +1 -1
  334. package/dist/src/touch-runtime2.js +1 -1
  335. package/dist/src/tree.js +1 -1
  336. package/dist/src/tv-remote.js +1 -1
  337. package/dist/src/type-text-runtime.js +1 -1
  338. package/dist/src/undici.js +8 -8
  339. package/dist/src/update-check.js +1 -1
  340. package/dist/src/vars.js +1 -1
  341. package/dist/src/version.js +1 -1
  342. package/dist/src/video.js +2 -2
  343. package/dist/src/wait.js +1 -0
  344. package/dist/src/web.js +1 -1
  345. package/dist/src/web2.js +1 -1
  346. package/package.json +22 -19
  347. package/server.json +2 -2
  348. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.23.apk.sha256 +0 -1
  349. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk +0 -0
  350. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk.sha256 +0 -1
  351. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.manifest.json +0 -16
  352. package/dist/src/adb-transport.js +0 -1
  353. package/dist/src/alert-runtime.js +0 -1
  354. package/dist/src/app-deployment-resolution.js +0 -2
  355. package/dist/src/app-inventory-contract.js +0 -1
  356. package/dist/src/app-log-session-resource.js +0 -1
  357. package/dist/src/application-lifecycle-runtime.js +0 -1
  358. package/dist/src/auth-session.js +0 -1
  359. package/dist/src/cache.js +0 -1
  360. package/dist/src/capabilities.js +0 -1
  361. package/dist/src/capture.js +0 -1
  362. package/dist/src/catalog.js +0 -1
  363. package/dist/src/click-button.js +0 -1
  364. package/dist/src/client-metro-companion.js +0 -1
  365. package/dist/src/client-options.js +0 -3
  366. package/dist/src/compatibility-policy.js +0 -1
  367. package/dist/src/daemon-artifacts.js +0 -1
  368. package/dist/src/daemon-client-transport.js +0 -1
  369. package/dist/src/daemon-http.js +0 -1
  370. package/dist/src/device-claim-rule.js +0 -1
  371. package/dist/src/device-rotation.js +0 -1
  372. package/dist/src/device-session.js +0 -3
  373. package/dist/src/device2.js +0 -1
  374. package/dist/src/device3.js +0 -3
  375. package/dist/src/dispatch-resolve.js +0 -4
  376. package/dist/src/format.js +0 -1
  377. package/dist/src/gesture-plan-types.js +0 -1
  378. package/dist/src/host.js +0 -1
  379. package/dist/src/human-control-contract.js +0 -1
  380. package/dist/src/interaction-ref-policy.js +0 -1
  381. package/dist/src/interactor-operation-binding.js +0 -1
  382. package/dist/src/keyboard-actions.js +0 -1
  383. package/dist/src/lease-context.js +0 -1
  384. package/dist/src/lease-registry-scope.js +0 -1
  385. package/dist/src/lease-scope.js +0 -1
  386. package/dist/src/managed-device-scope.js +0 -1
  387. package/dist/src/observe-until.js +0 -1
  388. package/dist/src/output-common.js +0 -5
  389. package/dist/src/owner-identity.js +0 -3
  390. package/dist/src/path-resolution.js +0 -1
  391. package/dist/src/perf-runtime-plan.js +0 -1
  392. package/dist/src/platform-runtime-app-log-process.js +0 -1
  393. package/dist/src/platform-runtime-managed-owner.js +0 -1
  394. package/dist/src/platform-runtime-screen-recording-process-host.js +0 -1
  395. package/dist/src/png.js +0 -1
  396. package/dist/src/prepare-kind.js +0 -1
  397. package/dist/src/provider-device-runtimes.js +0 -1
  398. package/dist/src/provider-session-ownership.js +0 -2
  399. package/dist/src/providers.js +0 -1
  400. package/dist/src/registry.js +0 -68
  401. package/dist/src/request-admission.js +0 -1
  402. package/dist/src/request-cancellation.js +0 -1
  403. package/dist/src/request-progress-protocol.js +0 -1
  404. package/dist/src/runner-cache-metadata.js +0 -3
  405. package/dist/src/runner-disposal.js +0 -1
  406. package/dist/src/runner-session-types.js +0 -1
  407. package/dist/src/runtime-admission.js +0 -1
  408. package/dist/src/screen-recording-admission-ledger.js +0 -1
  409. package/dist/src/screen-recording-resource-recovery.js +0 -1
  410. package/dist/src/screenshot-result.js +0 -1
  411. package/dist/src/script.js +0 -1
  412. package/dist/src/scroll-command.js +0 -1
  413. package/dist/src/scroll-gesture.js +0 -1
  414. package/dist/src/scroll-indicator.js +0 -1
  415. package/dist/src/session-artifact-paths.js +0 -1
  416. package/dist/src/session-paths.js +0 -1
  417. package/dist/src/session-repair-tombstone.js +0 -1
  418. package/dist/src/session-routing.js +0 -1
  419. package/dist/src/session-snapshot.js +0 -1
  420. package/dist/src/snapshot4.js +0 -1
  421. package/dist/src/src4.js +0 -1
  422. package/dist/src/src5.js +0 -1
  423. package/dist/src/src6.js +0 -1
  424. package/dist/src/src7.js +0 -2
  425. package/dist/src/src8.js +0 -115
  426. package/dist/src/string-enum.js +0 -1
  427. package/dist/src/success-text.js +0 -1
  428. package/dist/src/timeouts.js +0 -1
  429. package/dist/src/touch-reference-frame.js +0 -1
  430. package/dist/src/transport.js +0 -3
  431. package/dist/src/ttl-memo.js +0 -1
  432. package/dist/src/verified-file.js +0 -1
  433. package/dist/src/viewport.js +0 -1
  434. package/dist/src/window-state.js +0 -1
  435. /package/dist/src/{doctor-output.js → doctor-lines.js} +0 -0
@@ -114,6 +114,7 @@ extension RunnerTests {
114
114
  let app: XCUIApplication
115
115
 
116
116
  var systemSurface: SystemSurfaceHost? = nil
117
+ var observation: SnapshotObservationPayload? = nil
117
118
  }
118
119
 
119
120
  enum ActiveCommandPreparation {
@@ -494,6 +495,26 @@ extension RunnerTests {
494
495
  command: Command,
495
496
  routeToSpringboard: Bool = false
496
497
  ) -> ActiveCommandPreparation {
498
+ if command.command == .snapshot, command.observeOnly == true {
499
+ #if os(iOS)
500
+ guard command.appBundleId?.trimmedNonEmpty != nil else {
501
+ return .response(observeOnlyUnavailableResponse())
502
+ }
503
+ let observedApp = resolveAppWithoutActivation(command: command)
504
+ let reportedState = observedApp.state
505
+ guard reportedState == .runningForeground else {
506
+ return .response(observeOnlyUnavailableResponse())
507
+ }
508
+ return .context(ActiveCommandContext(
509
+ app: observedApp,
510
+ observation: SnapshotObservationPayload(appState: Self.applicationStateName(reportedState))
511
+ ))
512
+ #else
513
+ return .response(Response(ok: false, error: ErrorPayload(
514
+ code: "UNSUPPORTED_OPERATION", message: "observe-only snapshot is supported on iOS and iPadOS only"
515
+ )))
516
+ #endif
517
+ }
497
518
  if routeToSpringboard {
498
519
  return .context(ActiveCommandContext(app: springboard))
499
520
  }
@@ -516,11 +537,26 @@ extension RunnerTests {
516
537
 
517
538
 
518
539
 
540
+
541
+
519
542
  return prepareActivatedTarget(command: command)
520
543
  #endif
521
544
  case .existingApp:
522
545
 
523
546
 
547
+ #if os(macOS)
548
+ if let bundleId = command.appBundleId?.trimmedNonEmpty,
549
+ macReadMayBeServedInBackground(
550
+ command: command,
551
+ targetState: XCUIApplication(bundleIdentifier: bundleId).state
552
+ )
553
+ {
554
+
555
+
556
+ refreshCachedTargetIfProcessChanged(bundleId: bundleId)
557
+ return .context(ActiveCommandContext(app: resolveAppWithoutActivation(command: command)))
558
+ }
559
+ #endif
524
560
  return prepareActivatedTarget(command: command)
525
561
  case .mayLaunch:
526
562
  if shouldSkipAppActivationPreflight(command) {
@@ -644,6 +680,14 @@ extension RunnerTests {
644
680
  return XCUIApplication(bundleIdentifier: host.bundleId).state
645
681
  }
646
682
 
683
+ func observeOnlyUnavailableResponse() -> Response {
684
+ Response(ok: false, error: ErrorPayload(
685
+ code: "OBSERVATION_UNAVAILABLE",
686
+ message: "The session app cannot be observed without activation.",
687
+ hint: "XCUIApplication must report runningForeground before and after capture. This state report does not prove screen ownership (#2696)."
688
+ ))
689
+ }
690
+
647
691
  func currentXCTestFailureCount() -> Int {
648
692
  return testRun?.failureCount ?? 0
649
693
  }
@@ -746,4 +790,16 @@ extension RunnerTests {
746
790
  }
747
791
  return XCUIApplication(bundleIdentifier: bundleId)
748
792
  }
793
+
794
+
795
+
796
+
797
+
798
+
799
+
800
+
801
+
802
+ func macReadMayBeServedInBackground(command: Command, targetState: XCUIApplication.State) -> Bool {
803
+ command.appBundleId?.trimmedNonEmpty != nil && targetState == .runningBackground
804
+ }
749
805
  }
@@ -429,17 +429,26 @@ extension RunnerTests {
429
429
  case .screenshot:
430
430
  #if os(macOS)
431
431
 
432
- if let bundleId = command.appBundleId, !bundleId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
432
+
433
+
434
+
435
+ let screenshotBundleId = command.appBundleId?.trimmedNonEmpty
436
+ if let bundleId = screenshotBundleId {
433
437
  let targetApp = XCUIApplication(bundleIdentifier: bundleId)
434
- targetApp.activate()
435
- activeApp = targetApp
438
+ if macAppCaptureNeedsRaise(
439
+ fullscreen: command.fullscreen,
440
+ targetState: targetApp.state
441
+ ) {
442
+ targetApp.activate()
436
443
 
437
- sleepFor(0.5)
444
+ sleepFor(0.5)
445
+ }
446
+ activeApp = targetApp
438
447
  }
439
448
  let screenshot: XCUIScreenshot
440
449
  if command.fullscreen == true {
441
450
  screenshot = XCUIScreen.main.screenshot()
442
- } else if let bundleId = command.appBundleId, !bundleId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
451
+ } else if screenshotBundleId != nil {
443
452
  screenshot = screenshotRoot(app: activeApp).screenshot()
444
453
  } else {
445
454
  screenshot = XCUIScreen.main.screenshot()
@@ -1,18 +1,25 @@
1
1
  import Foundation
2
+ import Network
2
3
 
3
4
 
4
5
 
5
- enum RunnerEnv {
6
- static func resolvePort() -> UInt16 {
7
- if let env = ProcessInfo.processInfo.environment["AGENT_DEVICE_RUNNER_PORT"], let port = UInt16(env) {
8
- return port
9
- }
10
- for arg in CommandLine.arguments {
11
- if arg.hasPrefix("AGENT_DEVICE_RUNNER_PORT=") {
12
- let value = arg.replacingOccurrences(of: "AGENT_DEVICE_RUNNER_PORT=", with: "")
13
- if let port = UInt16(value) { return port }
14
- }
6
+
7
+
8
+
9
+ struct RunnerListenerConfiguration {
10
+ let port: NWEndpoint.Port
11
+ let token: RunnerListenerToken
12
+
13
+ static func fromEnvironment(
14
+ _ environment: [String: String] = ProcessInfo.processInfo.environment
15
+ ) -> RunnerListenerConfiguration? {
16
+ guard
17
+ let rawPort = environment["AGENT_DEVICE_RUNNER_PORT"].flatMap({ UInt16($0) }), rawPort > 0,
18
+ let port = NWEndpoint.Port(rawValue: rawPort),
19
+ let token = RunnerListenerToken(environment["AGENT_DEVICE_RUNNER_TOKEN"])
20
+ else {
21
+ return nil
15
22
  }
16
- return 0
23
+ return RunnerListenerConfiguration(port: port, token: token)
17
24
  }
18
25
  }
@@ -284,6 +284,14 @@ extension RunnerTests {
284
284
  return false
285
285
  }
286
286
 
287
+
288
+
289
+
290
+ func macAppCaptureNeedsRaise(fullscreen: Bool?, targetState: XCUIApplication.State) -> Bool {
291
+ guard targetState != .runningForeground else { return false }
292
+ return fullscreen != true || targetState == .notRunning
293
+ }
294
+
287
295
  @MainActor
288
296
  func canUseFastForegroundAppGuard(
289
297
  activeApp: XCUIApplication,
@@ -66,6 +66,9 @@ enum CommandLaunchPolicy: Equatable {
66
66
 
67
67
 
68
68
 
69
+
70
+
71
+
69
72
  case existingApp
70
73
 
71
74
  case mayLaunch
@@ -239,6 +242,7 @@ struct Command: Codable {
239
242
  let interactiveOnly: Bool?
240
243
  let preferredBackend: String?
241
244
  let customActions: Bool?
245
+ let observeOnly: Bool?
242
246
  let depth: Int?
243
247
  let scope: String?
244
248
  let raw: Bool?
@@ -488,6 +492,7 @@ struct DataPayload: Codable {
488
492
  var failedStepIndex: Int?
489
493
  var sequenceResults: [SequenceStepResult]?
490
494
  var targetActivation: TargetActivationFactPayload?
495
+ var observation: SnapshotObservationPayload?
491
496
 
492
497
 
493
498
  var screenshotMetadata: ScreenshotMetadataPayload?
@@ -529,6 +534,13 @@ struct SystemSurfaceProvenancePayload: Codable {
529
534
  let kind: String
530
535
  }
531
536
 
537
+ struct SnapshotObservationPayload: Codable {
538
+ var mode = "observe-only"
539
+ var activationPerformed = false
540
+ let appState: String
541
+ var appStateSource = "xcuiapplication-state"
542
+ }
543
+
532
544
  struct SnapshotQualityPayload: Codable {
533
545
  let nodes: [PresentedNode]
534
546
  let truncated: Bool
@@ -3,6 +3,8 @@ import XCTest
3
3
 
4
4
  extension RunnerTests {
5
5
  static let navigationBackKeywords = ["back", "close", "cancel"]
6
+ static let systemBackButtonIdentifier = "BackButton"
7
+ static let floatingBarBackControlMaxYFraction: CGFloat = 0.4
6
8
  static let navigationFallbackVerificationDelay: TimeInterval = 0.25
7
9
 
8
10
 
@@ -88,7 +90,11 @@ extension RunnerTests {
88
90
  let candidates = app.buttons.matching(Self.navigationBackPredicate()).allElementsBoundByIndex.compactMap {
89
91
  element -> (XCUIElement, Int)? in
90
92
  guard element.exists, element.isHittable else { return nil }
91
- guard Self.isTopNavigationControlFrame(element.frame, in: frame) else { return nil }
93
+ guard Self.isTopNavigationBackCandidateFrame(
94
+ element.frame,
95
+ in: frame,
96
+ identifier: element.identifier
97
+ ) else { return nil }
92
98
  guard let rank = Self.navigationBackControlRank(
93
99
  label: element.label,
94
100
  identifier: element.identifier
@@ -132,6 +138,24 @@ extension RunnerTests {
132
138
  return candidate.midY >= window.minY && candidate.midY <= maxY
133
139
  }
134
140
 
141
+
142
+
143
+
144
+ static func isTopNavigationBackCandidateFrame(
145
+ _ candidate: CGRect,
146
+ in window: CGRect,
147
+ identifier: String
148
+ ) -> Bool {
149
+ if isTopNavigationControlFrame(candidate, in: window) { return true }
150
+ guard identifier == systemBackButtonIdentifier,
151
+ SnapshotGeometry.isPositiveFinite(candidate), SnapshotGeometry.isPositiveFinite(window)
152
+ else {
153
+ return false
154
+ }
155
+ let maxY = window.minY + window.height * floatingBarBackControlMaxYFraction
156
+ return candidate.midY >= window.minY && candidate.midY <= maxY
157
+ }
158
+
135
159
  static func topLeadingNavigationFallbackPoint(in frame: CGRect) -> CGPoint? {
136
160
  guard SnapshotGeometry.isPositiveFinite(frame) else {
137
161
  return nil
@@ -17,7 +17,7 @@ struct SnapshotCaptureTarget {
17
17
 
18
18
  enum SnapshotCommandPreparation {
19
19
  case response(Response)
20
- case capture(SnapshotCaptureTarget, systemSurface: SystemSurfaceHost?)
20
+ case capture(SnapshotCaptureTarget, systemSurface: SystemSurfaceHost?, observation: SnapshotObservationPayload?)
21
21
  }
22
22
 
23
23
 
@@ -19,19 +19,27 @@ extension RunnerTests {
19
19
  return .response(response)
20
20
  case .context(let context):
21
21
  return .capture(
22
- self.takeSnapshotCaptureTarget(app: context.app),
23
- systemSurface: context.systemSurface
22
+ context.observation == nil
23
+ ? self.takeSnapshotCaptureTarget(app: context.app)
24
+ : SnapshotCaptureTarget(
25
+ app: context.app,
26
+ bundleId: command.appBundleId?.trimmedNonEmpty,
27
+ processIdentifier: Self.processIdentifier(of: context.app)
28
+ ),
29
+ systemSurface: context.systemSurface,
30
+ observation: context.observation
24
31
  )
25
32
  }
26
33
  }
27
34
  switch preparation {
28
35
  case .response(let response):
29
36
  return response
30
- case .capture(let target, let systemSurface):
37
+ case .capture(let target, let systemSurface, let observation):
31
38
  return try executeSnapshotPrepared(
32
39
  command: command,
33
40
  target: target,
34
- systemSurface: systemSurface
41
+ systemSurface: systemSurface,
42
+ observation: observation
35
43
  )
36
44
  }
37
45
  }
@@ -86,7 +94,8 @@ extension RunnerTests {
86
94
  private func executeSnapshotPrepared(
87
95
  command: Command,
88
96
  target: SnapshotCaptureTarget,
89
- systemSurface: SystemSurfaceHost?
97
+ systemSurface: SystemSurfaceHost?,
98
+ observation: SnapshotObservationPayload?
90
99
  ) throws -> Response {
91
100
  let options = Self.presentationOptions(from: command)
92
101
  do {
@@ -102,6 +111,21 @@ extension RunnerTests {
102
111
  kind: systemSurface.kind.rawValue
103
112
  )
104
113
  }
114
+ if let observation {
115
+ guard let capturedProcessIdentifier = target.processIdentifier else {
116
+ return observeOnlyUnavailableResponse()
117
+ }
118
+ let unchanged = try runMainThreadWork(
119
+ "observe_only_state",
120
+ timeout: Self.mainThreadExecutionTimeout,
121
+ timeoutError: Self.mainThreadExecutionTimeoutError
122
+ ) {
123
+ target.app.state == .runningForeground
124
+ && Self.processIdentifier(of: target.app) == capturedProcessIdentifier
125
+ }
126
+ guard unchanged else { return observeOnlyUnavailableResponse() }
127
+ payload.observation = observation
128
+ }
105
129
  setNeedsPostSnapshotInteractionDelay()
106
130
  return Response(ok: true, data: payload)
107
131
  } catch let failure as SnapshotCaptureFailure {
@@ -524,9 +524,6 @@ extension RunnerTests {
524
524
 
525
525
 
526
526
 
527
-
528
-
529
-
530
527
  static func awaitSynthesizedReplacementCommitOutcome(
531
528
  expectedText: String,
532
529
  placeholder: String?,
@@ -64,9 +64,7 @@ extension RunnerTests {
64
64
  static let warmupValueTimeout: TimeInterval = 0.4
65
65
  static let verificationStabilityWindow: TimeInterval = 0.2
66
66
 
67
-
68
-
69
- static let unconfirmedSettleCeiling: TimeInterval = 1.0
67
+ static let replacementSettleCeiling: TimeInterval = 1.0
70
68
 
71
69
 
72
70
 
@@ -243,7 +241,7 @@ extension RunnerTests {
243
241
  }
244
242
  }
245
243
 
246
- func clearTextInput(_ element: XCUIElement) {
244
+ func clearTextInput(app: XCUIApplication, _ element: XCUIElement) {
247
245
 
248
246
 
249
247
 
@@ -257,7 +255,7 @@ extension RunnerTests {
257
255
  return
258
256
  }
259
257
  #if !os(tvOS)
260
- moveCaretToEnd(element: element)
258
+ moveCaretToEnd(app: app, element: element)
261
259
  #endif
262
260
  let count = estimatedDeleteCount(for: element)
263
261
  let deletes = String(repeating: XCUIKeyboardKey.delete.rawValue, count: count)
@@ -358,6 +356,21 @@ extension RunnerTests {
358
356
  }
359
357
 
360
358
 
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+ func textEntrySnapshotFrame(_ element: XCUIElement) -> CGRect? {
368
+
369
+
370
+ safely("TEXT_ENTRY_SNAPSHOT_FRAME", { element.exists ? try? element.snapshot() : nil })?.frame
371
+ }
372
+
373
+
361
374
  func probeTextEntryInput(_ element: XCUIElement) -> TextEntryInputProbe {
362
375
  var probe = TextEntryInputProbe.unavailable
363
376
  let (_, exception) = catchingObjCException(fallback: ()) {
@@ -395,20 +408,29 @@ extension RunnerTests {
395
408
  return nil
396
409
  }
397
410
 
398
- private func moveCaretToEnd(element: XCUIElement) {
411
+ private func moveCaretToEnd(app: XCUIApplication, element: XCUIElement) {
399
412
  #if os(tvOS)
400
413
  return
401
414
  #else
402
- let frame = element.frame
403
- guard !frame.isEmpty else {
404
- element.tap()
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+
424
+
425
+
426
+ guard let frame = textEntrySnapshotFrame(element), !frame.isEmpty else {
405
427
  return
406
428
  }
407
- let origin = element.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
408
- let target = origin.withOffset(
409
- CGVector(dx: max(2, frame.width - 4), dy: max(2, frame.height / 2))
429
+ _ = tapAt(
430
+ app: app,
431
+ x: frame.minX + max(2, frame.width - 4),
432
+ y: frame.minY + max(2, frame.height / 2)
410
433
  )
411
- target.tap()
412
434
  #endif
413
435
  }
414
436
 
@@ -39,41 +39,74 @@ extension RunnerTests {
39
39
  let target: TextEntryElementIdentity
40
40
  }
41
41
 
42
+ struct ReplacementTextEntryConfirmation {
43
+ private let requested: String
44
+ private let baseline: TextEntryObservation?
45
+ private var deadline: Date
46
+ private var latest: TextEntryObservation?
47
+ private var stableSince: Date
48
+
49
+ init(requested: String, baseline: TextEntryObservation?, startedAt: Date) {
50
+ self.requested = requested
51
+ self.baseline = baseline
52
+ deadline = startedAt.addingTimeInterval(TextEntryTiming.replacementSettleCeiling)
53
+ stableSince = startedAt
54
+ }
42
55
 
56
+ mutating func observe(_ observed: TextEntryObservation, at sampledAt: Date) -> TextEntryResult? {
43
57
 
44
-
45
-
46
-
47
- static func textEntryValueEchoes(observed: String, expected: String, baseline: String) -> Bool {
48
- let request = textEntryRequestWithoutSubmitKeys(expected)
49
- let residualAndRequest = baseline + request
50
- return isOrderedSubsequence(observed, of: residualAndRequest)
51
- || (isOrderedSubsequence(request, of: observed) && !isOrderedSubsequence(request, of: baseline))
52
- || isOrderedSubsequence(residualAndRequest, of: observed)
58
+ if latest == nil {
59
+ deadline = max(deadline, sampledAt.addingTimeInterval(TextEntryTiming.verificationStabilityWindow))
60
+ }
61
+ if latest.map({ observed.isSettled(with: $0) }) != true { stableSince = sampledAt }
62
+ latest = observed
63
+ let result = RunnerTests.replacementTextEntryResult(requested: requested, baseline: baseline, observed: observed)
64
+ let settled = sampledAt.timeIntervalSince(stableSince) >= TextEntryTiming.verificationStabilityWindow
65
+ let moved = baseline.map { !observed.isSettled(with: $0) } ?? true
66
+ if settled && (moved || result.verified != false || sampledAt >= deadline) {
67
+ return result
68
+ }
69
+ if sampledAt >= deadline {
70
+ return TextEntryResult(
71
+ verified: nil, repaired: false, expectedText: requested, observedText: observed.value,
72
+ failure: .commitNotObserved
73
+ )
74
+ }
75
+ return nil
76
+ }
53
77
  }
54
78
 
55
79
 
56
-
57
-
58
- static func unconfirmedTextEntryEvidence(
80
+ static func replacementTextEntryResult(
59
81
  requested: String,
60
82
  baseline: TextEntryObservation?,
61
83
  observed: TextEntryObservation?
62
- ) -> TextEntryUnconfirmedEvidence? {
63
- guard !textEntryRequestWithoutSubmitKeys(requested).isEmpty,
64
- let baseline,
65
- let observed,
66
- baseline.identity.isSameElement(as: observed.identity),
67
- observed.value != baseline.value,
68
- !textEntryValueEchoes(observed: observed.value, expected: requested, baseline: baseline.value)
69
- else {
70
- return nil
84
+ ) -> TextEntryResult {
85
+ func result(_ verified: Bool?) -> TextEntryResult {
86
+ TextEntryResult(verified: verified, repaired: false, expectedText: requested, observedText: observed?.value)
87
+ }
88
+ guard let observed else { return result(nil) }
89
+ if let baseline, !baseline.identity.isSameElement(as: observed.identity) {
90
+ return result(false)
71
91
  }
72
- return TextEntryUnconfirmedEvidence(
73
- requested: requested,
74
- before: baseline.value,
75
- after: observed.value,
76
- target: observed.identity
92
+ let request = observed.identity.elementType == elementTypeNamesByRawValue[XCUIElement.ElementType.textView.rawValue]
93
+ ? requested : textEntryRequestWithoutSubmitKeys(requested)
94
+ if observed.value == requested || observed.value == request { return result(true) }
95
+
96
+ if request != requested { return result(nil) }
97
+ guard !request.isEmpty, let baseline else { return result(false) }
98
+ if isOrderedSubsequence(observed.value, of: baseline.value + request) { return result(false) }
99
+ return TextEntryResult(
100
+ verified: nil,
101
+ repaired: false,
102
+ expectedText: requested,
103
+ observedText: observed.value,
104
+ unconfirmed: TextEntryUnconfirmedEvidence(
105
+ requested: requested,
106
+ before: baseline.value,
107
+ after: observed.value,
108
+ target: observed.identity
109
+ )
77
110
  )
78
111
  }
79
112
 
@@ -137,7 +137,7 @@ extension RunnerTests {
137
137
  if keyboardVisibleBeforeTap, let target {
138
138
  return TextEntryTarget(
139
139
  element: target,
140
- refreshPoint: textEntryRefreshPoint(for: target) ?? requestedPoint,
140
+ refreshPoint: textEntryRefreshPoint(for: target, fallbackTo: requestedPoint),
141
141
  prefersFocusedElement: false
142
142
  )
143
143
  }
@@ -157,18 +157,32 @@ extension RunnerTests {
157
157
  : (waitForTextEntryReadiness(app: app, target: readyTarget) ?? stabilized.element ?? target)
158
158
  return TextEntryTarget(
159
159
  element: element,
160
- refreshPoint: textEntryRefreshPoint(for: element) ?? requestedPoint,
160
+ refreshPoint: textEntryRefreshPoint(for: element, fallbackTo: requestedPoint),
161
161
  prefersFocusedElement: false
162
162
  )
163
163
  }
164
164
 
165
- private func textEntryRefreshPoint(for element: XCUIElement?) -> CGPoint? {
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+ private func textEntryRefreshPoint(
175
+ for element: XCUIElement?,
176
+ fallbackTo requestedPoint: CGPoint?
177
+ ) -> CGPoint? {
166
178
  guard let element else {
179
+ return requestedPoint
180
+ }
181
+ guard let frame = textEntrySnapshotFrame(element) else {
167
182
  return nil
168
183
  }
169
- let frame = element.frame
170
184
  guard !frame.isEmpty else {
171
- return nil
185
+ return requestedPoint
172
186
  }
173
187
  return CGPoint(x: frame.midX, y: frame.midY)
174
188
  }