agent-device 0.21.15 → 0.21.17

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 (282) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.15.apk → agent-device-android-ime-helper-0.21.17.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.17.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.15.manifest.json → agent-device-android-ime-helper-0.21.17.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.15.apk → agent-device-android-snapshot-helper-0.21.17.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.17.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.15.manifest.json → agent-device-android-snapshot-helper-0.21.17.manifest.json} +6 -6
  7. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +1 -4
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +9 -9
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +13 -22
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -9
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +31 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1 -1
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +9 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +40 -6
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +202 -73
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +17 -2
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +109 -128
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +4 -0
  20. package/dist/src/adapter.js +1 -1
  21. package/dist/src/adb-executor.js +1 -1
  22. package/dist/src/adb-failure.js +1 -1
  23. package/dist/src/adb-transport.js +1 -1
  24. package/dist/src/agent-browser-process-record.js +1 -1
  25. package/dist/src/agent-browser-provider.js +1 -1
  26. package/dist/src/agent-browser-tool.js +1 -1
  27. package/dist/src/agent-device-client.js +2 -2
  28. package/dist/src/ai-sdk.js +1 -1
  29. package/dist/src/alert-runtime.js +1 -1
  30. package/dist/src/android-input-ownership.js +1 -1
  31. package/dist/src/app-catalog.js +1 -1
  32. package/dist/src/app-deployment-resolution.js +1 -1
  33. package/dist/src/app-inventory.js +1 -1
  34. package/dist/src/app-launch.js +1 -1
  35. package/dist/src/app-lifecycle.js +1 -1
  36. package/dist/src/app-lifecycle2.js +1 -1
  37. package/dist/src/app-log-files.js +1 -1
  38. package/dist/src/app-log-runtime2.js +1 -1
  39. package/dist/src/app-resolution.js +2 -2
  40. package/dist/src/apple-runner-platform.js +1 -1
  41. package/dist/src/application-lifecycle-interaction.js +1 -1
  42. package/dist/src/archive.js +1 -1
  43. package/dist/src/artifact-download.js +1 -1
  44. package/dist/src/auth-session.js +1 -1
  45. package/dist/src/auth.js +1 -1
  46. package/dist/src/back-mode.js +1 -1
  47. package/dist/src/backend-snapshot-options.js +1 -1
  48. package/dist/src/boot-diagnostics.js +1 -1
  49. package/dist/src/cache.js +1 -0
  50. package/dist/src/capture.js +1 -1
  51. package/dist/src/cli-config.js +1 -1
  52. package/dist/src/cli-help.js +9 -7
  53. package/dist/src/cli-runner.js +1 -1
  54. package/dist/src/cli.js +4 -4
  55. package/dist/src/click-button.js +1 -1
  56. package/dist/src/client-metro-companion.js +1 -1
  57. package/dist/src/client-metro.js +1 -1
  58. package/dist/src/client-types.d.ts +6 -6
  59. package/dist/src/clipboard-shell-response.js +1 -1
  60. package/dist/src/code-signature-cache.js +1 -1
  61. package/dist/src/command-schema.js +3 -3
  62. package/dist/src/command-tools.js +3 -3
  63. package/dist/src/connection-runtime.js +1 -1
  64. package/dist/src/connection.js +5 -5
  65. package/dist/src/contracts.js +1 -1
  66. package/dist/src/daemon-client-lease-beat.js +1 -0
  67. package/dist/src/daemon-client-lifecycle.js +1 -1
  68. package/dist/src/daemon-client-transport.js +1 -0
  69. package/dist/src/daemon-policy-file.js +1 -0
  70. package/dist/src/daemon-process.js +1 -1
  71. package/dist/src/daemon-registration.js +1 -1
  72. package/dist/src/daemon-shutdown-report.js +1 -1
  73. package/dist/src/daemon.js +1 -1
  74. package/dist/src/debug-symbols-facade.js +1 -1
  75. package/dist/src/device-claim-inspection.js +1 -1
  76. package/dist/src/device-claim-rule.js +1 -2
  77. package/dist/src/device-inventory-context.js +1 -1
  78. package/dist/src/{stop-sequence.js → device-readiness-runtime.js} +1 -1
  79. package/dist/src/device-rotation.js +1 -1
  80. package/dist/src/device-selection-resolver.js +1 -1
  81. package/dist/src/device-session.js +1 -1
  82. package/dist/src/device-shell.js +1 -1
  83. package/dist/src/device.js +1 -1
  84. package/dist/src/device2.js +1 -1
  85. package/dist/src/devicectl.js +1 -1
  86. package/dist/src/diagnostics.js +1 -1
  87. package/dist/src/dispatch-resolve.js +1 -1
  88. package/dist/src/doctor-facade.js +1 -1
  89. package/dist/src/doctor2.js +1 -1
  90. package/dist/src/durable-resource.js +1 -1
  91. package/dist/src/engine-eval-script.js +1 -1
  92. package/dist/src/error.js +1 -1
  93. package/dist/src/exec.js +1 -1
  94. package/dist/src/file.js +1 -1
  95. package/dist/src/find.js +1 -1
  96. package/dist/src/format.js +1 -2
  97. package/dist/src/gesture-admission.js +1 -1
  98. package/dist/src/gesture-plan.js +1 -1
  99. package/dist/src/gesture-runtime.js +1 -1
  100. package/dist/src/harmonyos.js +1 -1
  101. package/dist/src/helper.js +2 -2
  102. package/dist/src/host.js +1 -1
  103. package/dist/src/human-control-contract.js +1 -1
  104. package/dist/src/human-control.js +1 -1
  105. package/dist/src/index.d.ts +1 -1
  106. package/dist/src/index.js +1 -1
  107. package/dist/src/input-actions.js +1 -1
  108. package/dist/src/input-actions2.js +1 -1
  109. package/dist/src/install-artifact-facade.js +1 -1
  110. package/dist/src/install-source-network-transport.js +1 -1
  111. package/dist/src/install-source2.js +1 -1
  112. package/dist/src/interaction-positionals.js +1 -1
  113. package/dist/src/interaction-ref-policy.js +1 -1
  114. package/dist/src/interaction2.js +1 -1
  115. package/dist/src/interactor-operation-binding.js +1 -1
  116. package/dist/src/interactor.js +5 -4
  117. package/dist/src/interactor2.js +1 -1
  118. package/dist/src/interactors.js +1 -1
  119. package/dist/src/internal/bin.js +1 -1
  120. package/dist/src/internal/daemon.js +2 -2
  121. package/dist/src/internal/png-worker.js +1 -1
  122. package/dist/src/internal/run-script-http-child.js +1 -1
  123. package/dist/src/inventory.js +1 -1
  124. package/dist/src/inventory2.js +1 -1
  125. package/dist/src/inventory3.js +1 -1
  126. package/dist/src/inventory5.js +1 -1
  127. package/dist/src/ios-snapshot-engine.js +1 -1
  128. package/dist/src/ios-snapshot-runtime.js +1 -1
  129. package/dist/src/lease-context.js +1 -1
  130. package/dist/src/lease-scope.js +1 -1
  131. package/dist/src/lease.js +1 -1
  132. package/dist/src/legacy-xctest-device-set.js +1 -0
  133. package/dist/src/limrun-download-file.js +1 -1
  134. package/dist/src/limrun-runtime-dependencies.js +1 -1
  135. package/dist/src/limrun.d.ts +1 -1
  136. package/dist/src/linux.js +1 -1
  137. package/dist/src/location-coordinates.js +1 -1
  138. package/dist/src/managed-device-scope.js +1 -1
  139. package/dist/src/mechanics.js +16 -16
  140. package/dist/src/multitouch-support.js +1 -1
  141. package/dist/src/observation.js +1 -1
  142. package/dist/src/overlay.js +3 -3
  143. package/dist/src/owner-identity.js +3 -3
  144. package/dist/src/parameterized-recorded-fill.js +1 -1
  145. package/dist/src/perf-facade.js +1 -1
  146. package/dist/src/perf-runtime-operation-builder.js +1 -1
  147. package/dist/src/perf-runtime-plan.js +1 -1
  148. package/dist/src/perf-target.js +1 -1
  149. package/dist/src/perf.js +1 -1
  150. package/dist/src/physical-device-control.js +1 -1
  151. package/dist/src/platform-request-scope.js +1 -1
  152. package/dist/src/platform-runtime-app-log-process.js +1 -1
  153. package/dist/src/platform-runtime-managed-owner.js +1 -1
  154. package/dist/src/platform-runtime-open-target.js +1 -1
  155. package/dist/src/platform-runtime-operation-host.js +2 -2
  156. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  157. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  158. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  159. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  160. package/dist/src/platform-runtime-unavailable.js +1 -1
  161. package/dist/src/platform-runtime.js +1 -1
  162. package/dist/src/platform-runtime2.js +1 -1
  163. package/dist/src/png-crop-bytes.js +1 -1
  164. package/dist/src/png-size.js +1 -1
  165. package/dist/src/png-worker-client.js +1 -1
  166. package/dist/src/png.js +1 -1
  167. package/dist/src/prepare-kind.js +1 -1
  168. package/dist/src/process.js +1 -1
  169. package/dist/src/provider-session-ownership.js +1 -1
  170. package/dist/src/provider-webdriver.js +1 -1
  171. package/dist/src/proxy.js +2 -2
  172. package/dist/src/quality-warnings.js +1 -1
  173. package/dist/src/react-native.js +1 -1
  174. package/dist/src/record-runtime.js +1 -1
  175. package/dist/src/recording.js +1 -1
  176. package/dist/src/rect-center.js +1 -1
  177. package/dist/src/register-builtins.js +1 -1
  178. package/dist/src/registry.js +36 -36
  179. package/dist/src/remote-config2.js +1 -1
  180. package/dist/src/replay-divergence.js +1 -1
  181. package/dist/src/replay.js +1 -1
  182. package/dist/src/reporting.js +1 -1
  183. package/dist/src/request-admission.js +1 -1
  184. package/dist/src/request-cancel.js +1 -1
  185. package/dist/src/request-runtime-binding.js +1 -1
  186. package/dist/src/result-serialization.js +1 -1
  187. package/dist/src/retry.js +1 -1
  188. package/dist/src/runner-artifact-manifest.js +1 -0
  189. package/dist/src/runner-cache-metadata.js +3 -2
  190. package/dist/src/runner-client.js +1 -1
  191. package/dist/src/runner-command-traits.js +1 -0
  192. package/dist/src/runner-dev-tools-security.js +1 -1
  193. package/dist/src/runner-device-readiness.js +1 -1
  194. package/dist/src/runner-disposal.js +1 -1
  195. package/dist/src/runner-error-classification.js +3 -3
  196. package/dist/src/runner-exchange.js +1 -0
  197. package/dist/src/runner-operations-facade.js +1 -1
  198. package/dist/src/runner-owner-facade.js +1 -1
  199. package/dist/src/runner-session-types.js +1 -0
  200. package/dist/src/runner-start-budget.js +1 -0
  201. package/dist/src/runner-startup-transport.js +1 -0
  202. package/dist/src/runner-xctestrun.js +1 -0
  203. package/dist/src/runner.js +1 -1
  204. package/dist/src/runtime-transport-hints.js +1 -1
  205. package/dist/src/runtime.js +1 -1
  206. package/dist/src/runtime10.js +2 -2
  207. package/dist/src/runtime2.js +3 -3
  208. package/dist/src/runtime3.js +1 -1
  209. package/dist/src/runtime4.js +5 -5
  210. package/dist/src/runtime5.js +1 -1
  211. package/dist/src/runtime6.js +1 -1
  212. package/dist/src/runtime7.js +1 -1
  213. package/dist/src/runtime8.js +1 -1
  214. package/dist/src/runtime9.js +1 -1
  215. package/dist/src/screen-recording-admission-ledger.js +1 -1
  216. package/dist/src/screen-recording-completion.js +1 -1
  217. package/dist/src/screen-recording-options.js +1 -1
  218. package/dist/src/screen-recording-resource-recovery.js +1 -1
  219. package/dist/src/screen-recording-transport.js +1 -1
  220. package/dist/src/screenshot-density.js +1 -1
  221. package/dist/src/screenshot-image.js +1 -1
  222. package/dist/src/screenshot-runtime.js +1 -1
  223. package/dist/src/screenshot.js +1 -1
  224. package/dist/src/screenshot3.js +1 -1
  225. package/dist/src/script.js +1 -1
  226. package/dist/src/scroll-command.d.ts +4 -1
  227. package/dist/src/scroll-command.js +1 -1
  228. package/dist/src/scroll-gesture.js +1 -1
  229. package/dist/src/sdk-batch-runner.js +2 -2
  230. package/dist/src/sdk-batch.js +2 -2
  231. package/dist/src/sdk-contracts.d.ts +10 -0
  232. package/dist/src/sdk-contracts.js +2 -2
  233. package/dist/src/sdk-device.js +1 -1
  234. package/dist/src/sdk-io.js +1 -1
  235. package/dist/src/sdk-remote-config.js +1 -1
  236. package/dist/src/selection.js +0 -0
  237. package/dist/src/selector-runtime.js +1 -1
  238. package/dist/src/server.js +1 -1
  239. package/dist/src/session-allocation.js +1 -1
  240. package/dist/src/session-routing.js +1 -1
  241. package/dist/src/session-runtime-admission.js +1 -1
  242. package/dist/src/session-snapshot.js +1 -1
  243. package/dist/src/session-store.js +3 -3
  244. package/dist/src/session2.js +5 -4
  245. package/dist/src/settings.js +1 -1
  246. package/dist/src/settings2.js +1 -1
  247. package/dist/src/simctl.js +1 -1
  248. package/dist/src/simulator-boot.js +1 -1
  249. package/dist/src/simulator.js +1 -1
  250. package/dist/src/snapshot-runtime-binding.js +1 -1
  251. package/dist/src/snapshot-runtime.js +1 -1
  252. package/dist/src/snapshot-state.js +1 -1
  253. package/dist/src/snapshot2.js +1 -1
  254. package/dist/src/snapshot3.js +1 -1
  255. package/dist/src/snapshot4.js +1 -1
  256. package/dist/src/src.js +1 -1
  257. package/dist/src/src7.js +1 -1
  258. package/dist/src/src8.js +2 -2
  259. package/dist/src/string-enum.js +1 -1
  260. package/dist/src/takeover.js +1 -1
  261. package/dist/src/target-evidence.js +1 -0
  262. package/dist/src/text-entry-focus.js +1 -1
  263. package/dist/src/tool-provider.js +1 -1
  264. package/dist/src/tool-provider2.js +1 -1
  265. package/dist/src/touch-runtime.js +1 -1
  266. package/dist/src/transport.js +2 -2
  267. package/dist/src/tv-remote.js +1 -1
  268. package/dist/src/type-text-runtime.js +1 -1
  269. package/dist/src/vars.js +2 -0
  270. package/dist/src/verified-file.js +1 -1
  271. package/dist/src/video.js +1 -1
  272. package/dist/src/viewport.js +1 -1
  273. package/dist/src/web.js +1 -1
  274. package/dist/src/web2.js +1 -1
  275. package/dist/src/webdriver-source.js +1 -1
  276. package/package.json +2 -2
  277. package/server.json +2 -2
  278. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.15.apk.sha256 +0 -1
  279. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.15.apk.sha256 +0 -1
  280. package/dist/src/capture-disclosure.js +0 -1
  281. package/dist/src/fold-runtime.js +0 -1
  282. package/dist/src/native-build-cache.js +0 -1
