agent-device 0.20.9 → 0.20.10
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.20.9.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.9.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.9.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.9.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +6 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +94 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +30 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +133 -63
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +61 -0
- package/dist/src/ai-sdk.js +1 -0
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apps.js +5 -5
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +30 -23
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +7 -7
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +1582 -0
- package/dist/src/command-tools.js +2 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/dispatch.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/helper-package-install.js +1 -1
- package/dist/src/helper.js +1 -1
- package/dist/src/ime-lifecycle.js +1 -1
- package/dist/src/ime-recovery-marker.js +1 -1
- package/dist/src/index.d.ts +2 -1578
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions3.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +4 -4
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +10 -2
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/{screenshot-geometry.js → mobile-snapshot-semantics.js} +1 -1
- package/dist/src/perf.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.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-resize.js +1 -1
- package/dist/src/provider.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/registry.js +27 -27
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +5 -5
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +3 -3
- 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/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/script-source-bundle.js +16 -0
- package/dist/src/sdk-android-adb.d.ts +40 -40
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +122 -85
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-selectors.d.ts +89 -77
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +10 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session2.js +7 -8
- package/dist/src/shared.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -0
- package/dist/src/snapshot.js +6 -6
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +1 -1
- package/dist/src/src4.js +1 -0
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -0
- package/dist/src/verified-file.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +21 -8
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.9.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.9.apk.sha256 +0 -1
- package/dist/src/cancel.js +0 -1
- package/dist/src/prepare-kind.js +0 -15
- package/dist/src/selector-vocabulary.js +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
37cfdc9733315068659a6a4c1da8e65cd403e382401194f989f510fb0f320ba5 agent-device-android-ime-helper-0.20.10.apk
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-ime-helper",
|
|
3
|
-
"version": "0.20.
|
|
4
|
-
"assetName": "agent-device-android-ime-helper-0.20.
|
|
5
|
-
"sha256": "
|
|
3
|
+
"version": "0.20.10",
|
|
4
|
+
"assetName": "agent-device-android-ime-helper-0.20.10.apk",
|
|
5
|
+
"sha256": "37cfdc9733315068659a6a4c1da8e65cd403e382401194f989f510fb0f320ba5",
|
|
6
6
|
"packageName": "com.callstack.agentdevice.imehelper",
|
|
7
|
-
"versionCode":
|
|
7
|
+
"versionCode": 20010,
|
|
8
8
|
"serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
|
|
9
9
|
"broadcastProtocol": "android-ime-helper-v1"
|
|
10
10
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a5e8c39ef8dc5ca6fc1959dfcd52b00bd7845ce584abc0930f8d4a517bd784cc agent-device-android-snapshot-helper-0.20.10.apk
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-snapshot-helper",
|
|
3
|
-
"version": "0.20.
|
|
4
|
-
"releaseTag": "v0.20.
|
|
5
|
-
"assetName": "agent-device-android-snapshot-helper-0.20.
|
|
3
|
+
"version": "0.20.10",
|
|
4
|
+
"releaseTag": "v0.20.10",
|
|
5
|
+
"assetName": "agent-device-android-snapshot-helper-0.20.10.apk",
|
|
6
6
|
"apkUrl": null,
|
|
7
|
-
"sha256": "
|
|
8
|
-
"checksumName": "agent-device-android-snapshot-helper-0.20.
|
|
7
|
+
"sha256": "a5e8c39ef8dc5ca6fc1959dfcd52b00bd7845ce584abc0930f8d4a517bd784cc",
|
|
8
|
+
"checksumName": "agent-device-android-snapshot-helper-0.20.10.apk.sha256",
|
|
9
9
|
"packageName": "com.callstack.agentdevice.snapshothelper",
|
|
10
|
-
"versionCode":
|
|
10
|
+
"versionCode": 20010,
|
|
11
11
|
"instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
|
|
12
12
|
"minSdk": 23,
|
|
13
13
|
"targetSdk": 36,
|
|
@@ -103,11 +103,11 @@ extension RunnerTests {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
func
|
|
106
|
+
func privateAXSnapshotAcquisition(
|
|
107
107
|
app: XCUIApplication,
|
|
108
|
-
options:
|
|
108
|
+
options: PresentationOptions,
|
|
109
109
|
deadline: Date = .distantFuture
|
|
110
|
-
) ->
|
|
110
|
+
) -> SnapshotAcquisition? {
|
|
111
111
|
#if os(iOS) && targetEnvironment(simulator)
|
|
112
112
|
let requestedDepth = options.depth ?? 64
|
|
113
113
|
// An explicit --depth request is honored as asked: no accepted-depth
|
|
@@ -202,8 +202,9 @@ extension RunnerTests {
|
|
|
202
202
|
effectiveDepth,
|
|
203
203
|
deepExtension?[RunnerAXSnapshotDeepExtensionNodesAddedKey] as? Int ?? 0
|
|
204
204
|
)
|
|
205
|
-
return
|
|
206
|
-
|
|
205
|
+
return SnapshotAcquisition(
|
|
206
|
+
nodes: nodes,
|
|
207
|
+
truncated: (response["truncated"] as? Bool) == true,
|
|
207
208
|
effectiveDepth: depthLimited ? effectiveDepth : nil,
|
|
208
209
|
customActions: Self.privateAXCustomActionCoverage(
|
|
209
210
|
response[RunnerAXSnapshotCustomActionsKey]
|
|
@@ -584,10 +584,10 @@ extension RunnerTests {
|
|
|
584
584
|
}
|
|
585
585
|
|
|
586
586
|
/// Pure command→options projection, extracted so the runner unit bundle can
|
|
587
|
-
/// prove the decoded wire field actually reaches
|
|
588
|
-
static func
|
|
587
|
+
/// prove the decoded wire field actually reaches presentation options (#1634 P2).
|
|
588
|
+
static func presentationOptions(from command: Command) -> PresentationOptions {
|
|
589
589
|
let customActions = command.customActions ?? false
|
|
590
|
-
return
|
|
590
|
+
return PresentationOptions(
|
|
591
591
|
interactiveOnly: command.interactiveOnly ?? false,
|
|
592
592
|
depth: command.depth,
|
|
593
593
|
scope: command.scope,
|
|
@@ -602,7 +602,7 @@ extension RunnerTests {
|
|
|
602
602
|
}
|
|
603
603
|
|
|
604
604
|
private func executeSnapshotPrepared(command: Command, activeApp: XCUIApplication) throws -> Response {
|
|
605
|
-
let options = Self.
|
|
605
|
+
let options = Self.presentationOptions(from: command)
|
|
606
606
|
do {
|
|
607
607
|
let payload: DataPayload
|
|
608
608
|
if options.raw {
|
|
@@ -23,10 +23,103 @@ enum FlatSnapshotVisibilityPolicy {
|
|
|
23
23
|
case viewportProjected
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
enum FlatSnapshotGeometry {
|
|
27
|
+
case geometryless
|
|
28
|
+
case framed(intersectsViewportAndScrollClip: Bool)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
enum FlatSnapshotDescendantVisibility: Equatable {
|
|
32
|
+
case independent
|
|
33
|
+
case owned
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
struct FlatSnapshotProjectionCursor {
|
|
37
|
+
static let root = FlatSnapshotProjectionCursor(ancestorProjectedOut: false)
|
|
38
|
+
|
|
39
|
+
private let ancestorProjectedOut: Bool
|
|
40
|
+
|
|
41
|
+
var isProjectedOut: Bool { ancestorProjectedOut }
|
|
42
|
+
|
|
43
|
+
func project(
|
|
44
|
+
geometry: FlatSnapshotGeometry,
|
|
45
|
+
descendantVisibility: FlatSnapshotDescendantVisibility
|
|
46
|
+
) -> FlatSnapshotProjectionDecision {
|
|
47
|
+
let nodeProjectedOut: Bool
|
|
48
|
+
switch geometry {
|
|
49
|
+
case .geometryless:
|
|
50
|
+
nodeProjectedOut = false
|
|
51
|
+
case .framed(let intersectsViewportAndScrollClip):
|
|
52
|
+
nodeProjectedOut = !intersectsViewportAndScrollClip
|
|
53
|
+
}
|
|
54
|
+
let presentationVisible = !ancestorProjectedOut && !nodeProjectedOut
|
|
55
|
+
let descendantsProjectedOut = ancestorProjectedOut
|
|
56
|
+
|| (nodeProjectedOut && descendantVisibility == .owned)
|
|
57
|
+
return FlatSnapshotProjectionDecision(
|
|
58
|
+
presentationVisible: presentationVisible,
|
|
59
|
+
descendants: FlatSnapshotProjectionCursor(
|
|
60
|
+
ancestorProjectedOut: descendantsProjectedOut
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
struct FlatSnapshotProjectionDecision {
|
|
67
|
+
let presentationVisible: Bool
|
|
68
|
+
let descendants: FlatSnapshotProjectionCursor
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
struct FlatSnapshotProjectionTransition {
|
|
72
|
+
let decision: FlatSnapshotProjectionDecision
|
|
73
|
+
let hiddenContentFrame: CGRect?
|
|
74
|
+
}
|
|
75
|
+
|
|
26
76
|
extension RunnerTests {
|
|
77
|
+
func flatSnapshotGeometry(
|
|
78
|
+
frame: CGRect,
|
|
79
|
+
intersectsViewportAndScrollClip: Bool
|
|
80
|
+
) -> FlatSnapshotGeometry {
|
|
81
|
+
if frame.isNull || frame.isEmpty { return .geometryless }
|
|
82
|
+
return .framed(intersectsViewportAndScrollClip: intersectsViewportAndScrollClip)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func flatSnapshotDescendantVisibility(
|
|
86
|
+
elementType: XCUIElement.ElementType?,
|
|
87
|
+
hasChildren: Bool
|
|
88
|
+
) -> FlatSnapshotDescendantVisibility {
|
|
89
|
+
guard hasChildren, let elementType else { return .independent }
|
|
90
|
+
if elementType == .cell || Self.scrollContainerTypes.contains(elementType) {
|
|
91
|
+
return .owned
|
|
92
|
+
}
|
|
93
|
+
return .independent
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
func flatSnapshotProjectionTransition(
|
|
97
|
+
frame: CGRect,
|
|
98
|
+
intersectsViewportAndScrollClip: Bool,
|
|
99
|
+
elementType: XCUIElement.ElementType?,
|
|
100
|
+
hasChildren: Bool,
|
|
101
|
+
cursor: FlatSnapshotProjectionCursor
|
|
102
|
+
) -> FlatSnapshotProjectionTransition {
|
|
103
|
+
let hasFrame = !frame.isNull && !frame.isEmpty
|
|
104
|
+
return FlatSnapshotProjectionTransition(
|
|
105
|
+
decision: cursor.project(
|
|
106
|
+
geometry: flatSnapshotGeometry(
|
|
107
|
+
frame: frame,
|
|
108
|
+
intersectsViewportAndScrollClip: intersectsViewportAndScrollClip
|
|
109
|
+
),
|
|
110
|
+
descendantVisibility: flatSnapshotDescendantVisibility(
|
|
111
|
+
elementType: elementType,
|
|
112
|
+
hasChildren: hasChildren
|
|
113
|
+
)
|
|
114
|
+
),
|
|
115
|
+
hiddenContentFrame: !cursor.isProjectedOut && hasFrame
|
|
116
|
+
&& !intersectsViewportAndScrollClip ? frame : nil
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
27
120
|
func flatSnapshotFilterDecision(
|
|
28
121
|
_ node: FlatSnapshotFilterNode,
|
|
29
|
-
options:
|
|
122
|
+
options: PresentationOptions,
|
|
30
123
|
visibilityPolicy: FlatSnapshotVisibilityPolicy,
|
|
31
124
|
insideMatchedScope: Bool
|
|
32
125
|
) -> FlatSnapshotFilterDecision {
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift
CHANGED
|
@@ -229,21 +229,23 @@ extension RunnerTests {
|
|
|
229
229
|
let identifier = element.identifier.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
230
230
|
let valueText = String(describing: element.value ?? "")
|
|
231
231
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
232
|
-
let node =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
232
|
+
let node = SnapshotPresentation.singleElementRead(
|
|
233
|
+
RawAXNode(
|
|
234
|
+
index: 0,
|
|
235
|
+
type: elementTypeName(element.elementType),
|
|
236
|
+
label: label.isEmpty ? nil : label,
|
|
237
|
+
identifier: identifier.isEmpty ? nil : identifier,
|
|
238
|
+
value: valueText.isEmpty ? nil : valueText,
|
|
239
|
+
rect: snapshotRect(from: element.frame),
|
|
240
|
+
enabled: element.isEnabled,
|
|
241
|
+
focused: nil,
|
|
242
|
+
selected: element.isSelected ? true : nil,
|
|
243
|
+
hittable: element.isHittable,
|
|
244
|
+
depth: 0,
|
|
245
|
+
parentIndex: nil,
|
|
246
|
+
hiddenContentAbove: nil,
|
|
247
|
+
hiddenContentBelow: nil
|
|
248
|
+
)
|
|
247
249
|
)
|
|
248
250
|
return Response(
|
|
249
251
|
ok: true,
|
|
@@ -317,7 +319,11 @@ extension RunnerTests {
|
|
|
317
319
|
.filter { element in
|
|
318
320
|
guard element.exists else { return false }
|
|
319
321
|
let frame = element.frame
|
|
320
|
-
return
|
|
322
|
+
return isCoordinateTextInputCandidate(
|
|
323
|
+
enabled: element.isEnabled,
|
|
324
|
+
frame: frame,
|
|
325
|
+
point: point
|
|
326
|
+
)
|
|
321
327
|
}
|
|
322
328
|
.sorted { left, right in
|
|
323
329
|
let leftArea = max(1, left.frame.width * left.frame.height)
|
|
@@ -336,13 +342,6 @@ extension RunnerTests {
|
|
|
336
342
|
}
|
|
337
343
|
}
|
|
338
344
|
|
|
339
|
-
private func frameContainsPoint(_ frame: CGRect, _ point: CGPoint, tolerance: CGFloat) -> Bool {
|
|
340
|
-
point.x >= frame.minX - tolerance
|
|
341
|
-
&& point.x <= frame.maxX + tolerance
|
|
342
|
-
&& point.y >= frame.minY - tolerance
|
|
343
|
-
&& point.y <= frame.maxY + tolerance
|
|
344
|
-
}
|
|
345
|
-
|
|
346
345
|
private func readableText(for element: XCUIElement) -> String? {
|
|
347
346
|
let label = element.label.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
348
347
|
let identifier = element.identifier.trimmingCharacters(in: .whitespacesAndNewlines)
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift
CHANGED
|
@@ -235,7 +235,7 @@ struct DataPayload: Codable {
|
|
|
235
235
|
let text: String?
|
|
236
236
|
let found: Bool?
|
|
237
237
|
let items: [String]?
|
|
238
|
-
let nodes: [
|
|
238
|
+
let nodes: [PresentedNode]?
|
|
239
239
|
let truncated: Bool?
|
|
240
240
|
let snapshotQuality: SnapshotQuality?
|
|
241
241
|
let gestureStartUptimeMs: Double?
|
|
@@ -277,7 +277,7 @@ struct DataPayload: Codable {
|
|
|
277
277
|
text: String? = nil,
|
|
278
278
|
found: Bool? = nil,
|
|
279
279
|
items: [String]? = nil,
|
|
280
|
-
nodes: [
|
|
280
|
+
nodes: [PresentedNode]? = nil,
|
|
281
281
|
truncated: Bool? = nil,
|
|
282
282
|
snapshotQuality: SnapshotQuality? = nil,
|
|
283
283
|
gestureStartUptimeMs: Double? = nil,
|
|
@@ -375,27 +375,7 @@ struct SnapshotRect: Codable {
|
|
|
375
375
|
let height: Double
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
struct
|
|
379
|
-
let index: Int
|
|
380
|
-
let type: String
|
|
381
|
-
let label: String?
|
|
382
|
-
let identifier: String?
|
|
383
|
-
let value: String?
|
|
384
|
-
let rect: SnapshotRect
|
|
385
|
-
let enabled: Bool
|
|
386
|
-
let focused: Bool?
|
|
387
|
-
let selected: Bool?
|
|
388
|
-
let hittable: Bool
|
|
389
|
-
let depth: Int
|
|
390
|
-
let parentIndex: Int?
|
|
391
|
-
let hiddenContentAbove: Bool?
|
|
392
|
-
let hiddenContentBelow: Bool?
|
|
393
|
-
/// Names of the element's UIAccessibilityCustomActions, present only when the
|
|
394
|
-
/// capture asked for them and the element carries some.
|
|
395
|
-
var actions: [String]? = nil
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
struct SnapshotOptions {
|
|
378
|
+
struct PresentationOptions {
|
|
399
379
|
let interactiveOnly: Bool
|
|
400
380
|
let depth: Int?
|
|
401
381
|
let scope: String?
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift
CHANGED
|
@@ -81,17 +81,16 @@ extension RunnerTests {
|
|
|
81
81
|
return navigationBackKeywords.firstIndex { text.contains($0) }
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
// isFinite/>0 alone don't reject CGRect.infinite — its origin (~-9e307) is finite.
|
|
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
|
+
|
|
84
92
|
static func isTopNavigationControlFrame(_ candidate: CGRect, in window: CGRect) -> Bool {
|
|
85
|
-
guard
|
|
86
|
-
candidate.width.isFinite,
|
|
87
|
-
candidate.height.isFinite,
|
|
88
|
-
window.width.isFinite,
|
|
89
|
-
window.height.isFinite,
|
|
90
|
-
candidate.width > 0,
|
|
91
|
-
candidate.height > 0,
|
|
92
|
-
window.width > 0,
|
|
93
|
-
window.height > 0
|
|
94
|
-
else {
|
|
93
|
+
guard isUsableNavigationFrame(candidate), isUsableNavigationFrame(window) else {
|
|
95
94
|
return false
|
|
96
95
|
}
|
|
97
96
|
// Accept the compact navigation/search header band without matching deep content controls.
|
|
@@ -100,7 +99,7 @@ extension RunnerTests {
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
static func topLeadingNavigationFallbackPoint(in frame: CGRect) -> CGPoint? {
|
|
103
|
-
guard frame
|
|
102
|
+
guard isUsableNavigationFrame(frame) else {
|
|
104
103
|
return nil
|
|
105
104
|
}
|
|
106
105
|
// Aim at the standard leading navigation slot, bounded for compact and tablet widths.
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import XCTest
|
|
2
2
|
|
|
3
3
|
extension RunnerTests {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
private static let privateAXProjectionTolerance: CGFloat = 1
|
|
5
|
+
|
|
6
|
+
func privateAXPresentation(rawRoot: [String: Any], options: PresentationOptions, viewport: CGRect)
|
|
7
|
+
-> [RawAXNode]
|
|
6
8
|
{
|
|
7
|
-
var nodes: [
|
|
9
|
+
var nodes: [RawAXNode] = []
|
|
8
10
|
var hints: [Int: (above: Bool, below: Bool)] = [:]
|
|
9
11
|
appendPrivateAXNode(rawRoot, to: &nodes, hints: &hints, options: options, viewport: viewport,
|
|
10
|
-
depth: 0, parentIndex: nil, insideMatchedScope: false, scrollContext: nil
|
|
12
|
+
depth: 0, parentIndex: nil, insideMatchedScope: false, scrollContext: nil,
|
|
13
|
+
projectionCursor: .root)
|
|
11
14
|
return applyHiddenContentHints(hints, to: nodes)
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
private func appendPrivateAXNode(_ raw: [String: Any], to nodes: inout [
|
|
15
|
-
hints: inout [Int: (above: Bool, below: Bool)], options:
|
|
17
|
+
private func appendPrivateAXNode(_ raw: [String: Any], to nodes: inout [RawAXNode],
|
|
18
|
+
hints: inout [Int: (above: Bool, below: Bool)], options: PresentationOptions, viewport: CGRect,
|
|
16
19
|
depth: Int, parentIndex: Int?, insideMatchedScope: Bool,
|
|
17
|
-
scrollContext: (index: Int, rect: CGRect)
|
|
20
|
+
scrollContext: (index: Int, rect: CGRect)?, projectionCursor: FlatSnapshotProjectionCursor)
|
|
18
21
|
{
|
|
19
22
|
if let limit = options.depth, depth > limit { return }
|
|
20
23
|
let rect = privateAXRect(raw["frame"])
|
|
@@ -24,15 +27,29 @@ extension RunnerTests {
|
|
|
24
27
|
let rawType = privateAXPresentationInt(raw["type"]) ?? 0
|
|
25
28
|
let enabled = privateAXPresentationBool(raw["enabled"]) ?? true
|
|
26
29
|
let children = raw["children"] as? [[String: Any]] ?? []
|
|
30
|
+
let hasSemanticContent = [label, identifier, value].contains(where: { !$0.isEmpty })
|
|
27
31
|
let elementType = flatSnapshotElementType(rawElementType: rawType)
|
|
28
32
|
let hasFrame = !rect.isNull && !rect.isEmpty
|
|
33
|
+
let negligibleDecoration = parentIndex != nil
|
|
34
|
+
&& !hasSemanticContent
|
|
35
|
+
&& (!hasFrame
|
|
36
|
+
|| rect.width <= Self.privateAXProjectionTolerance
|
|
37
|
+
|| rect.height <= Self.privateAXProjectionTolerance)
|
|
29
38
|
let onScreen = hasFrame
|
|
30
39
|
&& isVisibleInRegularSnapshot(
|
|
31
40
|
rect,
|
|
32
41
|
viewport: viewport,
|
|
33
42
|
scrollContainerAnchor: scrollContext
|
|
34
43
|
)
|
|
35
|
-
let
|
|
44
|
+
let projectionTransition = flatSnapshotProjectionTransition(
|
|
45
|
+
frame: rect,
|
|
46
|
+
intersectsViewportAndScrollClip: onScreen,
|
|
47
|
+
elementType: elementType,
|
|
48
|
+
hasChildren: !children.isEmpty,
|
|
49
|
+
cursor: projectionCursor
|
|
50
|
+
)
|
|
51
|
+
let projection = projectionTransition.decision
|
|
52
|
+
let presentationVisible = projection.presentationVisible && !negligibleDecoration
|
|
36
53
|
let decision = flatSnapshotFilterDecision(
|
|
37
54
|
FlatSnapshotFilterNode(isRoot: parentIndex == nil, label: label, identifier: identifier,
|
|
38
55
|
valueText: value.isEmpty ? nil : value, visible: presentationVisible),
|
|
@@ -40,15 +57,15 @@ extension RunnerTests {
|
|
|
40
57
|
insideMatchedScope: insideMatchedScope)
|
|
41
58
|
let include = decision.include
|
|
42
59
|
|
|
43
|
-
if
|
|
44
|
-
rememberHiddenContentHint(for:
|
|
60
|
+
if let hiddenFrame = projectionTransition.hiddenContentFrame, let scrollContext {
|
|
61
|
+
rememberHiddenContentHint(for: hiddenFrame, relativeTo: scrollContext, hints: &hints)
|
|
45
62
|
}
|
|
46
63
|
|
|
47
64
|
let currentIndex: Int?
|
|
48
65
|
if include {
|
|
49
66
|
currentIndex = nodes.count
|
|
50
67
|
let typeName = elementType.map(elementTypeName) ?? "Element(\(rawType))"
|
|
51
|
-
nodes.append(
|
|
68
|
+
nodes.append(RawAXNode(index: nodes.count, type: typeName,
|
|
52
69
|
label: label.isEmpty ? nil : label, identifier: identifier.isEmpty ? nil : identifier,
|
|
53
70
|
value: value.isEmpty ? nil : value, rect: snapshotRect(from: rect), enabled: enabled,
|
|
54
71
|
focused: privateAXPresentationBool(raw["focused"]) == true ? true : nil,
|
|
@@ -71,7 +88,8 @@ extension RunnerTests {
|
|
|
71
88
|
for child in children {
|
|
72
89
|
appendPrivateAXNode(child, to: &nodes, hints: &hints, options: options, viewport: viewport,
|
|
73
90
|
depth: depth + 1, parentIndex: currentIndex,
|
|
74
|
-
insideMatchedScope: decision.insideMatchedScope, scrollContext: nextScrollContext
|
|
91
|
+
insideMatchedScope: decision.insideMatchedScope, scrollContext: nextScrollContext,
|
|
92
|
+
projectionCursor: projection.descendants)
|
|
75
93
|
}
|
|
76
94
|
}
|
|
77
95
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift
CHANGED
|
@@ -3,10 +3,10 @@ import XCTest
|
|
|
3
3
|
// Swift port of buildScrollGesturePlan from packages/contracts/src/scroll-gesture.ts.
|
|
4
4
|
//
|
|
5
5
|
// This is a deliberate two-place invariant: the daemon keeps the TS implementation (for Android,
|
|
6
|
-
// recording, and reported-pixels), and the runner places the gesture with this Swift copy.
|
|
7
|
-
//
|
|
8
|
-
// packages/contracts/src/scroll-gesture.test.ts —
|
|
9
|
-
// if you change the math in either language, update the other and
|
|
6
|
+
// recording, and reported-pixels), and the runner places the gesture with this Swift copy. Both
|
|
7
|
+
// ports are asserted against the same table, contracts/fixtures/scroll-gesture.json (gated
|
|
8
|
+
// XCTest at the bottom of this file, vitest twin packages/contracts/src/scroll-gesture.test.ts) —
|
|
9
|
+
// if you change the math in either language, update the other and the table.
|
|
10
10
|
//
|
|
11
11
|
// All inputs here are positive (reference dims, travel, center), so Swift's `.rounded()`
|
|
12
12
|
// (half away from zero) matches JS `Math.round` (half up) on every value computed below.
|
|
@@ -20,7 +20,10 @@ struct RunnerScrollGesturePlan {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
private let runnerDefaultScrollAmount = 0.6
|
|
23
|
-
|
|
23
|
+
// Both constants are pinned by contracts/fixtures/scroll-gesture.json (`constants`). Scroll gestures
|
|
24
|
+
// stay out of the outer 10% of each axis so a saturated scroll never touches down inside the status
|
|
25
|
+
// bar / Dynamic Island band (#1781 A1).
|
|
26
|
+
private let runnerDefaultEdgePaddingFraction = 0.1
|
|
24
27
|
|
|
25
28
|
func runnerScrollGesturePlan(
|
|
26
29
|
direction: String,
|