agent-device 0.20.10 → 0.21.0

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 (490) hide show
  1. package/README.md +2 -2
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.apk → agent-device-android-ime-helper-0.21.0.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.0.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.manifest.json → agent-device-android-ime-helper-0.21.0.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.10.manifest.json → agent-device-android-snapshot-helper-0.21.0.manifest.json} +6 -6
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +35 -33
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +6 -1
  10. package/apple/snapshot-bridge/LICENSE.idb +23 -0
  11. package/apple/snapshot-bridge/README.md +49 -0
  12. package/apple/snapshot-bridge/SnapshotBridge.m +280 -0
  13. package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +33 -0
  14. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +382 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +58 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +19 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAlertVerification.swift +36 -0
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerStringNormalization.swift +8 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +12 -1
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +100 -6
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +2 -2
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +16 -8
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +21 -88
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +124 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +106 -103
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +6 -14
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +63 -91
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -6
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +72 -155
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXElementTypes.swift +12 -0
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +74 -78
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +17 -9
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +42 -11
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +185 -461
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +98 -0
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +224 -164
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationInvariant.swift +19 -0
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +110 -0
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +206 -0
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +147 -25
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -0
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +24 -307
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +206 -0
  44. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +158 -0
  45. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +49 -16
  46. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +2 -11
  47. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +4 -19
  48. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -20
  49. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +111 -0
  50. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +42 -81
  51. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +35 -82
  52. package/dist/apple/snapshot-presentation/Package.swift +21 -0
  53. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +56 -0
  54. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +259 -0
  55. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +153 -0
  56. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationFailure.swift +27 -0
  57. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +91 -0
  58. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +161 -0
  59. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotScopePolicy.swift +53 -0
  60. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +242 -0
  61. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +97 -0
  62. package/dist/src/adapter.js +1 -0
  63. package/dist/src/adb-executor.js +2 -0
  64. package/dist/src/adb-failure.js +1 -0
  65. package/dist/src/adb-host.js +1 -0
  66. package/dist/src/adb.js +1 -0
  67. package/dist/src/agent-browser-lifecycle.js +1 -0
  68. package/dist/src/agent-browser-process-record.js +1 -0
  69. package/dist/src/agent-browser-provider.js +1 -0
  70. package/dist/src/agent-browser-tool.js +1 -1
  71. package/dist/src/agent-device-client.js +2 -2
  72. package/dist/src/ai-sdk.d.ts +2 -2
  73. package/dist/src/ai-sdk.js +1 -1
  74. package/dist/src/alert-contract.js +1 -0
  75. package/dist/src/alert-runtime.js +1 -0
  76. package/dist/src/android-adb.d.ts +27 -19
  77. package/dist/src/android-adb.js +1 -1
  78. package/dist/src/android-input-ownership.js +1 -0
  79. package/dist/src/android-system-chrome.js +1 -0
  80. package/dist/src/android.js +1 -1
  81. package/dist/src/api.js +11 -0
  82. package/dist/src/app-catalog.js +1 -0
  83. package/dist/src/app-deployment-resolution.js +2 -0
  84. package/dist/src/app-helpers.js +1 -1
  85. package/dist/src/app-inventory-contract.js +1 -0
  86. package/dist/src/app-inventory.js +1 -0
  87. package/dist/src/app-launch.js +2 -0
  88. package/dist/src/app-lifecycle-facade.js +1 -0
  89. package/dist/src/app-lifecycle.js +3 -6
  90. package/dist/src/app-lifecycle2.js +2 -2
  91. package/dist/src/app-lifecycle3.js +1 -0
  92. package/dist/src/app-log-files.js +1 -1
  93. package/dist/src/app-log-reconnect.js +1 -1
  94. package/dist/src/app-log-runtime.js +1 -4
  95. package/dist/src/app-log-runtime2.js +4 -0
  96. package/dist/src/app-parsers.js +4 -0
  97. package/dist/src/app-resolution-cache.js +1 -0
  98. package/dist/src/app-resolution-facade.js +1 -0
  99. package/dist/src/app-resolution.js +2 -2
  100. package/dist/src/app-state.js +1 -2
  101. package/dist/src/application-lifecycle-interaction.js +1 -0
  102. package/dist/src/application-lifecycle-runtime.js +1 -0
  103. package/dist/src/apps-simctl.js +1 -0
  104. package/dist/src/archive.js +4 -0
  105. package/dist/src/artifact-download.js +1 -0
  106. package/dist/src/artifacts.d.ts +6 -2
  107. package/dist/src/artifacts.js +1 -1
  108. package/dist/src/async-lifecycle.js +1 -0
  109. package/dist/src/audio-probe-result.js +1 -0
  110. package/dist/src/audio-probe-runtime.js +1 -0
  111. package/dist/src/audio-probe-support.js +1 -0
  112. package/dist/src/auth-session.js +1 -1
  113. package/dist/src/auth.js +1 -1
  114. package/dist/src/back-mode.js +1 -0
  115. package/dist/src/{url.js → base-url.js} +1 -1
  116. package/dist/src/boot-diagnostics.js +2 -2
  117. package/dist/src/byte-limit-stream.js +1 -1
  118. package/dist/src/capabilities.js +1 -0
  119. package/dist/src/capture.js +1 -0
  120. package/dist/src/catalog.js +1 -0
  121. package/dist/src/cli-command-aliases.js +1 -0
  122. package/dist/src/cli-config.js +1 -1
  123. package/dist/src/cli-help.js +69 -50
  124. package/dist/src/cli-output.js +1 -1
  125. package/dist/src/cli-runner.js +1 -1
  126. package/dist/src/cli.js +4 -6
  127. package/dist/src/click-button.js +1 -0
  128. package/dist/src/client-metro-companion.js +1 -0
  129. package/dist/src/client-metro.js +1 -1
  130. package/dist/src/client-types.d.ts +255 -231
  131. package/dist/src/clipboard.js +1 -0
  132. package/dist/src/code-signature-cache.js +1 -0
  133. package/dist/src/code-signature.js +1 -0
  134. package/dist/src/color.js +1 -0
  135. package/dist/src/command-metadata.js +1 -1
  136. package/dist/src/command-schema.js +3 -3
  137. package/dist/src/command-surface.js +1 -1
  138. package/dist/src/command-tools.js +2 -2
  139. package/dist/src/command.js +1 -0
  140. package/dist/src/compatibility-policy.js +1 -0
  141. package/dist/src/config.js +1 -1
  142. package/dist/src/config2.js +1 -0
  143. package/dist/src/connection-runtime.js +1 -1
  144. package/dist/src/connection.js +5 -5
  145. package/dist/src/contracts.d.ts +1 -1
  146. package/dist/src/contracts.js +1 -1
  147. package/dist/src/daemon-client-lifecycle.js +1 -0
  148. package/dist/src/daemon-process.js +1 -0
  149. package/dist/src/daemon-registration.js +1 -0
  150. package/dist/src/daemon-shutdown-report.js +1 -1
  151. package/dist/src/daemon.js +2 -2
  152. package/dist/src/debug-symbols-facade.js +5 -0
  153. package/dist/src/deploy-result-target.js +1 -0
  154. package/dist/src/device-claim-inspection.js +1 -1
  155. package/dist/src/device-claim-rule.js +1 -0
  156. package/dist/src/device-input-state.d.ts +190 -3
  157. package/dist/src/device-inventory-context.js +1 -0
  158. package/dist/src/device-isolation.js +1 -0
  159. package/dist/src/device-release.js +1 -0
  160. package/dist/src/device-rotation.js +1 -0
  161. package/dist/src/device-selection-resolver.js +1 -0
  162. package/dist/src/device-session.js +1 -0
  163. package/dist/src/device.js +1 -1
  164. package/dist/src/device2.js +3 -2
  165. package/dist/src/diagnostics.js +3 -0
  166. package/dist/src/diagnostics2.js +1 -0
  167. package/dist/src/dispatch-resolve.js +1 -0
  168. package/dist/src/doctor-facade.js +1 -0
  169. package/dist/src/doctor-output.js +1 -0
  170. package/dist/src/doctor.js +1 -0
  171. package/dist/src/doctor2.js +1 -0
  172. package/dist/src/doctor3.js +1 -0
  173. package/dist/src/durable-resource.js +1 -0
  174. package/dist/src/entities.js +1 -1
  175. package/dist/src/error.js +2 -0
  176. package/dist/src/exec.js +1 -0
  177. package/dist/src/file.js +1 -0
  178. package/dist/src/find.js +1 -1
  179. package/dist/src/finders.js +1 -1
  180. package/dist/src/format.js +2 -0
  181. package/dist/src/generic-settle.js +1 -1
  182. package/dist/src/generic.js +1 -1
  183. package/dist/src/gesture-admission.js +1 -0
  184. package/dist/src/gesture-plan-types.js +1 -0
  185. package/dist/src/gesture-plan.js +1 -0
  186. package/dist/src/gesture-runtime.js +1 -0
  187. package/dist/src/harmonyos.js +1 -1
  188. package/dist/src/hdc.js +1 -1
  189. package/dist/src/helper.js +2 -2
  190. package/dist/src/host-file.js +1 -0
  191. package/dist/src/human-control-contract.js +1 -0
  192. package/dist/src/human-control.js +1 -0
  193. package/dist/src/index.d.ts +1 -1
  194. package/dist/src/index.js +1 -1
  195. package/dist/src/input-actions.js +1 -4
  196. package/dist/src/input-actions2.js +2 -1
  197. package/dist/src/install-artifact-facade.js +1 -0
  198. package/dist/src/install-source-network-transport.js +1 -0
  199. package/dist/src/install-source.d.ts +3 -10
  200. package/dist/src/install-source2.js +1 -1
  201. package/dist/src/interaction-positionals.js +1 -0
  202. package/dist/src/interaction-ref-policy.js +1 -0
  203. package/dist/src/interaction.js +1 -1
  204. package/dist/src/interaction2.js +1 -1
  205. package/dist/src/interactor-operation-catalog.js +1 -0
  206. package/dist/src/interactor-types.js +1 -0
  207. package/dist/src/interactor.js +6 -2
  208. package/dist/src/interactor2.js +1 -1
  209. package/dist/src/interactors.js +1 -1
  210. package/dist/src/internal/bin.d.ts +1 -1
  211. package/dist/src/internal/bin.js +1 -2
  212. package/dist/src/internal/companion-tunnel.d.ts +1 -1
  213. package/dist/src/internal/companion-tunnel.js +1 -1
  214. package/dist/src/internal/daemon.d.ts +1 -1
  215. package/dist/src/internal/daemon.js +2 -4
  216. package/dist/src/internal/png-worker.d.ts +4 -4
  217. package/dist/src/internal/png-worker.js +1 -1
  218. package/dist/src/internal/run-script-http-child.d.ts +4 -0
  219. package/dist/src/internal/run-script-http-child.js +1 -0
  220. package/dist/src/internal/update-check-entry.d.ts +1 -1
  221. package/dist/src/inventory.js +4 -4
  222. package/dist/src/inventory2.js +1 -1
  223. package/dist/src/inventory3.js +1 -1
  224. package/dist/src/inventory5.js +1 -1
  225. package/dist/src/inventory6.js +1 -1
  226. package/dist/src/ios-client.js +16 -0
  227. package/dist/src/ios-snapshot-acquisition.js +1 -0
  228. package/dist/src/ios-snapshot-adapter.js +1 -0
  229. package/dist/src/ios-snapshot-planning.js +1 -0
  230. package/dist/src/ios-snapshot-runtime.js +1 -0
  231. package/dist/src/json.js +1 -0
  232. package/dist/src/keyboard-actions.js +1 -0
  233. package/dist/src/launch-console.js +1 -0
  234. package/dist/src/lease-context.js +1 -1
  235. package/dist/src/lease-scope.js +1 -0
  236. package/dist/src/lease.js +1 -1
  237. package/dist/src/limrun-runtime-dependencies.js +1 -1
  238. package/dist/src/limrun.d.ts +1610 -7
  239. package/dist/src/limrun.js +1 -1
  240. package/dist/src/linux.js +1 -1
  241. package/dist/src/local-interactor-operation-set.js +1 -0
  242. package/dist/src/location-coordinates.js +1 -1
  243. package/dist/src/logcat.js +1 -1
  244. package/dist/src/macos-facade.js +1 -0
  245. package/dist/src/managed-device-scope.js +1 -0
  246. package/dist/src/mechanics.js +19 -0
  247. package/dist/src/metro.d.ts +4 -2
  248. package/dist/src/metro.js +1 -1
  249. package/dist/src/metro2.js +1 -1
  250. package/dist/src/mobile-snapshot-semantics.js +1 -1
  251. package/dist/src/multitouch-support.js +1 -0
  252. package/dist/src/numeric.js +1 -0
  253. package/dist/src/observability.js +1 -1
  254. package/dist/src/observation.js +2 -0
  255. package/dist/src/output-path.js +1 -1
  256. package/dist/src/owner-identity.js +3 -1
  257. package/dist/src/parameterized-recorded-fill.js +1 -0
  258. package/dist/src/parser.js +1 -1
  259. package/dist/src/perf-facade.js +2 -0
  260. package/dist/src/perf-runtime-operation-builder.js +1 -0
  261. package/dist/src/perf-runtime-plan.js +1 -0
  262. package/dist/src/perf-runtime.js +1 -0
  263. package/dist/src/perf.js +1 -4
  264. package/dist/src/physical-device-control.js +1 -1
  265. package/dist/src/physical-device-facade.js +1 -0
  266. package/dist/src/platform-request-scope.js +1 -0
  267. package/dist/src/platform-runtime-android-adb-host.js +1 -0
  268. package/dist/src/platform-runtime-android-mechanics.js +1 -0
  269. package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
  270. package/dist/src/platform-runtime-app-log-process.js +1 -1
  271. package/dist/src/platform-runtime-apple-resources.js +1 -0
  272. package/dist/src/platform-runtime-host.js +1 -1
  273. package/dist/src/platform-runtime-managed-owner.js +1 -0
  274. package/dist/src/platform-runtime-network-web-transport.js +1 -1
  275. package/dist/src/platform-runtime-open-target.js +1 -1
  276. package/dist/src/platform-runtime-operation-host.js +4 -4
  277. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  278. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  279. package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
  280. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  281. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  282. package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
  283. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  284. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
  285. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -0
  286. package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
  287. package/dist/src/platform-runtime-unavailable.js +1 -0
  288. package/dist/src/platform-runtime.js +1 -1
  289. package/dist/src/platform-runtime2.js +1 -1
  290. package/dist/src/plist.js +1 -1
  291. package/dist/src/png-worker-contract.js +1 -1
  292. package/dist/src/prepare-kind.js +1 -0
  293. package/dist/src/process-exit.js +1 -1
  294. package/dist/src/process.js +1 -0
  295. package/dist/src/provider-device-runtime.js +1 -0
  296. package/dist/src/provider-session-ownership.js +2 -0
  297. package/dist/src/provider-webdriver.js +1 -1
  298. package/dist/src/provider.js +1 -1
  299. package/dist/src/providers.js +1 -0
  300. package/dist/src/proxy.js +2 -2
  301. package/dist/src/react-native-overlay.js +1 -0
  302. package/dist/src/react-native.js +1 -1
  303. package/dist/src/record-runtime.js +1 -1
  304. package/dist/src/record-trace.js +1 -1
  305. package/dist/src/rect-center.js +1 -0
  306. package/dist/src/register-builtins.js +1 -0
  307. package/dist/src/registry.js +39 -28
  308. package/dist/src/remote-config2.js +1 -1
  309. package/dist/src/replay-divergence.js +2 -0
  310. package/dist/src/replay.js +2 -2
  311. package/dist/src/reporting.js +8 -8
  312. package/dist/src/request-admission.js +1 -0
  313. package/dist/src/request-cancel.js +1 -0
  314. package/dist/src/request-cancellation.js +1 -0
  315. package/dist/src/request-progress-protocol.js +1 -0
  316. package/dist/src/request-providers.js +1 -0
  317. package/dist/src/request-runtime-binding.js +1 -0
  318. package/dist/src/request.js +1 -0
  319. package/dist/src/result-serialization.js +1 -0
  320. package/dist/src/retry.js +1 -0
  321. package/dist/src/rolldown-runtime.js +1 -1
  322. package/dist/src/runner-cache-metadata.js +2 -0
  323. package/dist/src/runner-client.js +1 -1
  324. package/dist/src/runner-disposal.js +1 -1
  325. package/dist/src/runner-operations-facade.js +1 -0
  326. package/dist/src/runner-owner-facade.js +1 -0
  327. package/dist/src/runner-owner-state.js +1 -0
  328. package/dist/src/runner-presentation.js +1 -0
  329. package/dist/src/runner-selector-query.js +1 -0
  330. package/dist/src/runner.js +1 -0
  331. package/dist/src/{runtime-transport.js → runtime-transport-hints.js} +1 -1
  332. package/dist/src/runtime.js +3 -3
  333. package/dist/src/runtime2.js +4 -4
  334. package/dist/src/runtime3.js +1 -1
  335. package/dist/src/runtime4.js +4 -3
  336. package/dist/src/runtime5.js +1 -1
  337. package/dist/src/runtime6.js +1 -1
  338. package/dist/src/runtime7.js +1 -1
  339. package/dist/src/runtime8.js +1 -1
  340. package/dist/src/runtime9.js +1 -1
  341. package/dist/src/scoped-provider.js +1 -1
  342. package/dist/src/screen-recording-completion.js +1 -0
  343. package/dist/src/screen-recording-live-handle.js +1 -0
  344. package/dist/src/screen-recording-options.js +1 -0
  345. package/dist/src/screen-recording-resource-recovery.js +1 -0
  346. package/dist/src/screen-recording-runtime.js +1 -0
  347. package/dist/src/screenshot-density.js +1 -1
  348. package/dist/src/screenshot-result.js +1 -6
  349. package/dist/src/screenshot-runtime.js +1 -0
  350. package/dist/src/screenshot.js +1 -1
  351. package/dist/src/screenshot2.js +1 -0
  352. package/dist/src/screenshot3.js +5 -0
  353. package/dist/src/script.js +1 -0
  354. package/dist/src/scroll-command.js +1 -0
  355. package/dist/src/scroll-gesture.js +1 -0
  356. package/dist/src/scroll-indicator.js +1 -0
  357. package/dist/src/sdk-batch-runner.d.ts +23 -6
  358. package/dist/src/sdk-batch-runner.js +2 -3
  359. package/dist/src/sdk-batch.js +2 -0
  360. package/dist/src/sdk-contracts.d.ts +127 -41
  361. package/dist/src/sdk-contracts.js +2 -2
  362. package/dist/src/sdk-device.js +1 -1
  363. package/dist/src/sdk-finders.js +1 -1
  364. package/dist/src/sdk-io.js +1 -1
  365. package/dist/src/sdk-remote-config.d.ts +1 -1
  366. package/dist/src/sdk-remote-config.js +1 -1
  367. package/dist/src/sdk-selectors.d.ts +472 -144
  368. package/dist/src/sdk-selectors.js +1 -1
  369. package/dist/src/selection.js +1 -0
  370. package/dist/src/selector-runtime.js +1 -1
  371. package/dist/src/selectors.js +1 -1
  372. package/dist/src/semantic-index.js +1 -0
  373. package/dist/src/server.js +4 -4
  374. package/dist/src/session-allocation.js +1 -0
  375. package/dist/src/session-artifact-paths.js +1 -0
  376. package/dist/src/session-paths.js +1 -0
  377. package/dist/src/session-repair-tombstone.js +1 -0
  378. package/dist/src/session-routing.js +1 -0
  379. package/dist/src/session-runtime-admission.js +1 -0
  380. package/dist/src/session-snapshot.js +1 -0
  381. package/dist/src/session-store.js +4 -0
  382. package/dist/src/session-target-evidence.js +1 -1
  383. package/dist/src/session2.js +5 -27
  384. package/dist/src/settings.js +1 -0
  385. package/dist/src/shared.js +2 -2
  386. package/dist/src/simctl-facade.js +1 -0
  387. package/dist/src/simctl.js +1 -1
  388. package/dist/src/simulator-facade.js +1 -0
  389. package/dist/src/simulator.js +1 -1
  390. package/dist/src/snapshot-capture-annotations.js +1 -0
  391. package/dist/src/snapshot-desktop-projection.js +1 -0
  392. package/dist/src/snapshot-diagnostics.js +1 -0
  393. package/dist/src/snapshot-process.js +1 -0
  394. package/dist/src/snapshot-quality-backend-capabilities.js +1 -0
  395. package/dist/src/snapshot-quality-verdict.js +1 -0
  396. package/dist/src/snapshot-runtime-binding.js +1 -0
  397. package/dist/src/snapshot-runtime.js +1 -1
  398. package/dist/src/snapshot-scope.js +1 -1
  399. package/dist/src/snapshot-state.js +1 -0
  400. package/dist/src/snapshot.js +1 -8
  401. package/dist/src/snapshot2.js +1 -1
  402. package/dist/src/snapshot3.js +1 -1
  403. package/dist/src/snapshot4.js +1 -0
  404. package/dist/src/src.js +1 -1
  405. package/dist/src/src2.js +1 -1
  406. package/dist/src/src3.js +1 -2
  407. package/dist/src/src4.js +1 -1
  408. package/dist/src/src5.js +1 -0
  409. package/dist/src/src6.js +1 -0
  410. package/dist/src/src7.js +2 -0
  411. package/dist/src/src8.js +115 -0
  412. package/dist/src/startup-recovery-fence.js +1 -0
  413. package/dist/src/status-markers.js +1 -0
  414. package/dist/src/string-enum.js +1 -1
  415. package/dist/src/success-text.js +1 -0
  416. package/dist/src/surface-snapshot.js +1 -0
  417. package/dist/src/surface-snapshot2.js +1 -0
  418. package/dist/src/takeover.js +5 -0
  419. package/dist/src/tool-provider-facade.js +1 -0
  420. package/dist/src/tool-provider.js +4 -3
  421. package/dist/src/tool-provider2.js +1 -1
  422. package/dist/src/tool-provider3.js +1 -1
  423. package/dist/src/toolchain-probe.js +2 -0
  424. package/dist/src/touch-runtime.js +1 -0
  425. package/dist/src/transport.js +3 -0
  426. package/dist/src/tree.js +1 -0
  427. package/dist/src/ttl-memo.js +1 -0
  428. package/dist/src/tv-remote.js +1 -0
  429. package/dist/src/type-text-runtime.js +1 -0
  430. package/dist/src/undici.js +99 -0
  431. package/dist/src/update-check.js +1 -1
  432. package/dist/src/verified-file.js +1 -1
  433. package/dist/src/version.js +1 -1
  434. package/dist/src/video.js +2 -2
  435. package/dist/src/web.js +2 -1
  436. package/dist/src/web2.js +1 -0
  437. package/dist/src/webdriver-ios-snapshot.js +1 -0
  438. package/dist/src/webdriver-source.js +1 -0
  439. package/linux/atspi-dump.py +54 -9
  440. package/package.json +56 -34
  441. package/server.json +9 -3
  442. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +0 -1
  443. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk +0 -0
  444. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +0 -1
  445. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +0 -4
  446. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +0 -168
  447. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -6
  448. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +0 -4
  449. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +0 -4
  450. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +0 -183
  451. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
  452. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -4
  453. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +0 -4
  454. package/dist/src/appearance.js +0 -1
  455. package/dist/src/apps.js +0 -5
  456. package/dist/src/audio-probe.js +0 -1
  457. package/dist/src/cli-grammar.js +0 -1
  458. package/dist/src/command-catalog.js +0 -1
  459. package/dist/src/debug-symbols.js +0 -5
  460. package/dist/src/device-input-state.js +0 -2
  461. package/dist/src/device-ready.js +0 -1
  462. package/dist/src/dispatch.js +0 -1
  463. package/dist/src/handler-utils.js +0 -1
  464. package/dist/src/helper-package-install.js +0 -1
  465. package/dist/src/host-process.js +0 -3
  466. package/dist/src/ime-lifecycle.js +0 -2
  467. package/dist/src/ime-recovery-marker.js +0 -1
  468. package/dist/src/input-actions3.js +0 -1
  469. package/dist/src/install-artifact.js +0 -1
  470. package/dist/src/install-artifact2.js +0 -1
  471. package/dist/src/interaction-common.js +0 -1
  472. package/dist/src/interaction-runtime.js +0 -1
  473. package/dist/src/interaction-snapshot.js +0 -1
  474. package/dist/src/manifest.js +0 -1
  475. package/dist/src/method-scope.js +0 -1
  476. package/dist/src/png-resize.js +0 -1
  477. package/dist/src/process-lock.js +0 -1
  478. package/dist/src/runner-lease.js +0 -1
  479. package/dist/src/runner-sequence.js +0 -1
  480. package/dist/src/script-source-bundle.js +0 -16
  481. package/dist/src/sdk-android-adb.d.ts +0 -245
  482. package/dist/src/sdk-android-adb.js +0 -4
  483. package/dist/src/sdk.js +0 -1
  484. package/dist/src/setting-state.js +0 -1
  485. package/dist/src/shell-quote.js +0 -1
  486. package/dist/src/snapshot-session.js +0 -1
  487. package/dist/src/timing-safe-equal.js +0 -1
  488. package/dist/src/unsupported-interactor.js +0 -1
  489. package/dist/src/verdict.js +0 -1
  490. /package/dist/src/{recording-telemetry.js → telemetry.js} +0 -0