@@ -0,0 +1 @@
1
+ 8217a388cb181b785090b23258a1c412319d03869d9627f9ee5a81f6746fbe48 agent-device-android-ime-helper-0.21.17.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-ime-helper",
3
- "version": "0.21.15",
4
- "assetName": "agent-device-android-ime-helper-0.21.15.apk",
5
- "sha256": "2f8d38e6705542b327057b059c77cf3a6358fa2fc9a53e4bf5ecfb6279c441bf",
3
+ "version": "0.21.17",
4
+ "assetName": "agent-device-android-ime-helper-0.21.17.apk",
5
+ "sha256": "8217a388cb181b785090b23258a1c412319d03869d9627f9ee5a81f6746fbe48",
6
6
  "packageName": "com.callstack.agentdevice.imehelper",
7
- "versionCode": 21015,
7
+ "versionCode": 21017,
8
8
  "serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
9
9
  "broadcastProtocol": "android-ime-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ b8801f4de4f76f9ed646694b0b0785c511a7a3cfef2744bdd746055176e1bf06 agent-device-android-snapshot-helper-0.21.17.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.21.15",
4
- "releaseTag": "v0.21.15",
5
- "assetName": "agent-device-android-snapshot-helper-0.21.15.apk",
3
+ "version": "0.21.17",
4
+ "releaseTag": "v0.21.17",
5
+ "assetName": "agent-device-android-snapshot-helper-0.21.17.apk",
6
6
  "apkUrl": null,
