agent-device 0.21.14 → 0.21.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.14.apk → agent-device-android-ime-helper-0.21.16.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.16.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.14.manifest.json → agent-device-android-ime-helper-0.21.16.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.16.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.16.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.14.manifest.json → agent-device-android-snapshot-helper-0.21.16.manifest.json} +6 -6
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +84 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerMainOwnedState.swift +27 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +10 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +21 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +40 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +179 -91
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -49
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +11 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +136 -29
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +6 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +8 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +56 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +18 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +9 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +2 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +245 -41
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +47 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +7 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +115 -111
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +17 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +8 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +12 -11
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +7 -4
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +15 -8
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +1 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +26 -9
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -0
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +1 -1
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.d.ts +1 -8
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android-snapshot-quality.js +1 -0
- package/dist/src/android-system-chrome.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-runtime2.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/capture-disclosure.js +1 -1
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +3 -2
- package/dist/src/cli.js +4 -4
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +103 -96
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +3 -3
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lease-beat.js +1 -0
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-transport.js +1 -0
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +15 -2
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/format.js +1 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan-types.d.ts +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host.js +1 -1
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact-facade.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -1
- package/dist/src/interactor.js +5 -4
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-engine.js +1 -0
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-download-file.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +16 -3
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +17 -17
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/native-build-cache.js +1 -1
- package/dist/src/observation.js +1 -1
- package/dist/src/overlay.js +3 -0
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-size.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/provider-session-ownership.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +36 -36
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +1 -1
- package/dist/src/reporting.js +1 -1
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/runner-artifact-manifest.js +1 -0
- package/dist/src/runner-cache-metadata.js +3 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +3 -3
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +1 -3
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.d.ts +13 -6
- package/dist/src/scroll-command.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +38 -10
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +4 -4
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -1
- package/dist/src/snapshot-desktop-projection.js +1 -1
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src4.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/stop-sequence.js +1 -1
- package/dist/src/string-enum.js +1 -1
- package/dist/src/surface-snapshot.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/transport.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.14.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk.sha256 +0 -1
- package/dist/src/absence-observation-errors.js +0 -1
- package/dist/src/runner-presentation.js +0 -1
- package/dist/src/semantic-index.js +0 -1
- package/dist/src/snapshot-scope.js +0 -1
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift
CHANGED
|
@@ -3,6 +3,7 @@ import XCTest
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
extension RunnerTests {
|
|
6
|
+
@MainActor
|
|
6
7
|
func typeTextReliably(
|
|
7
8
|
app: XCUIApplication,
|
|
8
9
|
target: TextEntryTarget,
|
|
@@ -135,6 +136,39 @@ extension RunnerTests {
|
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
let synthesizedTypePlan = Self.synthesizedTextPlan(
|
|
145
|
+
characterCount: text.count,
|
|
146
|
+
delaySeconds: delaySeconds,
|
|
147
|
+
selectsExistingText: false,
|
|
148
|
+
peelsWarmupCharacter: repairMode != .none
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
let synthesizedTypeCarriesTheCommand = !SynthesizedDeliveryBudget.exceeds(synthesizedTypePlan)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
func typeApplicationWide(_ value: String, reason: String) -> (element: XCUIElement?, failure: TextEntryFailure?) {
|
|
161
|
+
NSLog(
|
|
162
|
+
"AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=xctest-application-fallback reason=%@ chars=%d commandChars=%d",
|
|
163
|
+
reason,
|
|
164
|
+
value.count,
|
|
165
|
+
text.count
|
|
166
|
+
)
|
|
167
|
+
textEntryRoute = "xctest-application-fallback"
|
|
168
|
+
app.typeText(value)
|
|
169
|
+
return (resolveTextEntryElement(app: app, target: activeTarget), nil)
|
|
170
|
+
}
|
|
171
|
+
|
|
138
172
|
func typeIntoCurrentTarget(_ value: String) -> (element: XCUIElement?, failure: TextEntryFailure?) {
|
|
139
173
|
#if os(iOS)
|
|
140
174
|
if shouldUseSynthesizedFirstResponderType {
|
|
@@ -162,17 +196,18 @@ extension RunnerTests {
|
|
|
162
196
|
return (currentTarget, nil)
|
|
163
197
|
} else if activeTarget.prefersFocusedElement && isKeyboardVisible(app: app) {
|
|
164
198
|
#if os(iOS)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
guard synthesizedTypeCarriesTheCommand else {
|
|
204
|
+
return typeApplicationWide(value, reason: "delivery-budget")
|
|
205
|
+
}
|
|
165
206
|
textEntryRoute = "synthesized-first-responder"
|
|
166
207
|
NSLog("AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder")
|
|
167
|
-
|
|
168
|
-
app: app,
|
|
169
|
-
text: value,
|
|
170
|
-
replacingExistingText: false
|
|
171
|
-
)
|
|
172
|
-
switch action {
|
|
208
|
+
switch synthesizer.enterText(app: app, text: value, replacingExistingText: false) {
|
|
173
209
|
case .fallback:
|
|
174
|
-
|
|
175
|
-
app.typeText(value)
|
|
210
|
+
return typeApplicationWide(value, reason: "synthesis-unavailable")
|
|
176
211
|
case .raise(let message):
|
|
177
212
|
NSException(
|
|
178
213
|
name: NSExceptionName.internalInconsistencyException,
|
|
@@ -200,131 +235,100 @@ extension RunnerTests {
|
|
|
200
235
|
)
|
|
201
236
|
}
|
|
202
237
|
|
|
203
|
-
func
|
|
204
|
-
|
|
238
|
+
func readBackWarmupCharacter(_ peeledCharacter: String) {
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
let warmupExpectedText = expectedTextEntryValue(
|
|
243
|
+
typedText: peeledCharacter,
|
|
244
|
+
mode: repairMode,
|
|
245
|
+
initialText: initialText
|
|
246
|
+
)
|
|
247
|
+
guard let warmupExpectedText else {
|
|
205
248
|
sleepFor(TextEntryTiming.pollInterval)
|
|
206
249
|
return
|
|
207
250
|
}
|
|
208
251
|
let deadline = Date().addingTimeInterval(TextEntryTiming.warmupValueTimeout)
|
|
209
252
|
while Date() < deadline {
|
|
210
|
-
if editableTextValue(for: resolveTextEntryElement(app: app, target:
|
|
253
|
+
if editableTextValue(for: resolveTextEntryElement(app: app, target: activeTarget)) == warmupExpectedText {
|
|
211
254
|
return
|
|
212
255
|
}
|
|
213
256
|
sleepFor(TextEntryTiming.pollInterval)
|
|
214
257
|
}
|
|
215
258
|
}
|
|
216
259
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
var typedTarget: XCUIElement?
|
|
263
|
+
var sawWarmupPost = false
|
|
264
|
+
var planFailure: TextEntryResult?
|
|
265
|
+
var stepStartedAt = Date()
|
|
266
|
+
let pacedStartedAt = Date()
|
|
267
|
+
runSynthesizedTextPlan(
|
|
268
|
+
synthesizedTypePlan,
|
|
269
|
+
text: text,
|
|
270
|
+
post: { slice, step in
|
|
271
|
+
stepStartedAt = Date()
|
|
272
|
+
let dispatch = typeIntoCurrentTarget(slice)
|
|
223
273
|
if let failure = dispatch.failure {
|
|
224
|
-
|
|
274
|
+
planFailure = dispatchFailureResult(failure)
|
|
275
|
+
return .stop
|
|
225
276
|
}
|
|
226
277
|
typedTarget = dispatch.element ?? typedTarget
|
|
227
|
-
if
|
|
228
|
-
|
|
278
|
+
if step.warmsUpField {
|
|
279
|
+
|
|
280
|
+
activeTarget = activeTarget.withElement(typedTarget)
|
|
229
281
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
282
|
+
return .posted
|
|
283
|
+
},
|
|
284
|
+
waitAfterWarmupCharacter: { peeledCharacter in
|
|
285
|
+
let warmupStartedAt = Date()
|
|
286
|
+
readBackWarmupCharacter(peeledCharacter)
|
|
287
|
+
logTextEntryPhase(
|
|
288
|
+
commandId: commandId,
|
|
289
|
+
phase: "warmup",
|
|
290
|
+
startedAt: warmupStartedAt,
|
|
291
|
+
chars: 1,
|
|
292
|
+
mode: repairMode
|
|
293
|
+
)
|
|
294
|
+
},
|
|
295
|
+
didPostStep: { step in
|
|
296
|
+
guard !synthesizedTypePlan.pacesEveryCharacter else {
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
let phase: String
|
|
300
|
+
if step.warmsUpField {
|
|
301
|
+
phase = "type-first"
|
|
302
|
+
sawWarmupPost = true
|
|
303
|
+
} else {
|
|
304
|
+
phase = sawWarmupPost ? "type-remaining" : "type-all"
|
|
305
|
+
}
|
|
306
|
+
logTextEntryPhase(
|
|
307
|
+
commandId: commandId,
|
|
308
|
+
phase: phase,
|
|
309
|
+
startedAt: stepStartedAt,
|
|
310
|
+
chars: step.characterCount,
|
|
311
|
+
mode: repairMode
|
|
246
312
|
)
|
|
247
313
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
expectedText: expectedText,
|
|
253
|
-
repairMode: repairMode
|
|
254
|
-
)
|
|
314
|
+
)
|
|
315
|
+
if synthesizedTypePlan.pacesEveryCharacter {
|
|
316
|
+
|
|
317
|
+
|
|
255
318
|
logTextEntryPhase(
|
|
256
319
|
commandId: commandId,
|
|
257
|
-
phase: "
|
|
258
|
-
startedAt:
|
|
259
|
-
chars:
|
|
320
|
+
phase: "type-delayed",
|
|
321
|
+
startedAt: pacedStartedAt,
|
|
322
|
+
chars: text.count,
|
|
260
323
|
mode: repairMode
|
|
261
324
|
)
|
|
262
|
-
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: text.count, mode: repairMode)
|
|
263
|
-
result.textEntryRoute = textEntryRoute
|
|
264
|
-
return result
|
|
265
325
|
}
|
|
266
326
|
|
|
267
|
-
|
|
268
|
-
if
|
|
269
|
-
|
|
270
|
-
let firstStartedAt = Date()
|
|
271
|
-
let firstDispatch = typeIntoCurrentTarget(firstCharacter)
|
|
272
|
-
if let failure = firstDispatch.failure {
|
|
273
|
-
return dispatchFailureResult(failure)
|
|
274
|
-
}
|
|
275
|
-
var firstTypedTarget = firstDispatch.element
|
|
276
|
-
logTextEntryPhase(
|
|
277
|
-
commandId: commandId,
|
|
278
|
-
phase: "type-first",
|
|
279
|
-
startedAt: firstStartedAt,
|
|
280
|
-
chars: 1,
|
|
281
|
-
mode: repairMode
|
|
282
|
-
)
|
|
283
|
-
activeTarget = activeTarget.withElement(firstTypedTarget)
|
|
284
|
-
let warmupExpectedText = expectedTextEntryValue(
|
|
285
|
-
typedText: firstCharacter,
|
|
286
|
-
mode: repairMode,
|
|
287
|
-
initialText: initialText
|
|
288
|
-
)
|
|
289
|
-
let warmupStartedAt = Date()
|
|
290
|
-
waitForWarmupValue(warmupExpectedText, target: activeTarget)
|
|
291
|
-
logTextEntryPhase(
|
|
292
|
-
commandId: commandId,
|
|
293
|
-
phase: "warmup",
|
|
294
|
-
startedAt: warmupStartedAt,
|
|
295
|
-
chars: 1,
|
|
296
|
-
mode: repairMode
|
|
297
|
-
)
|
|
298
|
-
let remainingText = String(characters.dropFirst())
|
|
299
|
-
let remainingStartedAt = Date()
|
|
300
|
-
let remainingDispatch = typeIntoCurrentTarget(remainingText)
|
|
301
|
-
if let failure = remainingDispatch.failure {
|
|
302
|
-
return dispatchFailureResult(failure)
|
|
303
|
-
}
|
|
304
|
-
firstTypedTarget = remainingDispatch.element ?? firstTypedTarget
|
|
305
|
-
logTextEntryPhase(
|
|
306
|
-
commandId: commandId,
|
|
307
|
-
phase: "type-remaining",
|
|
308
|
-
startedAt: remainingStartedAt,
|
|
309
|
-
chars: characters.count - 1,
|
|
310
|
-
mode: repairMode
|
|
311
|
-
)
|
|
312
|
-
typedTarget = firstTypedTarget
|
|
313
|
-
} else {
|
|
314
|
-
let typeStartedAt = Date()
|
|
315
|
-
let dispatch = typeIntoCurrentTarget(text)
|
|
316
|
-
if let failure = dispatch.failure {
|
|
317
|
-
return dispatchFailureResult(failure)
|
|
318
|
-
}
|
|
319
|
-
typedTarget = dispatch.element
|
|
320
|
-
logTextEntryPhase(
|
|
321
|
-
commandId: commandId,
|
|
322
|
-
phase: "type-all",
|
|
323
|
-
startedAt: typeStartedAt,
|
|
324
|
-
chars: characters.count,
|
|
325
|
-
mode: repairMode
|
|
326
|
-
)
|
|
327
|
+
|
|
328
|
+
if let failure = planFailure {
|
|
329
|
+
return failure
|
|
327
330
|
}
|
|
331
|
+
activeTarget = activeTarget.withElement(typedTarget)
|
|
328
332
|
if repairMode == .none {
|
|
329
333
|
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: text.count, mode: repairMode)
|
|
330
334
|
return TextEntryResult(
|
|
@@ -338,7 +342,7 @@ extension RunnerTests {
|
|
|
338
342
|
let verifyStartedAt = Date()
|
|
339
343
|
var result = verifyTextEntryWithRepairIfNeeded(
|
|
340
344
|
app: app,
|
|
341
|
-
target: activeTarget
|
|
345
|
+
target: activeTarget,
|
|
342
346
|
expectedText: expectedText,
|
|
343
347
|
repairMode: repairMode
|
|
344
348
|
)
|
|
@@ -346,7 +350,7 @@ extension RunnerTests {
|
|
|
346
350
|
commandId: commandId,
|
|
347
351
|
phase: "verify",
|
|
348
352
|
startedAt: verifyStartedAt,
|
|
349
|
-
chars:
|
|
353
|
+
chars: text.count,
|
|
350
354
|
mode: repairMode
|
|
351
355
|
)
|
|
352
356
|
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: text.count, mode: repairMode)
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift
CHANGED
|
@@ -33,11 +33,7 @@ extension RunnerTests {
|
|
|
33
33
|
let combined = buffer + data
|
|
34
34
|
if let body = self.parseRequest(data: combined) {
|
|
35
35
|
self.handleRequestBody(body) { [weak self] result in
|
|
36
|
-
self?.
|
|
37
|
-
if result.shouldFinish {
|
|
38
|
-
self?.finish()
|
|
39
|
-
}
|
|
40
|
-
}
|
|
36
|
+
self?.sendResult(result, over: connection)
|
|
41
37
|
}
|
|
42
38
|
} else {
|
|
43
39
|
self.receiveRequest(connection: connection, buffer: combined)
|
|
@@ -45,10 +41,21 @@ extension RunnerTests {
|
|
|
45
41
|
}
|
|
46
42
|
}
|
|
47
43
|
|
|
44
|
+
private func sendResult(
|
|
45
|
+
_ result: (data: Data, shouldFinish: Bool),
|
|
46
|
+
over connection: NWConnection
|
|
47
|
+
) {
|
|
48
|
+
sendResponse(result.data, over: connection) { [weak self] in
|
|
49
|
+
if result.shouldFinish {
|
|
50
|
+
self?.finish()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
private func sendResponse(
|
|
49
56
|
_ response: Data,
|
|
50
57
|
over connection: NWConnection,
|
|
51
|
-
afterSend: @escaping () -> Void = {}
|
|
58
|
+
afterSend: @escaping @Sendable () -> Void = {}
|
|
52
59
|
) {
|
|
53
60
|
connection.send(content: response, isComplete: true, completion: .contentProcessed { error in
|
|
54
61
|
if let error {
|
|
@@ -89,7 +96,7 @@ extension RunnerTests {
|
|
|
89
96
|
|
|
90
97
|
private func handleRequestBody(
|
|
91
98
|
_ body: Data,
|
|
92
|
-
completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
|
|
99
|
+
completion: @escaping @Sendable ((data: Data, shouldFinish: Bool)) -> Void
|
|
93
100
|
) {
|
|
94
101
|
guard String(data: body, encoding: .utf8) != nil else {
|
|
95
102
|
completion((
|
|
@@ -187,7 +194,7 @@ extension RunnerTests {
|
|
|
187
194
|
|
|
188
195
|
func enqueueAccepted(
|
|
189
196
|
command: Command,
|
|
190
|
-
completion: @escaping (Result<Response, Error>) -> Void
|
|
197
|
+
completion: @escaping @Sendable (Result<Response, Error>) -> Void
|
|
191
198
|
) {
|
|
192
199
|
commandJournal.accept(command: command)
|
|
193
200
|
commandExecutionQueue.async {
|
|
@@ -202,7 +209,7 @@ extension RunnerTests {
|
|
|
202
209
|
|
|
203
210
|
func attachToInFlightCommandIfNeeded(
|
|
204
211
|
command: Command,
|
|
205
|
-
completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
|
|
212
|
+
completion: @escaping @Sendable ((data: Data, shouldFinish: Bool)) -> Void
|
|
206
213
|
) -> Bool {
|
|
207
214
|
guard let commandId = command.commandId?.trimmedNonEmpty else { return false }
|
|
208
215
|
inFlightCommandLock.lock()
|
|
@@ -226,7 +233,7 @@ extension RunnerTests {
|
|
|
226
233
|
result: (data: Data, shouldFinish: Bool),
|
|
227
234
|
completion: ((data: Data, shouldFinish: Bool)) -> Void
|
|
228
235
|
) {
|
|
229
|
-
var waiters: [((data: Data, shouldFinish: Bool)) -> Void] = []
|
|
236
|
+
var waiters: [@Sendable ((data: Data, shouldFinish: Bool)) -> Void] = []
|
|
230
237
|
if let commandId = command.commandId?.trimmedNonEmpty {
|
|
231
238
|
inFlightCommandLock.lock()
|
|
232
239
|
inFlightCommandIds.remove(commandId)
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift
CHANGED
|
@@ -52,23 +52,22 @@ extension RunnerTests {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
func elementHasFocus(_ element: XCUIElement) -> Bool {
|
|
55
|
-
|
|
56
|
-
_ = RunnerObjCExceptionCatcher.catchException({
|
|
57
|
-
if let value = (element as NSObject).value(forKey: "hasFocus") as? Bool {
|
|
58
|
-
focused = value
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
return focused
|
|
55
|
+
return focusBool(element as NSObject)
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
func activateElement(
|
|
58
|
+
func activateElement(
|
|
59
|
+
app: XCUIApplication,
|
|
60
|
+
element: XCUIElement,
|
|
61
|
+
action: String,
|
|
62
|
+
resolvedFrame: CGRect? = nil
|
|
63
|
+
) -> RunnerInteractionOutcome {
|
|
65
64
|
if let outcome = selectFocusedTvElement(app: app, element: element, action: action) {
|
|
66
65
|
return outcome
|
|
67
66
|
}
|
|
68
67
|
#if os(tvOS)
|
|
69
68
|
return performElementTap(element)
|
|
70
69
|
#else
|
|
71
|
-
let frame = element.frame
|
|
70
|
+
let frame = resolvedFrame ?? element.frame
|
|
72
71
|
if !frame.isEmpty {
|
|
73
72
|
|
|
74
73
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift
CHANGED
|
@@ -2,6 +2,7 @@ import XCTest
|
|
|
2
2
|
import AgentDeviceSnapshotPresentation
|
|
3
3
|
|
|
4
4
|
extension RunnerTests {
|
|
5
|
+
@MainActor
|
|
5
6
|
func executeTypeCommand(activeApp: XCUIApplication, command: Command) -> Response {
|
|
6
7
|
guard let text = command.text else {
|
|
7
8
|
return Response(ok: false, error: ErrorPayload(message: "type requires text"))
|
|
@@ -18,7 +19,7 @@ extension RunnerTests {
|
|
|
18
19
|
: nil
|
|
19
20
|
let focusStartedAt = Date()
|
|
20
21
|
#if os(iOS)
|
|
21
|
-
let xCTestChannelPenalized = isSnapshotXCTestChannelPenalized(bundleId:
|
|
22
|
+
let xCTestChannelPenalized = isSnapshotXCTestChannelPenalized(bundleId: mainOwned.bundleId)
|
|
22
23
|
var resolvedCoordinateTarget: TextEntryTarget?
|
|
23
24
|
if Self.shouldUseResolvedCoordinateTextEntryRoute(
|
|
24
25
|
repairMode: textEntryMode,
|
|
@@ -54,11 +54,7 @@ final class RunnerTests: XCTestCase {
|
|
|
54
54
|
let commandExecutionQueue = DispatchQueue(label: "agent-device.runner.commands")
|
|
55
55
|
let app = XCUIApplication()
|
|
56
56
|
lazy var springboard = XCUIApplication(bundleIdentifier: Self.springboardBundleId)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
var currentApp: XCUIApplication?
|
|
60
|
-
var currentBundleId: String?
|
|
61
|
-
var currentAppProcessIdentifier: Int?
|
|
57
|
+
let mainOwned = RunnerMainOwnedState()
|
|
62
58
|
|
|
63
59
|
|
|
64
60
|
var pendingTargetActivation: TargetActivationFactPayload?
|
|
@@ -68,7 +64,7 @@ final class RunnerTests: XCTestCase {
|
|
|
68
64
|
|
|
69
65
|
var textEntryTapWitness: TextEntryTapWitness?
|
|
70
66
|
let maxRequestBytes = 2 * 1024 * 1024
|
|
71
|
-
let mainThreadExecutionTimeout: TimeInterval = 30
|
|
67
|
+
static let mainThreadExecutionTimeout: TimeInterval = 30
|
|
72
68
|
let appExistenceTimeout: TimeInterval = 30
|
|
73
69
|
let retryCooldown: TimeInterval = 0.2
|
|
74
70
|
let postSnapshotInteractionDelay: TimeInterval = 0.2
|
|
@@ -83,27 +79,25 @@ final class RunnerTests: XCTestCase {
|
|
|
83
79
|
|
|
84
80
|
|
|
85
81
|
let recordingFrameCaptureTimeout: TimeInterval = 1
|
|
86
|
-
var needsPostSnapshotInteractionDelay = false
|
|
87
82
|
|
|
88
83
|
|
|
89
84
|
|
|
90
85
|
|
|
91
86
|
var lastLoggedFastAppGuardLine: String?
|
|
92
87
|
var lastLoggedGesturePolicyLines: [SynthesizedGesturePolicyKind: String] = [:]
|
|
93
|
-
var runnerMarkerWriter: (String) -> Void = { NSLog("%@", $0) }
|
|
88
|
+
var runnerMarkerWriter: @MainActor (String) -> Void = { NSLog("%@", $0) }
|
|
94
89
|
|
|
95
90
|
|
|
96
91
|
|
|
97
92
|
|
|
98
93
|
var firstInteractionReadyUptime: TimeInterval?
|
|
99
|
-
var runnerAccessibilityHealth: RunnerAccessibilityHealth = .unknown
|
|
100
94
|
var activeRecording: ScreenRecorder?
|
|
101
95
|
let commandJournal = RunnerCommandJournal()
|
|
102
96
|
|
|
103
97
|
|
|
104
98
|
let inFlightCommandLock = NSLock()
|
|
105
99
|
var inFlightCommandIds: Set<String> = []
|
|
106
|
-
var inFlightCommandWaiters: [String: [((data: Data, shouldFinish: Bool)) -> Void]] = [:]
|
|
100
|
+
var inFlightCommandWaiters: [String: [@Sendable ((data: Data, shouldFinish: Bool)) -> Void]] = [:]
|
|
107
101
|
|
|
108
102
|
|
|
109
103
|
|
|
@@ -206,6 +200,13 @@ final class RunnerTests: XCTestCase {
|
|
|
206
200
|
|
|
207
201
|
|
|
208
202
|
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
209
210
|
|
|
210
211
|
|
|
211
212
|
|
|
@@ -316,7 +317,7 @@ final class RunnerTests: XCTestCase {
|
|
|
316
317
|
deadline: .now() + xctestIdleKeepaliveInterval,
|
|
317
318
|
repeating: xctestIdleKeepaliveInterval
|
|
318
319
|
)
|
|
319
|
-
idleKeepaliveTimer.setEventHandler {
|
|
320
|
+
idleKeepaliveTimer.setEventHandler { @Sendable in
|
|
320
321
|
NSLog("AGENT_DEVICE_RUNNER_IDLE_KEEPALIVE")
|
|
321
322
|
}
|
|
322
323
|
idleKeepaliveTimer.resume()
|
|
@@ -2,12 +2,15 @@ import Foundation
|
|
|
2
2
|
import CoreGraphics
|
|
3
3
|
|
|
4
4
|
public enum SnapshotGeometry {
|
|
5
|
-
/// Twin of `isPositiveFiniteRect` in `packages/kernel/src/rect.ts
|
|
6
|
-
///
|
|
5
|
+
/// Twin of `isPositiveFiniteRect` in `packages/kernel/src/rect.ts`, and the one place the
|
|
6
|
+
/// `hittable` rule asks whether a box may be plotted or measured (#2891). Three refusals, each
|
|
7
|
+
/// reachable by a different input: a non-finite component, a finite box wide enough to overflow
|
|
8
|
+
/// its own right or bottom edge, and `CGRect.infinite`, which is built of finite components and
|
|
9
|
+
/// finite extents and so is refused by identity alone.
|
|
7
10
|
public static func isPositiveFinite(_ rect: CGRect) -> Bool {
|
|
8
11
|
!rect.isInfinite
|
|
9
|
-
&& rect.
|
|
10
|
-
&& rect.
|
|
12
|
+
&& rect.minX.isFinite && rect.minY.isFinite
|
|
13
|
+
&& rect.maxX.isFinite && rect.maxY.isFinite
|
|
11
14
|
&& rect.size.width > 0 && rect.size.height > 0
|
|
12
15
|
}
|
|
13
16
|
|
|
@@ -34,6 +34,8 @@ public struct RawAXNode: Equatable {
|
|
|
34
34
|
public let label: String?
|
|
35
35
|
public let identifier: String?
|
|
36
36
|
public let value: String?
|
|
37
|
+
/// The text a text field shows while empty (`placeholderValue`); `nil` for every other node.
|
|
38
|
+
public let placeholder: String?
|
|
37
39
|
public var rect: SnapshotRect
|
|
38
40
|
public let enabled: Bool
|
|
39
41
|
public let focused: Bool?
|
|
@@ -52,6 +54,7 @@ public struct RawAXNode: Equatable {
|
|
|
52
54
|
label: String?,
|
|
53
55
|
identifier: String?,
|
|
54
56
|
value: String?,
|
|
57
|
+
placeholder: String? = nil,
|
|
55
58
|
rect: SnapshotRect,
|
|
56
59
|
enabled: Bool,
|
|
57
60
|
focused: Bool?,
|
|
@@ -68,6 +71,7 @@ public struct RawAXNode: Equatable {
|
|
|
68
71
|
self.label = label
|
|
69
72
|
self.identifier = identifier
|
|
70
73
|
self.value = value
|
|
74
|
+
self.placeholder = placeholder
|
|
71
75
|
self.rect = rect
|
|
72
76
|
self.enabled = enabled
|
|
73
77
|
self.focused = focused
|
|
@@ -157,11 +161,14 @@ public struct PresentationOptions: Equatable {
|
|
|
157
161
|
/// What a capture knows about the viewport hosting its tree: the three cases of the host's
|
|
158
162
|
/// `IosViewportEvidence` (#2891). No rectangle stands for "unknown".
|
|
159
163
|
public enum SnapshotViewport: Equatable {
|
|
160
|
-
/// A box
|
|
164
|
+
/// A box that was checked on the way in. The initializer is the only gate: no caller, inside this
|
|
165
|
+
/// package or outside it, holds a `Box` whose rectangle `SnapshotGeometry.isPositiveFinite`
|
|
166
|
+
/// refuses, so a `.reported` case never needs re-checking what it was handed.
|
|
161
167
|
public struct Box: Equatable {
|
|
162
168
|
public let rect: CGRect
|
|
163
169
|
|
|
164
|
-
init(
|
|
170
|
+
init?(checked rect: CGRect) {
|
|
171
|
+
guard SnapshotGeometry.isPositiveFinite(rect) else { return nil }
|
|
165
172
|
self.rect = rect
|
|
166
173
|
}
|
|
167
174
|
}
|
|
@@ -194,15 +201,13 @@ public enum SnapshotViewport: Equatable {
|
|
|
194
201
|
box: CGRect,
|
|
195
202
|
interfaceOrientation: Int = RunnerInterfaceOrientation.unknown
|
|
196
203
|
) -> SnapshotViewport {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
: .missing(reason: .invalid)
|
|
204
|
+
guard let checked = Box(checked: box) else { return .missing(reason: .invalid) }
|
|
205
|
+
return .reported(checked, interfaceOrientation: interfaceOrientation)
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
public static func derived(box: CGRect) -> SnapshotViewport {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
: .missing(reason: .invalid)
|
|
209
|
+
guard let checked = Box(checked: box) else { return .missing(reason: .invalid) }
|
|
210
|
+
return .derived(checked)
|
|
206
211
|
}
|
|
207
212
|
}
|
|
208
213
|
|
|
@@ -271,6 +276,7 @@ public struct PresentedNode: Codable, Equatable {
|
|
|
271
276
|
public let label: String?
|
|
272
277
|
public let identifier: String?
|
|
273
278
|
public let value: String?
|
|
279
|
+
public let placeholder: String?
|
|
274
280
|
public let rect: SnapshotRect
|
|
275
281
|
public let enabled: Bool
|
|
276
282
|
public let focused: Bool?
|
|
@@ -294,6 +300,7 @@ public struct PresentedNode: Codable, Equatable {
|
|
|
294
300
|
self.label = raw.label
|
|
295
301
|
self.identifier = raw.identifier
|
|
296
302
|
self.value = raw.value
|
|
303
|
+
self.placeholder = raw.placeholder
|
|
297
304
|
self.rect = rect ?? raw.rect
|
|
298
305
|
self.enabled = raw.enabled
|
|
299
306
|
self.focused = raw.focused
|
|
@@ -199,21 +199,19 @@ public enum SnapshotVisibilityFold {
|
|
|
199
199
|
label: node.label,
|
|
200
200
|
identifier: node.identifier,
|
|
201
201
|
value: node.value,
|
|
202
|
+
placeholder: node.placeholder,
|
|
202
203
|
rect: node.rect,
|
|
203
204
|
enabled: node.enabled,
|
|
204
205
|
focused: node.focused,
|
|
205
206
|
selected: node.selected,
|
|
206
207
|
hittable: node.parentIndex == nil
|
|
207
208
|
? false
|
|
208
|
-
:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
)
|
|
215
|
-
: false
|
|
216
|
-
},
|
|
209
|
+
: clippedHittability(
|
|
210
|
+
source: node.hittable,
|
|
211
|
+
enabled: node.enabled,
|
|
212
|
+
clippedFrame: decision.effectiveFrame,
|
|
213
|
+
viewport: viewport
|
|
214
|
+
),
|
|
217
215
|
depth: outDepth,
|
|
218
216
|
parentIndex: keptIndex,
|
|
219
217
|
hiddenContentAbove: node.hiddenContentAbove,
|
|
@@ -244,4 +242,23 @@ public enum SnapshotVisibilityFold {
|
|
|
244
242
|
return applyHiddenContentHints(hints, to: kept)
|
|
245
243
|
}
|
|
246
244
|
|
|
245
|
+
/// The fold's share of the `hittable` policy (#2891). A declared `false` is kept; anything the
|
|
246
|
+
/// source left undecided is re-decided on the clipped frame: a disabled or degenerate frame —
|
|
247
|
+
/// including a `visibilityExempt` carrier a scroll anchor clipped to nothing — answers `false`,
|
|
248
|
+
/// and `nil` stays reserved for the one question the clipped frame cannot answer, containment
|
|
249
|
+
/// while the capture has no viewport box.
|
|
250
|
+
private static func clippedHittability(
|
|
251
|
+
source: Bool?,
|
|
252
|
+
enabled: Bool,
|
|
253
|
+
clippedFrame: CGRect,
|
|
254
|
+
viewport: SnapshotViewport
|
|
255
|
+
) -> Bool? {
|
|
256
|
+
if source == false { return false }
|
|
257
|
+
return SnapshotGeometry.isGeometricallyActionable(
|
|
258
|
+
enabled: enabled,
|
|
259
|
+
frame: clippedFrame,
|
|
260
|
+
viewport: viewport
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
247
264
|
}
|