agent-device 0.21.12 → 0.21.14
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.12.apk → agent-device-android-ime-helper-0.21.14.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.14.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.12.manifest.json → agent-device-android-ime-helper-0.21.14.manifest.json} +4 -4
- 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 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.12.manifest.json → agent-device-android-snapshot-helper-0.21.14.manifest.json} +6 -6
- package/apple/macos-helper/Package.swift +4 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +3 -6
- package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/ScreenshotResponseTests.swift +15 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +47 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +122 -42
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/Info.plist +23 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +17 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +21 -13
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -162
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +0 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +0 -56
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -48
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -50
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +33 -586
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +40 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +2 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +0 -36
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +630 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +34 -2256
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -338
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +160 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -24
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +0 -142
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +90 -39
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +78 -106
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +23 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +162 -113
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +0 -209
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +86 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +271 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +1 -200
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +20 -227
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +78 -295
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +40 -27
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +0 -78
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +85 -581
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +106 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +142 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +49 -78
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +0 -44
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +73 -114
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +1 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +11 -94
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +2 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +0 -35
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +0 -31
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +2 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +34 -52
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +135 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -6
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +140 -20
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +16 -19
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +21 -9
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +59 -10
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +12 -10
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +13 -8
- package/dist/src/absence-observation-errors.js +1 -1
- 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 -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 +2 -2
- 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 +3 -3
- 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/back-mode.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 +8 -7
- package/dist/src/cli-runner.js +1 -1
- 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 +4 -5
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-tools.js +3 -3
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-resolution.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +1 -1
- 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/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/display-inventory.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.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-plan-types.d.ts +38 -0
- 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.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-operation-catalog.js +1 -1
- package/dist/src/interactor.js +4 -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-runtime.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 +435 -4
- package/dist/src/linux.js +1 -1
- package/dist/src/local-interactor-operation-set.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 +5 -5
- 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 -0
- package/dist/src/observation.js +1 -1
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +1 -2
- 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 +2 -0
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-apps.js +1 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-host.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 +2 -2
- 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/register-builtins.js +1 -1
- package/dist/src/registry.js +35 -35
- 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/retry.js +1 -1
- package/dist/src/runner-cache-metadata.js +1 -1
- 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 -0
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-presentation.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +2 -2
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +4 -4
- 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-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 +377 -0
- 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 +28 -0
- package/dist/src/sdk-contracts.js +1 -1
- package/dist/src/sdk-device.js +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 +23 -726
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/semantic-index.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-observation.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 +2 -2
- package/dist/src/session2.js +3 -3
- package/dist/src/settings.js +1 -1
- package/dist/src/simctl-facade.js +1 -1
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-state.js +1 -1
- package/dist/src/simulator.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/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/string-enum.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider-facade.js +1 -1
- package/dist/src/tool-provider.js +2 -2
- 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/update-check.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +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 +3 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.12.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.12.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.12.apk.sha256 +0 -1
- package/dist/src/app-inventory.d.ts +0 -4
- package/dist/src/apps-simctl.js +0 -1
- package/dist/src/cloud-artifacts.d.ts +0 -61
- package/dist/src/runner-contract.js +0 -3
- package/dist/src/snapshot-process.js +0 -1
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift
CHANGED
|
@@ -1,30 +1,70 @@
|
|
|
1
|
+
import AgentDeviceSnapshotPresentation
|
|
1
2
|
import XCTest
|
|
2
3
|
|
|
3
4
|
extension RunnerTests {
|
|
4
5
|
static let navigationBackKeywords = ["back", "close", "cancel"]
|
|
5
6
|
static let navigationFallbackVerificationDelay: TimeInterval = 0.25
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
enum InAppBackOutcome {
|
|
12
|
+
case performed
|
|
13
|
+
case unavailable
|
|
14
|
+
case unverified(ErrorPayload)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
enum NavigationVisualObservation: Equatable {
|
|
20
|
+
case changed
|
|
21
|
+
case unchanged
|
|
22
|
+
case unobserved
|
|
23
|
+
|
|
24
|
+
var logToken: String {
|
|
25
|
+
switch self {
|
|
26
|
+
case .changed: return "yes"
|
|
27
|
+
case .unchanged: return "no"
|
|
28
|
+
case .unobserved: return "unknown"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
struct NavigationVisualSample {
|
|
36
|
+
let data: Data?
|
|
37
|
+
let refusalCode: String?
|
|
38
|
+
let refusalHint: String?
|
|
39
|
+
|
|
40
|
+
init(data: Data?, refusalCode: String? = nil, refusalHint: String? = nil) {
|
|
41
|
+
self.data = data
|
|
42
|
+
self.refusalCode = refusalCode
|
|
43
|
+
self.refusalHint = refusalHint
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func tapInAppBackControl(app: XCUIApplication) -> InAppBackOutcome {
|
|
8
48
|
#if os(macOS)
|
|
9
49
|
if let back = macOSNavigationBackElement(app: app) {
|
|
10
50
|
tapElementCenter(app: app, element: back)
|
|
11
|
-
return
|
|
51
|
+
return .performed
|
|
12
52
|
}
|
|
13
|
-
return
|
|
53
|
+
return .unavailable
|
|
14
54
|
#elseif os(tvOS)
|
|
15
55
|
_ = pressTvRemote(.menu)
|
|
16
|
-
return
|
|
56
|
+
return .performed
|
|
17
57
|
#else
|
|
18
58
|
let buttons = app.navigationBars.buttons.allElementsBoundByIndex
|
|
19
59
|
if let back = buttons.first(where: { $0.isHittable }) {
|
|
20
60
|
back.tap()
|
|
21
|
-
return
|
|
61
|
+
return .performed
|
|
22
62
|
}
|
|
23
63
|
if isSnapshotXCTestChannelPenalized(bundleId: currentBundleId) {
|
|
24
64
|
NSLog("AGENT_DEVICE_RUNNER_IN_APP_BACK_SKIPPED_XCTEST_ENUMERATION bundle=%@", currentBundleId ?? "")
|
|
25
65
|
} else if let back = topNavigationBackElement(app: app) {
|
|
26
66
|
tapElementCenter(app: app, element: back)
|
|
27
|
-
return
|
|
67
|
+
return .performed
|
|
28
68
|
}
|
|
29
69
|
return tapTopLeadingNavigationFallback(app: app)
|
|
30
70
|
#endif
|
|
@@ -81,16 +121,9 @@ extension RunnerTests {
|
|
|
81
121
|
return navigationBackKeywords.firstIndex { text.contains($0) }
|
|
82
122
|
}
|
|
83
123
|
|
|
84
|
-
|
|
85
|
-
static func isUsableNavigationFrame(_ frame: CGRect) -> Bool {
|
|
86
|
-
guard frame.width.isFinite, frame.height.isFinite, frame.width > 0, frame.height > 0 else {
|
|
87
|
-
return false
|
|
88
|
-
}
|
|
89
|
-
return !frame.isInfinite
|
|
90
|
-
}
|
|
91
|
-
|
|
92
124
|
static func isTopNavigationControlFrame(_ candidate: CGRect, in window: CGRect) -> Bool {
|
|
93
|
-
guard
|
|
125
|
+
guard SnapshotGeometry.isPositiveFinite(candidate), SnapshotGeometry.isPositiveFinite(window)
|
|
126
|
+
else {
|
|
94
127
|
return false
|
|
95
128
|
}
|
|
96
129
|
|
|
@@ -99,7 +132,7 @@ extension RunnerTests {
|
|
|
99
132
|
}
|
|
100
133
|
|
|
101
134
|
static func topLeadingNavigationFallbackPoint(in frame: CGRect) -> CGPoint? {
|
|
102
|
-
guard
|
|
135
|
+
guard SnapshotGeometry.isPositiveFinite(frame) else {
|
|
103
136
|
return nil
|
|
104
137
|
}
|
|
105
138
|
|
|
@@ -109,122 +142,48 @@ extension RunnerTests {
|
|
|
109
142
|
return CGPoint(x: frame.minX + xOffset, y: frame.minY + yOffset)
|
|
110
143
|
}
|
|
111
144
|
|
|
112
|
-
private func tapTopLeadingNavigationFallback(app: XCUIApplication) ->
|
|
145
|
+
private func tapTopLeadingNavigationFallback(app: XCUIApplication) -> InAppBackOutcome {
|
|
113
146
|
#if os(iOS)
|
|
114
147
|
let frame = onScreenWindowFrame(app: app)
|
|
115
148
|
guard let point = Self.topLeadingNavigationFallbackPoint(in: frame) else {
|
|
116
|
-
return
|
|
149
|
+
return .unavailable
|
|
117
150
|
}
|
|
118
151
|
let before = captureNavigationFallbackVisualState(app: app)
|
|
119
152
|
let context = synthesizedCoordinateContext(
|
|
120
153
|
app: app,
|
|
121
154
|
policy: synthesizedGesturePolicy(.coordinateTap)
|
|
122
155
|
)?.withReferenceFrame(frame)
|
|
123
|
-
|
|
156
|
+
switch performSynthesizedGesture(app, kind: .coordinateTap, context: context, synthesize: {
|
|
124
157
|
synthesizedTapAt(app: app, x: point.x, y: point.y, context: context)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
158
|
+
}) {
|
|
159
|
+
case .performed:
|
|
160
|
+
return verifyNavigationFallbackOutcome(app: app, before: before)
|
|
161
|
+
case .refused:
|
|
162
|
+
return .unavailable
|
|
163
|
+
case .xctestFallback:
|
|
164
|
+
let fallback = performGesture(app) {
|
|
165
|
+
tapAt(app: app, x: point.x, y: point.y)
|
|
166
|
+
}
|
|
167
|
+
if case .performed = fallback.outcome {
|
|
168
|
+
return verifyNavigationFallbackOutcome(app: app, before: before)
|
|
169
|
+
}
|
|
134
170
|
}
|
|
135
171
|
#endif
|
|
136
|
-
return
|
|
172
|
+
return .unavailable
|
|
137
173
|
}
|
|
138
174
|
|
|
139
|
-
private func captureNavigationFallbackVisualState(app: XCUIApplication) ->
|
|
175
|
+
private func captureNavigationFallbackVisualState(app: XCUIApplication) -> NavigationVisualSample {
|
|
140
176
|
#if os(iOS)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return nil
|
|
147
|
-
}
|
|
148
|
-
return runnerPngData(for: captured.image)
|
|
177
|
+
return Self.navigationFallbackSample(
|
|
178
|
+
resolvingApp: { self.captureResolvedAppScreen(app: app) },
|
|
179
|
+
systemSurface: { self.captureResolvedAppScreen(app: self.springboard) },
|
|
180
|
+
encoding: { runnerPngData(for: $0.image) }
|
|
181
|
+
)
|
|
149
182
|
#else
|
|
150
|
-
return nil
|
|
183
|
+
return NavigationVisualSample(data: nil)
|
|
151
184
|
#endif
|
|
152
185
|
}
|
|
153
186
|
|
|
154
|
-
private func didNavigationFallbackChangeVisualState(
|
|
155
|
-
app: XCUIApplication,
|
|
156
|
-
before: Data?
|
|
157
|
-
) -> Bool {
|
|
158
|
-
sleepFor(Self.navigationFallbackVerificationDelay)
|
|
159
|
-
let after = captureNavigationFallbackVisualState(app: app)
|
|
160
|
-
let changed = Self.didNavigationFallbackChangeVisualState(before: before, after: after)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
NSLog(
|
|
164
|
-
"AGENT_DEVICE_RUNNER_IN_APP_BACK_VISUAL_VERIFICATION beforeBytes=%ld afterBytes=%ld changed=%@",
|
|
165
|
-
before?.count ?? -1,
|
|
166
|
-
after?.count ?? -1,
|
|
167
|
-
changed ? "yes" : "no"
|
|
168
|
-
)
|
|
169
|
-
return changed
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
static func didNavigationFallbackChangeVisualState(before: Data?, after: Data?) -> Bool {
|
|
173
|
-
guard let before, let after else { return false }
|
|
174
|
-
return before != after
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private func macOSNavigationBackElement(app: XCUIApplication) -> XCUIElement? {
|
|
178
|
-
let predicate = NSPredicate(
|
|
179
|
-
format: "identifier == %@ OR label == %@",
|
|
180
|
-
"go back",
|
|
181
|
-
"Back"
|
|
182
|
-
)
|
|
183
|
-
let element = app.descendants(matching: .any).matching(predicate).firstMatch
|
|
184
|
-
return element.exists ? element : nil
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
187
|
|
|
229
188
|
|
|
230
189
|
|
|
@@ -232,23 +191,113 @@ extension RunnerTests {
|
|
|
232
191
|
|
|
233
192
|
|
|
234
193
|
|
|
194
|
+
static func navigationFallbackSample(
|
|
195
|
+
resolvingApp: () -> Result<CapturedAppScreen, RunnerAppScreenCaptureFailure>,
|
|
196
|
+
systemSurface: () -> Result<CapturedAppScreen, RunnerAppScreenCaptureFailure>,
|
|
197
|
+
encoding: (CapturedAppScreen) -> Data?
|
|
198
|
+
) -> NavigationVisualSample {
|
|
199
|
+
_ = systemSurface
|
|
200
|
+
return navigationVisualSample(from: resolvingApp(), encoding: encoding)
|
|
201
|
+
}
|
|
235
202
|
|
|
236
203
|
|
|
237
204
|
|
|
238
205
|
|
|
239
206
|
|
|
207
|
+
static func navigationVisualSample(
|
|
208
|
+
from outcome: Result<CapturedAppScreen, RunnerAppScreenCaptureFailure>,
|
|
209
|
+
encoding: (CapturedAppScreen) -> Data?
|
|
210
|
+
) -> NavigationVisualSample {
|
|
211
|
+
switch outcome {
|
|
212
|
+
case .success(let captured):
|
|
213
|
+
guard let png = encoding(captured) else {
|
|
214
|
+
let refusal = RunnerAppScreenCaptureFailure.unrenderableImage
|
|
215
|
+
return NavigationVisualSample(
|
|
216
|
+
data: nil,
|
|
217
|
+
refusalCode: refusal.rawValue,
|
|
218
|
+
refusalHint: refusal.hint
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
return NavigationVisualSample(data: png)
|
|
222
|
+
case .failure(let failure):
|
|
223
|
+
return NavigationVisualSample(
|
|
224
|
+
data: nil,
|
|
225
|
+
refusalCode: failure.rawValue,
|
|
226
|
+
refusalHint: failure.hint
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
240
230
|
|
|
231
|
+
private func verifyNavigationFallbackOutcome(
|
|
232
|
+
app: XCUIApplication,
|
|
233
|
+
before: NavigationVisualSample
|
|
234
|
+
) -> InAppBackOutcome {
|
|
235
|
+
sleepFor(Self.navigationFallbackVerificationDelay)
|
|
236
|
+
let after = captureNavigationFallbackVisualState(app: app)
|
|
237
|
+
let observation = Self.navigationVisualObservation(before: before.data, after: after.data)
|
|
241
238
|
|
|
242
239
|
|
|
240
|
+
NSLog(
|
|
241
|
+
"AGENT_DEVICE_RUNNER_IN_APP_BACK_VISUAL_VERIFICATION beforeBytes=%ld afterBytes=%ld changed=%@",
|
|
242
|
+
before.data?.count ?? -1,
|
|
243
|
+
after.data?.count ?? -1,
|
|
244
|
+
observation.logToken
|
|
245
|
+
)
|
|
246
|
+
return Self.inAppBackOutcome(observation: observation, before: before, after: after)
|
|
247
|
+
}
|
|
243
248
|
|
|
244
249
|
|
|
245
250
|
|
|
251
|
+
static func inAppBackOutcome(
|
|
252
|
+
observation: NavigationVisualObservation,
|
|
253
|
+
before: NavigationVisualSample,
|
|
254
|
+
after: NavigationVisualSample
|
|
255
|
+
) -> InAppBackOutcome {
|
|
256
|
+
switch observation {
|
|
257
|
+
case .changed:
|
|
258
|
+
return .performed
|
|
259
|
+
case .unchanged:
|
|
260
|
+
return .unavailable
|
|
261
|
+
case .unobserved:
|
|
246
262
|
|
|
247
263
|
|
|
264
|
+
return .unverified(Self.navigationFallbackErrorPayload(after: after, before: before))
|
|
265
|
+
}
|
|
266
|
+
}
|
|
248
267
|
|
|
268
|
+
static func navigationVisualObservation(
|
|
269
|
+
before: Data?,
|
|
270
|
+
after: Data?
|
|
271
|
+
) -> NavigationVisualObservation {
|
|
272
|
+
guard let before, let after else { return .unobserved }
|
|
273
|
+
return before != after ? .changed : .unchanged
|
|
274
|
+
}
|
|
249
275
|
|
|
250
276
|
|
|
251
277
|
|
|
252
278
|
|
|
279
|
+
static func navigationFallbackErrorPayload(
|
|
280
|
+
after: NavigationVisualSample,
|
|
281
|
+
before: NavigationVisualSample
|
|
282
|
+
) -> ErrorPayload {
|
|
283
|
+
ErrorPayload(
|
|
284
|
+
code:
|
|
285
|
+
after.refusalCode
|
|
286
|
+
?? before.refusalCode
|
|
287
|
+
?? RunnerAppScreenCaptureFailure.unresolvedScreen.rawValue,
|
|
288
|
+
message:
|
|
289
|
+
"The in-app back fallback was dispatched, but no display could be sampled to confirm the result. This is an unknown outcome, not evidence that a back control is absent.",
|
|
290
|
+
hint: after.refusalHint ?? before.refusalHint
|
|
291
|
+
)
|
|
292
|
+
}
|
|
253
293
|
|
|
294
|
+
private func macOSNavigationBackElement(app: XCUIApplication) -> XCUIElement? {
|
|
295
|
+
let predicate = NSPredicate(
|
|
296
|
+
format: "identifier == %@ OR label == %@",
|
|
297
|
+
"go back",
|
|
298
|
+
"Back"
|
|
299
|
+
)
|
|
300
|
+
let element = app.descendants(matching: .any).matching(predicate).firstMatch
|
|
301
|
+
return element.exists ? element : nil
|
|
302
|
+
}
|
|
254
303
|
}
|
|
@@ -89,212 +89,3 @@ extension RunnerTests {
|
|
|
89
89
|
(value as? Bool) ?? (value as? NSNumber)?.boolValue
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
@@ -25,12 +25,20 @@ extension RunnerTests {
|
|
|
25
25
|
private var startedSession = false
|
|
26
26
|
private var startError: Error?
|
|
27
27
|
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
28
31
|
init(outputPath: String, fps: Int32?) {
|
|
29
32
|
self.outputPath = outputPath
|
|
30
33
|
self.fps = fps
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
func start(
|
|
39
|
+
bootstrap: @escaping () -> Result<CapturedAppScreen, RunnerAppScreenCaptureFailure>,
|
|
40
|
+
frame: @escaping () -> RunnerImage?
|
|
41
|
+
) throws {
|
|
34
42
|
let url = URL(fileURLWithPath: outputPath)
|
|
35
43
|
let directory = url.deletingLastPathComponent()
|
|
36
44
|
try FileManager.default.createDirectory(
|
|
@@ -44,21 +52,34 @@ extension RunnerTests {
|
|
|
44
52
|
|
|
45
53
|
var dimensions: CGSize = .zero
|
|
46
54
|
var bootstrapImage: RunnerImage?
|
|
55
|
+
var lastFailure: RunnerAppScreenCaptureFailure?
|
|
47
56
|
let bootstrapDeadline = Date().addingTimeInterval(2.0)
|
|
48
57
|
while Date() < bootstrapDeadline {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
switch bootstrap() {
|
|
59
|
+
case .success(let captured):
|
|
60
|
+
bootstrapImage = captured.image
|
|
61
|
+
dimensions = CGSize(width: captured.pixelWidth, height: captured.pixelHeight)
|
|
62
|
+
case .failure(let failure):
|
|
63
|
+
lastFailure = failure
|
|
64
|
+
}
|
|
65
|
+
if dimensions.width > 0, dimensions.height > 0 {
|
|
52
66
|
break
|
|
53
67
|
}
|
|
54
68
|
Thread.sleep(forTimeInterval: 0.05)
|
|
55
69
|
}
|
|
56
70
|
guard dimensions.width > 0, dimensions.height > 0 else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#if os(iOS)
|
|
76
|
+
throw RunnerTests.recordingBootstrapError(from: lastFailure)
|
|
77
|
+
#else
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
_ = lastFailure
|
|
81
|
+
throw RunnerTests.recordingBootstrapError(from: nil)
|
|
82
|
+
#endif
|
|
62
83
|
}
|
|
63
84
|
|
|
64
85
|
let writer = try AVAssetWriter(outputURL: url, fileType: .mp4)
|
|
@@ -114,7 +135,7 @@ extension RunnerTests {
|
|
|
114
135
|
timer.setEventHandler { [weak self] in
|
|
115
136
|
guard let self else { return }
|
|
116
137
|
if self.shouldStop() { return }
|
|
117
|
-
guard let image =
|
|
138
|
+
guard let image = frame() else { return }
|
|
118
139
|
self.append(image: image)
|
|
119
140
|
}
|
|
120
141
|
self.timer = timer
|
|
@@ -212,6 +233,9 @@ extension RunnerTests {
|
|
|
212
233
|
return
|
|
213
234
|
}
|
|
214
235
|
lastTimestampValue = timestampValue
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
215
239
|
}
|
|
216
240
|
|
|
217
241
|
private func timestampCandidateValue(for nowUptime: TimeInterval) -> Int64 {
|
|
@@ -269,6 +293,58 @@ extension RunnerTests {
|
|
|
269
293
|
}
|
|
270
294
|
}
|
|
271
295
|
|
|
296
|
+
extension RunnerTests {
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
func startRecording(
|
|
303
|
+
_ recorder: ScreenRecorder,
|
|
304
|
+
capture: @escaping () -> Result<CapturedAppScreen, RunnerAppScreenCaptureFailure>
|
|
305
|
+
) throws {
|
|
306
|
+
try recorder.start(bootstrap: capture) { [weak self] in
|
|
307
|
+
guard let self else { return nil }
|
|
308
|
+
return try? self.runMainThreadWorkIfIdle(
|
|
309
|
+
"recording_frame",
|
|
310
|
+
timeout: self.recordingFrameCaptureTimeout,
|
|
311
|
+
timeoutError: self.mainThreadExecutionTimeoutError
|
|
312
|
+
) {
|
|
313
|
+
try capture().get().image
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
static func recordingBootstrapError(from lastFailure: RunnerAppScreenCaptureFailure?) -> Error {
|
|
323
|
+
lastFailure
|
|
324
|
+
?? NSError(
|
|
325
|
+
domain: "AgentDeviceRunner.Record",
|
|
326
|
+
code: 1,
|
|
327
|
+
userInfo: [NSLocalizedDescriptionKey: "failed to capture initial frame"]
|
|
328
|
+
)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
static func recordingStartErrorPayload(for error: Error) -> ErrorPayload {
|
|
335
|
+
if let failure = error as? RunnerAppScreenCaptureFailure {
|
|
336
|
+
return ErrorPayload(code: failure.rawValue, message: failure.message, hint: failure.hint)
|
|
337
|
+
}
|
|
338
|
+
return ErrorPayload(message: "failed to start recording: \(error.localizedDescription)")
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
272
348
|
|
|
273
349
|
|
|
274
350
|
|