7
- "sha256": "af733a540d518ede88f0336564d6d4d03b05191732130b65a3094228fa1bed54",
8
- "checksumName": "agent-device-android-snapshot-helper-0.21.15.apk.sha256",
7
+ "sha256": "b8801f4de4f76f9ed646694b0b0785c511a7a3cfef2744bdd746055176e1bf06",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.21.17.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 21015,
10
+ "versionCode": 21017,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
@@ -66,7 +66,6 @@ int main(int argc, const char *argv[]) {
66
66
  @property(nonatomic, assign) NSUInteger firstAlertActions;
67
67
  @property(nonatomic, assign) NSUInteger replacementAlertActions;
68
68
  @property(nonatomic, strong) UILabel *textEntryWriteBackStatus;
69
- @property(nonatomic, assign) NSUInteger textEntryRenderedEdits;
70
69
  @property(nonatomic, assign) NSUInteger textEntryWriteBacks;
71
70
  @property(nonatomic, copy, nullable) NSString *textEntryRenderedValue;
72
71
  @property(nonatomic, assign) NSTimeInterval textEntryLastEditTime;
@@ -187,8 +186,7 @@ static NSTimeInterval AgentDeviceAlertActivationBusyWindow(void) {
187
186
  - (void)updateTextEntryWriteBackStatus {
188
187
  NSTimeInterval burstSpan = self.textEntryLastEditTime - self.textEntryBurstStartTime;
189
188
  self.textEntryWriteBackStatus.text = [NSString
190
- stringWithFormat:@"edits=%lu write-backs=%lu burst-edits=%lu burst-ms=%lu min-gap-ms=%lu",
191
- (unsigned long)self.textEntryRenderedEdits,
189
+ stringWithFormat:@"write-backs=%lu burst-edits=%lu burst-ms=%lu min-gap-ms=%lu",
192
190
  (unsigned long)self.textEntryWriteBacks,
193
191
  (unsigned long)self.textEntryBurstEdits,
194
192
  (unsigned long)llround(burstSpan * 1000),
@@ -292,7 +290,6 @@ static const NSTimeInterval AgentDeviceTextEntryBurstBreakSeconds = 1.0;
292
290
  }
293
291
  } else {
294
292
  self.textEntryRenderedValue = [textField.text copy];
295
- self.textEntryRenderedEdits += 1;
296
293
  }
297
294
  [self updateTextEntryWriteBackStatus];
298
295
  }
@@ -17,21 +17,21 @@ typedef NS_ENUM(NSInteger, RunnerSynthesizedTextEntryStatus) {
17
17
 
18
18
  @interface RunnerSynthesizedTextEntry : NSObject
19
19
 
20
- // Characters per second the synthesized text-input records are typed at. Declared here, where the
21
- // typing happens, so the delivery budget that bounds a burst is charged the same pace the app sees.
22
- // The edit-acknowledge window that pace is sized for is a separate assumption about the app
23
- // (TextEntryTiming.synthesizedAcknowledgeWindowSeconds), not a value derived from this one.
24
- + (NSUInteger)typingSpeedCharactersPerSecond;
25
-
26
20
  // Synthesizes keyboard input for the current first responder without resolving an
27
21
  // XCUIElement or serializing the application's accessibility tree.
22
+ //
23
+ // `charactersPerSecond` is XCTest's `typingSpeed:` argument. The caller declares it because the
24
+ // same number is what the caller's delivery budget charges a burst (#2955): a pace owned here and
25
+ // read back from Swift would let a call site type at a speed its own budget never charged.
28
26
  + (RunnerSynthesizedTextEntryResult *)synthesizeTextWithApplication:(id)application
29
- text:(NSString *)text;
27
+ text:(NSString *)text
28
+ charactersPerSecond:(NSUInteger)charactersPerSecond;
30
29
 
31
30
  // Replaces the current first responder's contents with one synthesized Command-A record
32
- // followed by a text-input record, typed at the bounded pace declared in the implementation.
31
+ // followed by a text-input record, typed at the pace the caller declares.
33
32
  + (RunnerSynthesizedTextEntryResult *)replaceTextWithApplication:(id)application
34
- text:(NSString *)text;
33
+ text:(NSString *)text
34
+ charactersPerSecond:(NSUInteger)charactersPerSecond;
35
35
 
36
36
  @end
37
37
 
@@ -5,19 +5,10 @@
5
5
 
6
6
  static NSString *const RunnerTextSynthesisSurface = @"text";
7
7
 
8
- // XCTest's `typingSpeed:` argument is characters per second. At 60 the 11 characters of a `fill`
9
- // arrived at a fixture field across 131 ms (~13 ms per gap), which is faster than an app that owns
10
- // its field's value and re-applies it after the edit (a controlled React Native `TextInput`, an
11
- // async validator) can acknowledge: such a write lands between two characters of the burst and
12
- // erases what was typed while it was in flight, leaving a value that is stable short of the
13
- // request. 12 characters/second spaces them ~83 ms apart on average, which reduces that loss but
14
- // does not remove it: XCTest does not space the characters evenly, and two of them can reach the
15
- // app a few milliseconds apart. Against a fixture app that acknowledges each edit within 40 ms, 60
16
- // characters/second left 1 of 11 characters in 20 of 20 bursts, and this pace left 10 or 11. The
17
- // command refuses a field left short; back-pressure from the field (#2906) is what would prevent
18
- // it. The app-owned-value lane test pins the average spacing the app sees, and the delivery budget
19
- // in TextEntryTiming bounds what the pace costs a long text.
20
- static const NSUInteger RunnerTextEntryTypingSpeedCharactersPerSecond = 12;
8
+ // The pace (`typingSpeed:`) is a caller argument, not a constant here: TextEntryTiming owns it so
9
+ // the synthesized delivery budget charges the pace the app actually sees (#2955). XCTest's
10
+ // `typingSpeed:` is characters per second, and it spaces them unevenly — two characters of a paced
11
+ // burst can reach the app a few milliseconds apart at any pace.
21
12
 
22
13
  typedef id (*RunnerTextMsgSendInit)(id, SEL, NSString *);
23
14
  typedef id (*RunnerTextMsgSendInitPath)(id, SEL);
@@ -49,6 +40,7 @@ static RunnerSynthesizedTextEntryResult *RunnerTextEntryFailed(NSString *message
49
40
  static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
50
41
  id application,
51
42
  NSString *text,
43
+ NSUInteger charactersPerSecond,
52
44
  BOOL replace
53
45
  );
54
46
 
@@ -65,18 +57,16 @@ static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
65
57
 
66
58
  @implementation RunnerSynthesizedTextEntry
67
59
 
68
- + (NSUInteger)typingSpeedCharactersPerSecond {
69
- return RunnerTextEntryTypingSpeedCharactersPerSecond;
70
- }
71
-
72
60
  + (RunnerSynthesizedTextEntryResult *)synthesizeTextWithApplication:(id)application
73
- text:(NSString *)text {
74
- return RunnerSynthesizeTextWithMode(application, text, NO);
61
+ text:(NSString *)text
62
+ charactersPerSecond:(NSUInteger)charactersPerSecond {
63
+ return RunnerSynthesizeTextWithMode(application, text, charactersPerSecond, NO);
75
64
  }
76
65
 
77
66
  + (RunnerSynthesizedTextEntryResult *)replaceTextWithApplication:(id)application
78
- text:(NSString *)text {
79
- return RunnerSynthesizeTextWithMode(application, text, YES);
67
+ text:(NSString *)text
68
+ charactersPerSecond:(NSUInteger)charactersPerSecond {
69
+ return RunnerSynthesizeTextWithMode(application, text, charactersPerSecond, YES);
80
70
  }
81
71
 
82
72
  @end
@@ -84,6 +74,7 @@ static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
84
74
  static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
85
75
  id application,
86
76
  NSString *text,
77
+ NSUInteger charactersPerSecond,
87
78
  BOOL replace
88
79
  ) {
89
80
  @try {
@@ -151,7 +142,7 @@ static RunnerSynthesizedTextEntryResult *RunnerSynthesizeTextWithMode(
151
142
  bridge.typeTextSelector,
152
143
  text,
153
144
  0.0,
154
- RunnerTextEntryTypingSpeedCharactersPerSecond,
145
+ charactersPerSecond,
155
146
  YES
156
147
  );
157
148
  ((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.core.addPathSelector, path);
@@ -20,13 +20,4 @@ enum SystemSurfaceHostRegistry {
20
20
  SystemSurfaceHost(bundleId: "com.apple.SafariViewService", kind: .webAuth),
21
21
  SystemSurfaceHost(bundleId: "com.apple.PassbookUIService", kind: .payment),
22
22
  ]
23
-
24
- static func host(forBundleId bundleId: String?) -> SystemSurfaceHost? {
25
- guard let bundleId else { return nil }
26
- return hosts.first { $0.bundleId == bundleId }
27
- }
28
-
29
- static func isSystemSurfaceHost(_ bundleId: String?) -> Bool {
30
- host(forBundleId: bundleId) != nil
31
- }
32
23
  }
@@ -68,6 +68,35 @@ extension RunnerTests {
68
68
 
69
69
 
70
70
 
71
+
72
+ @MainActor
73
+ func executePasteboardWrite(command: Command) -> Response {
74
+ guard let text = command.text else {
75
+ return Response(
76
+ ok: false,
77
+ error: ErrorPayload(
78
+ code: "INVALID_ARGS",
79
+ message: "pasteboardWrite requires text",
80
+ hint: "Set text to the string the pasteboard should hold."
81
+ )
82
+ )
83
+ }
84
+ #if os(iOS) || os(visionOS)
85
+ UIPasteboard.general.string = text
86
+ return Response(ok: true, data: DataPayload(message: "pasteboard written"))
87
+ #else
88
+ return Response(
89
+ ok: false,
90
+ error: ErrorPayload(
91
+ code: "UNSUPPORTED_OPERATION",
92
+ message: "pasteboardWrite is supported on iOS and visionOS runners"
93
+ )
94
+ )
95
+ #endif
96
+ }
97
+
98
+
99
+
71
100
  static func applicationStateName(_ state: XCUIApplication.State) -> String {
72
101
  switch state {
73
102
  case .unknown: return "unknown"
@@ -423,6 +452,8 @@ extension RunnerTests {
423
452
  return executeUptime()
424
453
  case .appState:
425
454
  return executeAppState(command: command)
455
+ case .pasteboardWrite:
456
+ return executePasteboardWrite(command: command)
426
457
  case .activate:
427
458
  guard
428
459
  let bundleId = command.appBundleId?.trimmingCharacters(in: .whitespacesAndNewlines),
@@ -14,7 +14,7 @@ extension RunnerTests {
14
14
  }
15
15
  switch command.command {
16
16
  case .status, .activate, .terminate, .targetReset, .shutdown, .recordStart, .recordStop, .uptime,
17
- .appState, .snapshot:
17
+ .appState, .pasteboardWrite, .snapshot:
18
18
  return Response(
19
19
  ok: false,
20
20
  error: ErrorPayload(
@@ -139,7 +139,7 @@ final class RunnerCommandJournal {
139
139
  .remotePress, .type, .swipe, .scroll, .desktopScroll, .findText, .querySelector, .readText,
140
140
  .backInApp, .backSystem, .home, .rotate, .appSwitcher, .actionButton, .keyboardDismiss, .keyboardReturn,
141
141
  .alert, .sequence, .gesture, .gestureViewport, .recordStart, .recordStop,
142
- .status, .uptime, .appState, .activate, .terminate, .targetReset, .shutdown:
142
+ .status, .uptime, .appState, .pasteboardWrite, .activate, .terminate, .targetReset, .shutdown:
143
143
  return true
144
144
  }
145
145
  }
@@ -34,6 +34,7 @@ enum CommandType: String, Codable, CaseIterable {
34
34
  case status
35
35
  case uptime
36
36
  case appState
37
+ case pasteboardWrite
37
38
  case activate
38
39
  case terminate
39
40
  case targetReset
@@ -152,6 +153,11 @@ fileprivate extension CommandTraits {
152
153
 
153
154
 
154
155
 
156
+ static let deviceState = CommandTraits(launchPolicy: .noApp)
157
+
158
+
159
+
160
+
155
161
  static let presentedSurfaceMutation = CommandTraits(
156
162
  launchPolicy: .presentedSurface,
157
163
  convertsRecordedFailure: true
@@ -253,6 +259,9 @@ extension Command {
253
259
  case .recordStop, .uptime, .terminate, .targetReset, .shutdown:
254
260
  return .runnerLifecycle
255
261
 
262
+ case .pasteboardWrite:
263
+ return .deviceState
264
+
256
265
  case .actionButton:
257
266
  return .presentedSurfaceMutation
258
267
 
@@ -209,6 +209,19 @@ extension RunnerTests {
209
209
 
210
210
 
211
211
 
212
+ static func planVerdictReason(
213
+ xCTestTierRan: Bool,
214
+ state: SnapshotXCTestChannelPlanState,
215
+ firstFailure: (reason: String, code: String)?
216
+ ) -> (reason: String, code: String)? {
217
+ guard xCTestTierRan, state == .deferredToIndependentBackend else { return firstFailure }
218
+ return xcTestChannelStateFirstFailure(.boundedXCTestProbe)
219
+ }
220
+
221
+
222
+
223
+
224
+
212
225
  static func snapshotXCTestChannelTreatedAsPenalized(
213
226
  penalized: Bool,
214
227
  preferredBackend: String?
@@ -251,10 +264,14 @@ extension RunnerTests {
251
264
  let availablePlan = plan.filter { availableBackends.contains($0) }
252
265
  let recoveryPlan = availablePlan.filter { !$0.usesXCTestAccessibilityChannel }
253
266
  if !recoveryPlan.isEmpty {
267
+
268
+
269
+
270
+
254
271
  return EffectiveSnapshotCapturePlan(
255
- plan: recoveryPlan,
272
+ plan: recoveryPlan + availablePlan.filter { $0 == .recursiveTree },
256
273
  xCTestChannelState: .deferredToIndependentBackend,
257
- treeCaptureSliceBudgetOverride: nil,
274
+ treeCaptureSliceBudgetOverride: Self.penalizedXCTestProbeTreeSliceBudget,
258
275
  preferredBackend: nil
259
276
  )
260
277
  }
@@ -285,6 +302,7 @@ extension RunnerTests {
285
302
 
286
303
  let deadline = deadline ?? Date().addingTimeInterval(Self.snapshotPlanBudget)
287
304
  let suppressXCTestPenalty = snapshotXCTestPenaltyWarmupExemption.consume()
305
+ var xCTestTierRan = false
288
306
 
289
307
 
290
308
 
@@ -344,6 +362,7 @@ extension RunnerTests {
344
362
  }
345
363
  continue
346
364
  }
365
+ if kind.usesXCTestAccessibilityChannel { xCTestTierRan = true }
347
366
  let attempt = try captureWithBackend(
348
367
  kind,
349
368
  target: target,
@@ -391,18 +410,23 @@ extension RunnerTests {
391
410
  }
392
411
 
393
412
  let recovered = kind != effectivePlan.first || effective.xCTestChannelState != .normal
413
+ let verdictReason = Self.planVerdictReason(
414
+ xCTestTierRan: kind.usesXCTestAccessibilityChannel,
415
+ state: effective.xCTestChannelState,
416
+ firstFailure: firstFailure
417
+ )
394
418
  if recovered {
395
419
  NSLog(
396
420
  "AGENT_DEVICE_RUNNER_SNAPSHOT_RECOVERED backend=%@ reason=%@",
397
421
  kind.rawValue,
398
- firstFailure?.reason ?? "sparse tree"
422
+ verdictReason?.reason ?? "sparse tree"
399
423
  )
400
424
  }
401
425
  return stampedSnapshotPayload(
402
426
  capture,
403
427
  backend: kind,
404
428
  state: recovered ? .recovered : .healthy,
405
- reason: recovered || firstFailure?.code == "requested-backend" ? firstFailure : nil
429
+ reason: recovered || firstFailure?.code == "requested-backend" ? verdictReason : nil
406
430
  )
407
431
  }
408
432
 
@@ -425,13 +449,18 @@ extension RunnerTests {
425
449
  }
426
450
  }
427
451
 
452
+ let terminalReason = Self.planVerdictReason(
453
+ xCTestTierRan: xCTestTierRan,
454
+ state: effective.xCTestChannelState,
455
+ firstFailure: firstFailure
456
+ )
428
457
  let fallbackPayload =
429
- best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state: .sparse, reason: firstFailure) }
458
+ best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state: .sparse, reason: terminalReason) }
430
459
  ?? stampedSnapshotPayload(
431
460
  SnapshotBackendCapture(payload: sparseTruncatedSnapshotPayload(), effectiveDepth: nil),
432
461
  backend: effectivePlan.last ?? plan.last ?? .recursiveTree,
433
462
  state: .sparse,
434
- reason: firstFailure
463
+ reason: terminalReason
435
464
  )
436
465
  return fallbackPayload
437
466
  }
@@ -491,6 +520,11 @@ extension RunnerTests {
491
520
  }
492
521
  return (sweep.acquisition, sweep.outcome)
493
522
  case .privateAX:
523
+
524
+
525
+
526
+
527
+
494
528
  return (
495
529
  self.privateAXSnapshotAcquisition(
496
530
  target: target,