@@ -29,6 +29,7 @@ typedef id (*RunnerDragPointerPathFactory)(
29
29
  CGPoint,
30
30
  double
31
31
  );
32
+ typedef double (*RunnerDragProgressFunction)(double);
32
33
 
33
34
  static NSString * _Nullable RunnerResolveGestureEventBridge(
34
35
  id application,
@@ -56,6 +57,21 @@ static id RunnerContinuousDragPointerPath(
56
57
  CGPoint end,
57
58
  double durationMs
58
59
  );
60
+ static id RunnerControlledScrollPointerPath(
61
+ const RunnerGestureEventBridge *bridge,
62
+ CGPoint start,
63
+ CGPoint end,
64
+ double durationMs
65
+ );
66
+ static id RunnerSampledDragPointerPath(
67
+ const RunnerGestureEventBridge *bridge,
68
+ CGPoint start,
69
+ CGPoint end,
70
+ double durationMs,
71
+ RunnerDragProgressFunction progress,
72
+ NSInteger frameCount
73
+ );
74
+ static double RunnerSmoothstepProgress(double t);
59
75
  static NSString * _Nullable RunnerTrySynthesizeDrag(
60
76
  id application,
61
77
  CGPoint start,
@@ -68,6 +84,8 @@ static NSString * _Nullable RunnerTrySynthesizeTap(id application, CGPoint point
68
84
  // XCTest's proven swipe profile reaches the endpoint in 100 ms, then holds for the planned
69
85
  // fling duration. Fast movement is what lets UIKit distinguish a fling from a timed pan.
70
86
  static const NSTimeInterval RunnerSwipeMovementDurationSeconds = 0.1;
87
+ static const double RunnerDragSampleIntervalMs = 16.0;
88
+ static const NSInteger RunnerControlledScrollMaxFrameCount = 30;
71
89
  static id RunnerTapPointerPath(
72
90
  const RunnerGestureEventBridge *bridge,
73
91
  CGPoint point
@@ -115,6 +133,26 @@ static id RunnerTapPointerPath(
115
133
  }
116
134
  }
117
135
 
136
+ + (NSString * _Nullable)synthesizeControlledScrollWithApplication:(id)application
137
+ x:(double)x
138
+ y:(double)y
139
+ x2:(double)x2
140
+ y2:(double)y2
141
+ durationMs:(double)durationMs {
142
+ @try {
143
+ return RunnerTrySynthesizeDrag(
144
+ application,
145
+ CGPointMake(x, y),
146
+ CGPointMake(x2, y2),
147
+ durationMs,
148
+ @"agent-device-controlled-scroll",
149
+ RunnerControlledScrollPointerPath
150
+ );
151
+ } @catch (NSException *exception) {
152
+ return RunnerFormatXCTestException(exception, @"private XCTest event synthesis failed");
153
+ }
154
+ }
155
+
118
156
  + (NSString * _Nullable)synthesizeTapWithApplication:(id)application
119
157
  x:(double)x
120
158
  y:(double)y {
@@ -351,6 +389,46 @@ static id RunnerContinuousDragPointerPath(
351
389
  CGPoint start,
352
390
  CGPoint end,
353
391
  double durationMs
392
+ ) {
393
+ // This is velocity shaping, not just interpolation density: smoothstep's endpoint slope is zero,
394
+ // while a planned linear segment reaches lift with nonzero velocity unless a destination hold
395
+ // follows it. UIKit uses finger-up velocity for scroll deceleration. See ADR 0013 and issue #1586.
396
+ return RunnerSampledDragPointerPath(
397
+ bridge,
398
+ start,
399
+ end,
400
+ durationMs,
401
+ RunnerSmoothstepProgress,
402
+ RunnerContinuousDragFrameCount(durationMs)
403
+ );
404
+ }
405
+
406
+ static id RunnerControlledScrollPointerPath(
407
+ const RunnerGestureEventBridge *bridge,
408
+ CGPoint start,
409
+ CGPoint end,
410
+ double durationMs
411
+ ) {
412
+ // A stationary hold is not a reliable zero-velocity release in XCTest. Cubic ease-out decreases
413
+ // velocity from the first movement and reaches near zero before lift. Profiles that accelerate
414
+ // after pan recognition can still be classified as flings despite a slow final sample.
415
+ return RunnerSampledDragPointerPath(
416
+ bridge,
417
+ start,
418
+ end,
419
+ durationMs,
420
+ RunnerControlledScrollProgress,
421
+ RunnerControlledScrollFrameCount(durationMs)
422
+ );
423
+ }
424
+
425
+ static id RunnerSampledDragPointerPath(
426
+ const RunnerGestureEventBridge *bridge,
427
+ CGPoint start,
428
+ CGPoint end,
429
+ double durationMs,
430
+ RunnerDragProgressFunction progress,
431
+ NSInteger frameCount
354
432
  ) {
355
433
  id path =
356
434
  ((RunnerMsgSendInitPath)objc_msgSend)([bridge->core.pathClass alloc], bridge->initPathSelector, start, 0.0);
@@ -358,14 +436,10 @@ static id RunnerContinuousDragPointerPath(
358
436
  return nil;
359
437
  }
360
438
 
361
- // This is velocity shaping, not just interpolation density: smoothstep's endpoint slope is zero,
362
- // while a planned linear segment reaches lift with nonzero velocity unless a destination hold
363
- // follows it. UIKit uses finger-up velocity for scroll deceleration. See ADR 0013 and issue #1586.
364
- int frameCount = MAX(3, (int)(durationMs / 16.0));
365
439
  NSTimeInterval durationSeconds = durationMs / 1000.0;
366
- for (int index = 1; index <= frameCount; index += 1) {
440
+ for (NSInteger index = 1; index <= frameCount; index += 1) {
367
441
  double t = (double)index / (double)frameCount;
368
- double easedT = t * t * (3.0 - 2.0 * t);
442
+ double easedT = progress(t);
369
443
  CGPoint point = CGPointMake(
370
444
  start.x + (end.x - start.x) * easedT,
371
445
  start.y + (end.y - start.y) * easedT
@@ -377,6 +451,26 @@ static id RunnerContinuousDragPointerPath(
377
451
  return path;
378
452
  }
379
453
 
454
+ static double RunnerSmoothstepProgress(double t) {
455
+ return t * t * (3.0 - 2.0 * t);
456
+ }
457
+
458
+ NSInteger RunnerContinuousDragFrameCount(double durationMs) {
459
+ return MAX(3, (NSInteger)(durationMs / RunnerDragSampleIntervalMs));
460
+ }
461
+
462
+ NSInteger RunnerControlledScrollFrameCount(double durationMs) {
463
+ return MIN(
464
+ RunnerControlledScrollMaxFrameCount,
465
+ MAX(3, (NSInteger)ceil(durationMs / RunnerDragSampleIntervalMs) - 1)
466
+ );
467
+ }
468
+
469
+ double RunnerControlledScrollProgress(double t) {
470
+ double remaining = 1.0 - t;
471
+ return 1.0 - remaining * remaining * remaining;
472
+ }
473
+
380
474
  static id RunnerTapPointerPath(
381
475
  const RunnerGestureEventBridge *bridge,
382
476
  CGPoint point
@@ -11,8 +11,8 @@ import XCTest
11
11
  // This is pure geometry on purpose — no XCUIElement — so the exact decision
12
12
  // can be proven against the golden fixture table shared with the TS twin:
13
13
  // table: contracts/fixtures/tap-point-policy.json
14
- // TS twin: src/snapshot/mobile-snapshot-semantics.ts#isTapPointInsideViewport
15
- // TS test: src/snapshot/__tests__/tap-point-policy-parity.test.ts
14
+ // TS twin: packages/contracts/src/snapshot-visibility.ts#isTapPointInsideViewport
15
+ // TS test: packages/contracts/src/snapshot-tap-point-policy.test.ts
16
16
  // Drift on either side turns CI red without needing a simulator.
17
17
  enum TapPointPolicy {
18
18
  static func isAllowed(elementFrame: CGRect, windowFrame: CGRect) -> Bool {
@@ -1,4 +1,5 @@
1
1
  import XCTest
2
+ import AgentDeviceSnapshotPresentation
2
3
 
3
4
  extension RunnerTests {
4
5
  private static let privateAXSnapshotMaxNodes = 5_000
@@ -105,14 +106,14 @@ extension RunnerTests {
105
106
 
106
107
  func privateAXSnapshotAcquisition(
107
108
  app: XCUIApplication,
108
- options: PresentationOptions,
109
+ hint: CaptureHint,
109
110
  deadline: Date = .distantFuture
110
111
  ) -> SnapshotAcquisition? {
111
112
  #if os(iOS) && targetEnvironment(simulator)
112
- let requestedDepth = options.depth ?? 64
113
+ let requestedDepth = hint.rawTraversalDepth ?? 64
113
114
  // An explicit --depth request is honored as asked: no accepted-depth
114
115
  // memory, no frontier extension past it.
115
- let exactDepthRequested = options.depth != nil
116
+ let exactDepthRequested = hint.rawTraversalDepth != nil
116
117
  let rememberedDepth =
117
118
  exactDepthRequested
118
119
  ? nil
@@ -135,12 +136,16 @@ extension RunnerTests {
135
136
  NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_BUDGET_EXHAUSTED depth=%ld", depth)
136
137
  break
137
138
  }
139
+ // Declared residue (#1797): the bridge caps the tree at 5000 nodes while serializing,
140
+ // BEFORE either projection exists, so a raw capture of a huge screen is bounded rather
141
+ // than failing the way the tree backend's own raw cap does. The cap is disclosed as
142
+ // `truncated`, and it applied to the acquired tree before this projection split too.
138
143
  response = RunnerAXSnapshotBridge.snapshotTree(
139
144
  for: app,
140
145
  maxDepth: depth,
141
146
  maxNodes: Self.privateAXSnapshotMaxNodes,
142
147
  deepExtensionCallLimit: exactDepthRequested ? 0 : Self.privateAXDeepExtensionCallLimit,
143
- customActionLimit: options.customActions ? Self.privateAXCustomActionLimit : 0,
148
+ customActionLimit: hint.customActions ? Self.privateAXCustomActionLimit : 0,
144
149
  deadline: deadline
145
150
  )
146
151
  if response["ok"] as? Bool == true {
@@ -175,11 +180,13 @@ extension RunnerTests {
175
180
 
176
181
  let rootFrame = privateAXRect(root["frame"])
177
182
  let viewport = privateAXSnapshotViewport(app: app, rootFrame: rootFrame)
178
- let nodes = privateAXPresentation(
183
+ let nodes = privateAXAcquisition(
179
184
  rawRoot: root,
180
- options: options,
185
+ hint: hint,
181
186
  viewport: viewport
182
187
  )
188
+ // Serialization-level emptiness only: an acquired-but-fully-clipped tree is presentation's
189
+ // verdict now, surfaced by the plan's sparse classifier on the presented payload (#1797).
183
190
  if nodes.count <= 1 {
184
191
  NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_SPARSE=%ld", nodes.count)
185
192
  return nil
@@ -203,12 +210,14 @@ extension RunnerTests {
203
210
  deepExtension?[RunnerAXSnapshotDeepExtensionNodesAddedKey] as? Int ?? 0
204
211
  )
205
212
  return SnapshotAcquisition(
213
+ hint: hint,
206
214
  nodes: nodes,
207
215
  truncated: (response["truncated"] as? Bool) == true,
208
216
  effectiveDepth: depthLimited ? effectiveDepth : nil,
209
217
  customActions: Self.privateAXCustomActionCoverage(
210
218
  response[RunnerAXSnapshotCustomActionsKey]
211
- )
219
+ ),
220
+ viewport: viewport
212
221
  )
213
222
  #else
214
223
  return nil
@@ -230,7 +239,6 @@ extension RunnerTests {
230
239
  }
231
240
  do {
232
241
  let viewport = try runMainThreadWork(
233
- command: nil,
234
242
  timeout: 1,
235
243
  timeoutError: snapshotMainThreadTimeoutError("reading private AX viewport")
236
244
  ) {
@@ -50,50 +50,34 @@ extension RunnerTests {
50
50
  guard let button = chooseAlertButton(alert.buttons, action: action) else {
51
51
  return Response(ok: false, error: ErrorPayload(message: "alert \(action) button not found"))
52
52
  }
53
- let previousTitle = preferredAlertTitle(alert.root, buttons: alert.buttons)
54
- let actionButtonLabel = button.label.trimmingCharacters(in: .whitespacesAndNewlines)
55
- let actionButtonFrame = button.frame
53
+ guard Date() < deadline else {
54
+ return alertVerificationResponse(.timedOut, action: action, activated: false)
55
+ }
56
+ guard let original = captureAlertPresentation(alert.root) else {
57
+ return alertVerificationResponse(.unconfirmed, action: action, activated: false)
58
+ }
59
+ let observesApplicationRoot = alert.root.elementType == .application
60
+ guard Date() < deadline else {
61
+ return alertVerificationResponse(.timedOut, action: action, activated: false)
62
+ }
56
63
  let outcome = activateElement(app: alert.ownerApp, element: button, action: "alert \(action)")
57
64
  if let response = unsupportedResponse(for: outcome) {
58
65
  return response
59
66
  }
60
- sleepFor(0.2)
61
- if alertStillVisible(
62
- in: alert.ownerApp,
63
- source: alert.source,
64
- previousTitle: previousTitle,
65
- actionButtonLabel: actionButtonLabel,
66
- deadline: deadline
67
- ) {
68
- if !actionButtonFrame.isNull && !actionButtonFrame.isEmpty {
69
- let coordinateOutcome = tapAt(
70
- app: alert.ownerApp,
71
- x: actionButtonFrame.midX,
72
- y: actionButtonFrame.midY
73
- )
74
- if let response = unsupportedResponse(for: coordinateOutcome) {
75
- return response
76
- }
77
- sleepFor(0.2)
78
- }
79
- }
80
- if alertStillVisible(
81
- in: alert.ownerApp,
82
- source: alert.source,
83
- previousTitle: previousTitle,
84
- actionButtonLabel: actionButtonLabel,
85
- deadline: deadline
86
- ) {
87
- return Response(
88
- ok: false,
89
- error: ErrorPayload(
90
- code: "INTERACTION_FAILED",
91
- message: "alert \(action) did not dismiss the visible alert",
92
- hint: "The alert button was found but the system still reports the alert after tapping it."
67
+ while true {
68
+ sleepFor(min(0.2, max(0, deadline.timeIntervalSinceNow)))
69
+ let verification = RunnerAlertVerification.verify(
70
+ original: original,
71
+ observation: observeAlert(
72
+ in: alert.ownerApp,
73
+ source: alert.source,
74
+ observesApplicationRoot: observesApplicationRoot,
75
+ deadline: deadline
93
76
  )
94
77
  )
78
+ if verification == .stillVisible { continue }
79
+ return alertVerificationResponse(verification, action: action, activated: true)
95
80
  }
96
- return Response(ok: true, data: DataPayload(message: action == "accept" ? "accepted" : "dismissed"))
97
81
  }
98
82
 
99
83
  return Response(
@@ -130,57 +114,6 @@ extension RunnerTests {
130
114
  return RunnerAlert(root: root, ownerApp: ownerApp, buttons: buttons, source: source)
131
115
  }
132
116
 
133
- private func alertStillVisible(
134
- in ownerApp: XCUIApplication,
135
- source: RunnerAlertSource,
136
- previousTitle: String,
137
- actionButtonLabel: String,
138
- deadline: Date
139
- ) -> Bool {
140
- guard Date() < deadline,
141
- let current = resolveAlert(source: source, app: ownerApp, deadline: deadline)
142
- else {
143
- return false
144
- }
145
- let currentTitle = preferredAlertTitle(current.root, buttons: current.buttons)
146
- if previousTitle == currentTitle {
147
- return true
148
- }
149
- return current.buttons.contains { button in
150
- button.label.trimmingCharacters(in: .whitespacesAndNewlines) == actionButtonLabel
151
- }
152
- }
153
-
154
- private func resolveAlert(
155
- source: RunnerAlertSource,
156
- app: XCUIApplication,
157
- deadline: Date
158
- ) -> RunnerAlert? {
159
- switch source {
160
- case .blockingSystemModal:
161
- #if os(macOS)
162
- return nil
163
- #else
164
- guard case .resolved(let modal) = resolveBlockingSystemModal(deadline: deadline) else {
165
- return nil
166
- }
167
- return runnerAlert(modal)
168
- #endif
169
- case .appAlert:
170
- guard let alert = firstExistingElement(
171
- in: safeElementsQuery { app.alerts.allElementsBoundByIndex }
172
- ) else {
173
- return nil
174
- }
175
- return runnerAlert(root: alert, ownerApp: app, source: .appAlert)
176
- case .dismissPopup:
177
- guard let popup = firstDismissPopupWindow(in: app) else {
178
- return nil
179
- }
180
- return runnerAlert(root: popup, ownerApp: app, source: .dismissPopup)
181
- }
182
- }
183
-
184
117
  private func firstExistingElement(in elements: [XCUIElement]) -> XCUIElement? {
185
118
  elements.first { isVisibleElement($0) }
186
119
  }
@@ -0,0 +1,124 @@
1
+ import XCTest
2
+
3
+ extension RunnerTests {
4
+ func captureAlertPresentation(_ element: XCUIElement) -> RunnerAlertPresentation? {
5
+ var presentation: RunnerAlertPresentation?
6
+ _ = RunnerObjCExceptionCatcher.catchException {
7
+ guard let snapshot = try? element.snapshot() else { return }
8
+ presentation = self.alertPresentation(snapshot)
9
+ }
10
+ return presentation
11
+ }
12
+
13
+ func observeAlert(
14
+ in ownerApp: XCUIApplication,
15
+ source: RunnerAlertSource,
16
+ observesApplicationRoot: Bool,
17
+ deadline: Date
18
+ ) -> RunnerAlertObservation {
19
+ guard Date() < deadline else { return .deadlineExceeded }
20
+ var observation = RunnerAlertObservation.unavailable
21
+ _ = RunnerObjCExceptionCatcher.catchException {
22
+ switch ownerApp.state {
23
+ case .notRunning:
24
+ observation = .absent
25
+ return
26
+ case .runningForeground, .runningBackground:
27
+ break
28
+ #if !os(macOS)
29
+ case .runningBackgroundSuspended:
30
+ break
31
+ #endif
32
+ case .unknown:
33
+ return
34
+ @unknown default:
35
+ return
36
+ }
37
+ guard Date() < deadline, let snapshot = try? ownerApp.snapshot(),
38
+ !snapshot.children.isEmpty, !snapshot.frame.isNull, !snapshot.frame.isEmpty else { return }
39
+ if observesApplicationRoot {
40
+ observation = .visible(self.alertPresentation(snapshot))
41
+ return
42
+ }
43
+ let candidates = self.alertSnapshots(in: snapshot, source: source, viewport: snapshot.frame)
44
+ guard candidates.count <= 1 else { return }
45
+ observation = candidates.first.map { .visible(self.alertPresentation($0)) } ?? .absent
46
+ }
47
+ return Date() < deadline ? observation : .deadlineExceeded
48
+ }
49
+
50
+ private func alertSnapshots(
51
+ in snapshot: XCUIElementSnapshot,
52
+ source: RunnerAlertSource,
53
+ viewport: CGRect
54
+ ) -> [XCUIElementSnapshot] {
55
+ let frame = snapshot.frame
56
+ let visible = !frame.isNull && !frame.isEmpty && viewport.contains(CGPoint(x: frame.midX, y: frame.midY))
57
+ let matches: Bool
58
+ switch source {
59
+ case .blockingSystemModal:
60
+ matches = snapshot.elementType == .alert || snapshot.elementType == .sheet
61
+ case .appAlert:
62
+ matches = snapshot.elementType == .alert
63
+ case .dismissPopup:
64
+ matches = snapshot.elementType == .window && containsDismissPopupMarker(snapshot)
65
+ }
66
+ if matches && visible { return [snapshot] }
67
+ return snapshot.children.flatMap { alertSnapshots(in: $0, source: source, viewport: viewport) }
68
+ }
69
+
70
+ private func containsDismissPopupMarker(_ snapshot: XCUIElementSnapshot) -> Bool {
71
+ [snapshot.label, snapshot.identifier].contains {
72
+ $0.trimmingCharacters(in: .whitespacesAndNewlines).caseInsensitiveCompare("dismiss popup") == .orderedSame
73
+ } || snapshot.children.contains { containsDismissPopupMarker($0) }
74
+ }
75
+
76
+ private func alertPresentation(_ snapshot: XCUIElementSnapshot) -> RunnerAlertPresentation {
77
+ var content: [String] = []
78
+ var buttons: [String] = []
79
+ func collect(_ node: XCUIElementSnapshot) {
80
+ let label = node.label.trimmingCharacters(in: .whitespacesAndNewlines)
81
+ if actionableTypes.contains(node.elementType) {
82
+ buttons.append(label)
83
+ } else if !label.isEmpty {
84
+ content.append(label)
85
+ }
86
+ node.children.forEach(collect)
87
+ }
88
+ snapshot.children.forEach(collect)
89
+ return RunnerAlertPresentation(
90
+ title: snapshot.label.trimmingCharacters(in: .whitespacesAndNewlines),
91
+ content: content,
92
+ buttons: buttons
93
+ )
94
+ }
95
+
96
+ func alertVerificationResponse(
97
+ _ verification: RunnerAlertVerification,
98
+ action: String,
99
+ activated: Bool
100
+ ) -> Response {
101
+ let code: String
102
+ let message: String
103
+ switch verification {
104
+ case .disappeared, .presentationChanged:
105
+ return Response(ok: true, data: DataPayload(message: action == "accept" ? "accepted" : "dismissed"))
106
+ case .timedOut:
107
+ code = "ALERT_DEADLINE_EXCEEDED"
108
+ message = "alert \(action) exhausted its deadline"
109
+ case .stillVisible:
110
+ code = "INTERACTION_FAILED"
111
+ message = "alert \(action) still observes an unchanged alert presentation"
112
+ case .unconfirmed:
113
+ code = "ALERT_CONFIRMATION_UNAVAILABLE"
114
+ message = "alert \(action) could not read the alert presentation"
115
+ }
116
+ return Response(ok: false, error: ErrorPayload(
117
+ code: code,
118
+ message: message,
119
+ hint: activated
120
+ ? "The button was activated once. Inspect the current alert before deciding on another action."
121
+ : "No alert button was activated. Inspect the current alert before deciding on an action."
122
+ ))
123
+ }
124
+ }