agent-device 0.20.5 → 0.20.6
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/README.md +2 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.apk → agent-device-android-ime-helper-0.20.6.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.manifest.json → agent-device-android-ime-helper-0.20.6.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.apk → agent-device-android-snapshot-helper-0.20.6.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.manifest.json → agent-device-android-snapshot-helper-0.20.6.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +41 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +298 -92
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +118 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +134 -27
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +48 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +177 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +105 -448
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +587 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android.js +1 -1
- package/dist/src/app-log-request-scope.js +1 -1
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +34 -24
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -15
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/context.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -0
- package/dist/src/generic.js +1 -1
- package/dist/src/ime-lifecycle.js +3 -3
- package/dist/src/index.d.ts +27 -7
- package/dist/src/input-actions.js +4 -4
- package/dist/src/interaction-runtime.js +1 -0
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +15 -15
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +23 -2
- package/dist/src/linux.js +1 -1
- package/dist/src/process-exit.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +25 -24
- package/dist/src/remote-config.js +1 -1
- package/dist/src/remote-config2.js +1 -1
- 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-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/screenshot-geometry.js +1 -1
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/sdk-android-adb.d.ts +20 -2
- package/dist/src/sdk-android-adb.js +1 -1
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +17 -2
- package/dist/src/sdk-finders.d.ts +4 -20
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/{interaction.d.ts → sdk-selectors.d.ts} +98 -3
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.d.ts +1 -46
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +9 -9
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/text-surface.js +1 -0
- package/dist/src/viewport-dimension.js +13 -12
- package/dist/src/web.js +1 -1
- package/package.json +41 -35
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +0 -1
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m
CHANGED
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
#import "RunnerSynthesizedGesture.h"
|
|
2
|
+
#import "RunnerXCTestEventBridge.h"
|
|
2
3
|
|
|
3
4
|
#import <CoreGraphics/CoreGraphics.h>
|
|
4
5
|
#import <objc/message.h>
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
static NSString *const RunnerGestureSynthesisSurface = @"event";
|
|
8
|
+
|
|
7
9
|
typedef id (*RunnerMsgSendInitRecord)(id, SEL, NSString *, NSInteger);
|
|
8
10
|
typedef id (*RunnerMsgSendInitPath)(id, SEL, CGPoint, NSTimeInterval);
|
|
9
11
|
typedef void (*RunnerMsgSendPathMove)(id, SEL, CGPoint, NSTimeInterval);
|
|
10
12
|
typedef void (*RunnerMsgSendPathOffset)(id, SEL, NSTimeInterval);
|
|
11
|
-
typedef void (*RunnerMsgSendAddPath)(id, SEL, id);
|
|
12
|
-
typedef void (*RunnerMsgSendSetInteger)(id, SEL, NSInteger);
|
|
13
|
-
typedef BOOL (*RunnerMsgSendSynthesize)(id, SEL, NSError **);
|
|
14
13
|
|
|
14
|
+
// Gesture-specific extension of the shared bridge: the 2-arg
|
|
15
|
+
// `initWithName:interfaceOrientation:` record initializer and the touch-path
|
|
16
|
+
// factory/mutator selectors, none of which text-entry synthesis needs.
|
|
15
17
|
typedef struct {
|
|
16
|
-
|
|
17
|
-
Class pathClass;
|
|
18
|
+
RunnerXCTestEventBridge core;
|
|
18
19
|
SEL initRecordSelector;
|
|
19
|
-
SEL addPathSelector;
|
|
20
|
-
SEL setTargetProcessIDSelector;
|
|
21
|
-
SEL synthesizeSelector;
|
|
22
20
|
SEL interfaceOrientationSelector;
|
|
23
|
-
SEL processIDSelector;
|
|
24
21
|
SEL initPathSelector;
|
|
25
22
|
SEL moveSelector;
|
|
26
23
|
SEL liftSelector;
|
|
27
|
-
}
|
|
24
|
+
} RunnerGestureEventBridge;
|
|
28
25
|
|
|
29
26
|
typedef id (*RunnerDragPointerPathFactory)(
|
|
30
|
-
const
|
|
27
|
+
const RunnerGestureEventBridge *,
|
|
31
28
|
CGPoint,
|
|
32
29
|
CGPoint,
|
|
33
30
|
double
|
|
34
31
|
);
|
|
35
32
|
|
|
36
|
-
static NSString * _Nullable
|
|
33
|
+
static NSString * _Nullable RunnerResolveGestureEventBridge(
|
|
34
|
+
id application,
|
|
35
|
+
RunnerGestureEventBridge *bridge
|
|
36
|
+
);
|
|
37
|
+
static NSString * _Nullable RunnerCreateEventRecord(
|
|
37
38
|
id application,
|
|
38
|
-
|
|
39
|
+
NSString *recordName,
|
|
40
|
+
RunnerGestureEventBridge *bridge,
|
|
41
|
+
id *record
|
|
42
|
+
);
|
|
43
|
+
static NSString * _Nullable RunnerSynthesizeEventRecord(
|
|
44
|
+
const RunnerGestureEventBridge *bridge,
|
|
45
|
+
id record
|
|
39
46
|
);
|
|
40
|
-
static NSString * _Nullable RunnerRequireClass(Class cls, NSString *className);
|
|
41
|
-
static NSString * _Nullable RunnerRequireSelector(Class cls, SEL selector, NSString *selectorName);
|
|
42
|
-
static NSString * _Nullable RunnerRequireApplicationSelector(id application, SEL selector, NSString *selectorName);
|
|
43
47
|
static id RunnerSwipePointerPath(
|
|
44
|
-
const
|
|
48
|
+
const RunnerGestureEventBridge *bridge,
|
|
45
49
|
CGPoint start,
|
|
46
50
|
CGPoint end,
|
|
47
51
|
double durationMs
|
|
48
52
|
);
|
|
49
53
|
static id RunnerContinuousDragPointerPath(
|
|
50
|
-
const
|
|
54
|
+
const RunnerGestureEventBridge *bridge,
|
|
51
55
|
CGPoint start,
|
|
52
56
|
CGPoint end,
|
|
53
57
|
double durationMs
|
|
@@ -60,11 +64,12 @@ static NSString * _Nullable RunnerTrySynthesizeDrag(
|
|
|
60
64
|
NSString *recordName,
|
|
61
65
|
RunnerDragPointerPathFactory pathFactory
|
|
62
66
|
);
|
|
67
|
+
static NSString * _Nullable RunnerTrySynthesizeTap(id application, CGPoint point);
|
|
63
68
|
// XCTest's proven swipe profile reaches the endpoint in 100 ms, then holds for the planned
|
|
64
69
|
// fling duration. Fast movement is what lets UIKit distinguish a fling from a timed pan.
|
|
65
70
|
static const NSTimeInterval RunnerSwipeMovementDurationSeconds = 0.1;
|
|
66
71
|
static id RunnerTapPointerPath(
|
|
67
|
-
const
|
|
72
|
+
const RunnerGestureEventBridge *bridge,
|
|
68
73
|
CGPoint point
|
|
69
74
|
);
|
|
70
75
|
|
|
@@ -86,9 +91,7 @@ static id RunnerTapPointerPath(
|
|
|
86
91
|
RunnerSwipePointerPath
|
|
87
92
|
);
|
|
88
93
|
} @catch (NSException *exception) {
|
|
89
|
-
|
|
90
|
-
NSString *reason = exception.reason ?: @"private XCTest event synthesis failed";
|
|
91
|
-
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
94
|
+
return RunnerFormatXCTestException(exception, @"private XCTest event synthesis failed");
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -108,9 +111,7 @@ static id RunnerTapPointerPath(
|
|
|
108
111
|
RunnerContinuousDragPointerPath
|
|
109
112
|
);
|
|
110
113
|
} @catch (NSException *exception) {
|
|
111
|
-
|
|
112
|
-
NSString *reason = exception.reason ?: @"private XCTest event synthesis failed";
|
|
113
|
-
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
114
|
+
return RunnerFormatXCTestException(exception, @"private XCTest event synthesis failed");
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
|
|
@@ -118,46 +119,31 @@ static id RunnerTapPointerPath(
|
|
|
118
119
|
x:(double)x
|
|
119
120
|
y:(double)y {
|
|
120
121
|
@try {
|
|
121
|
-
return
|
|
122
|
+
return RunnerTrySynthesizeTap(application, CGPointMake(x, y));
|
|
122
123
|
} @catch (NSException *exception) {
|
|
123
|
-
|
|
124
|
-
NSString *reason = exception.reason ?: @"private XCTest event synthesis failed";
|
|
125
|
-
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
124
|
+
return RunnerFormatXCTestException(exception, @"private XCTest event synthesis failed");
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
+ (NSString * _Nullable)synthesizeGestureWithApplication:(id)application
|
|
130
129
|
pointerSamples:(NSArray<NSArray<NSDictionary<NSString *, NSNumber *> *> *> *)pointerSamples {
|
|
131
130
|
@try {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
NSInteger interfaceOrientation =
|
|
137
|
-
((RunnerMsgSendInteger)objc_msgSend)(application, bridge.interfaceOrientationSelector);
|
|
138
|
-
NSInteger targetProcessID =
|
|
139
|
-
((RunnerMsgSendInteger)objc_msgSend)(application, bridge.processIDSelector);
|
|
140
|
-
if (targetProcessID <= 0) {
|
|
141
|
-
return @"private XCTest event synthesis unavailable: could not resolve target process ID";
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
id record = ((RunnerMsgSendInitRecord)objc_msgSend)(
|
|
145
|
-
[bridge.recordClass alloc],
|
|
146
|
-
bridge.initRecordSelector,
|
|
131
|
+
RunnerGestureEventBridge bridge;
|
|
132
|
+
id record = nil;
|
|
133
|
+
NSString *error = RunnerCreateEventRecord(
|
|
134
|
+
application,
|
|
147
135
|
@"agent-device-gesture-plan",
|
|
148
|
-
|
|
136
|
+
&bridge,
|
|
137
|
+
&record
|
|
149
138
|
);
|
|
150
|
-
if (
|
|
151
|
-
return @"private XCTest event synthesis failed: could not create event record";
|
|
152
|
-
}
|
|
153
|
-
((RunnerMsgSendSetInteger)objc_msgSend)(record, bridge.setTargetProcessIDSelector, targetProcessID);
|
|
139
|
+
if (error != nil) return error;
|
|
154
140
|
|
|
155
141
|
for (NSArray<NSDictionary<NSString *, NSNumber *> *> *samples in pointerSamples) {
|
|
156
142
|
NSDictionary<NSString *, NSNumber *> *first = samples.firstObject;
|
|
157
143
|
if (first == nil) return @"private XCTest event synthesis failed: empty pointer path";
|
|
158
144
|
CGPoint start = CGPointMake(first[@"x"].doubleValue, first[@"y"].doubleValue);
|
|
159
145
|
id path = ((RunnerMsgSendInitPath)objc_msgSend)(
|
|
160
|
-
[bridge.pathClass alloc],
|
|
146
|
+
[bridge.core.pathClass alloc],
|
|
161
147
|
bridge.initPathSelector,
|
|
162
148
|
start,
|
|
163
149
|
first[@"offsetMs"].doubleValue / 1000.0
|
|
@@ -181,20 +167,12 @@ static id RunnerTapPointerPath(
|
|
|
181
167
|
bridge.liftSelector,
|
|
182
168
|
last[@"offsetMs"].doubleValue / 1000.0
|
|
183
169
|
);
|
|
184
|
-
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.addPathSelector, path);
|
|
170
|
+
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.core.addPathSelector, path);
|
|
185
171
|
}
|
|
186
172
|
|
|
187
|
-
|
|
188
|
-
BOOL ok = ((RunnerMsgSendSynthesize)objc_msgSend)(record, bridge.synthesizeSelector, &error);
|
|
189
|
-
if (!ok) {
|
|
190
|
-
NSString *detail = error.localizedDescription ?: @"synthesizeWithError returned false";
|
|
191
|
-
return [NSString stringWithFormat:@"private XCTest event synthesis failed: %@", detail];
|
|
192
|
-
}
|
|
193
|
-
return nil;
|
|
173
|
+
return RunnerSynthesizeEventRecord(&bridge, record);
|
|
194
174
|
} @catch (NSException *exception) {
|
|
195
|
-
|
|
196
|
-
NSString *reason = exception.reason ?: @"private XCTest event synthesis failed";
|
|
197
|
-
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
175
|
+
return RunnerFormatXCTestException(exception, @"private XCTest event synthesis failed");
|
|
198
176
|
}
|
|
199
177
|
}
|
|
200
178
|
|
|
@@ -214,135 +192,78 @@ static NSString * _Nullable RunnerTrySynthesizeDrag(
|
|
|
214
192
|
NSString *recordName,
|
|
215
193
|
RunnerDragPointerPathFactory pathFactory
|
|
216
194
|
) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
NSInteger interfaceOrientation =
|
|
224
|
-
((RunnerMsgSendInteger)objc_msgSend)(application, bridge.interfaceOrientationSelector);
|
|
225
|
-
NSInteger targetProcessID = ((RunnerMsgSendInteger)objc_msgSend)(application, bridge.processIDSelector);
|
|
226
|
-
if (targetProcessID <= 0) {
|
|
227
|
-
return @"private XCTest event synthesis unavailable: could not resolve target process ID";
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
id record = ((RunnerMsgSendInitRecord)objc_msgSend)(
|
|
231
|
-
[bridge.recordClass alloc],
|
|
232
|
-
bridge.initRecordSelector,
|
|
233
|
-
recordName,
|
|
234
|
-
interfaceOrientation
|
|
235
|
-
);
|
|
236
|
-
if (record == nil) {
|
|
237
|
-
return @"private XCTest event synthesis failed: could not create event record";
|
|
238
|
-
}
|
|
239
|
-
((RunnerMsgSendSetInteger)objc_msgSend)(record, bridge.setTargetProcessIDSelector, targetProcessID);
|
|
195
|
+
RunnerGestureEventBridge bridge;
|
|
196
|
+
id record = nil;
|
|
197
|
+
NSString *error = RunnerCreateEventRecord(application, recordName, &bridge, &record);
|
|
198
|
+
if (error != nil) return error;
|
|
240
199
|
|
|
241
200
|
id path = pathFactory(&bridge, start, end, durationMs);
|
|
242
201
|
if (path == nil) {
|
|
243
202
|
return @"private XCTest event synthesis failed: could not create pointer path";
|
|
244
203
|
}
|
|
245
|
-
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.addPathSelector, path);
|
|
204
|
+
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.core.addPathSelector, path);
|
|
246
205
|
|
|
247
|
-
|
|
248
|
-
BOOL ok = ((RunnerMsgSendSynthesize)objc_msgSend)(record, bridge.synthesizeSelector, &error);
|
|
249
|
-
if (!ok) {
|
|
250
|
-
NSString *detail = error.localizedDescription ?: @"synthesizeWithError returned false";
|
|
251
|
-
return [NSString stringWithFormat:@"private XCTest event synthesis failed: %@", detail];
|
|
252
|
-
}
|
|
253
|
-
return nil;
|
|
206
|
+
return RunnerSynthesizeEventRecord(&bridge, record);
|
|
254
207
|
}
|
|
255
208
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (missing != nil) {
|
|
262
|
-
return missing;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
NSInteger interfaceOrientation =
|
|
266
|
-
((RunnerMsgSendInteger)objc_msgSend)(application, bridge.interfaceOrientationSelector);
|
|
267
|
-
NSInteger targetProcessID = ((RunnerMsgSendInteger)objc_msgSend)(application, bridge.processIDSelector);
|
|
268
|
-
if (targetProcessID <= 0) {
|
|
269
|
-
return @"private XCTest event synthesis unavailable: could not resolve target process ID";
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
id record = ((RunnerMsgSendInitRecord)objc_msgSend)(
|
|
273
|
-
[bridge.recordClass alloc],
|
|
274
|
-
bridge.initRecordSelector,
|
|
209
|
+
static NSString * _Nullable RunnerTrySynthesizeTap(id application, CGPoint point) {
|
|
210
|
+
RunnerGestureEventBridge bridge;
|
|
211
|
+
id record = nil;
|
|
212
|
+
NSString *error = RunnerCreateEventRecord(
|
|
213
|
+
application,
|
|
275
214
|
@"agent-device-tap",
|
|
276
|
-
|
|
215
|
+
&bridge,
|
|
216
|
+
&record
|
|
277
217
|
);
|
|
278
|
-
if (
|
|
279
|
-
return @"private XCTest event synthesis failed: could not create event record";
|
|
280
|
-
}
|
|
281
|
-
((RunnerMsgSendSetInteger)objc_msgSend)(record, bridge.setTargetProcessIDSelector, targetProcessID);
|
|
218
|
+
if (error != nil) return error;
|
|
282
219
|
|
|
283
|
-
id path = RunnerTapPointerPath(&bridge,
|
|
220
|
+
id path = RunnerTapPointerPath(&bridge, point);
|
|
284
221
|
if (path == nil) {
|
|
285
222
|
return @"private XCTest event synthesis failed: could not create pointer path";
|
|
286
223
|
}
|
|
287
|
-
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.addPathSelector, path);
|
|
288
|
-
|
|
289
|
-
NSError *error = nil;
|
|
290
|
-
BOOL ok = ((RunnerMsgSendSynthesize)objc_msgSend)(record, bridge.synthesizeSelector, &error);
|
|
291
|
-
if (!ok) {
|
|
292
|
-
NSString *detail = error.localizedDescription ?: @"synthesizeWithError returned false";
|
|
293
|
-
return [NSString stringWithFormat:@"private XCTest event synthesis failed: %@", detail];
|
|
294
|
-
}
|
|
295
|
-
return nil;
|
|
224
|
+
((RunnerMsgSendAddPath)objc_msgSend)(record, bridge.core.addPathSelector, path);
|
|
225
|
+
return RunnerSynthesizeEventRecord(&bridge, record);
|
|
296
226
|
}
|
|
297
227
|
|
|
298
|
-
static NSString * _Nullable
|
|
228
|
+
static NSString * _Nullable RunnerResolveGestureEventBridge(
|
|
299
229
|
id application,
|
|
300
|
-
|
|
230
|
+
RunnerGestureEventBridge *bridge
|
|
301
231
|
) {
|
|
302
|
-
|
|
303
|
-
|
|
232
|
+
RunnerXCTestEventBridge core;
|
|
233
|
+
NSString *missing = RunnerResolveXCTestEventBridge(application, RunnerGestureSynthesisSurface, &core);
|
|
234
|
+
if (missing != nil) return missing;
|
|
235
|
+
|
|
304
236
|
SEL initRecordSelector = NSSelectorFromString(@"initWithName:interfaceOrientation:");
|
|
305
|
-
SEL addPathSelector = NSSelectorFromString(@"addPointerEventPath:");
|
|
306
|
-
SEL setTargetProcessIDSelector = NSSelectorFromString(@"setTargetProcessID:");
|
|
307
|
-
SEL synthesizeSelector = NSSelectorFromString(@"synthesizeWithError:");
|
|
308
237
|
SEL interfaceOrientationSelector = NSSelectorFromString(@"interfaceOrientation");
|
|
309
|
-
SEL processIDSelector = NSSelectorFromString(@"processID");
|
|
310
238
|
SEL initPathSelector = NSSelectorFromString(@"initForTouchAtPoint:offset:");
|
|
311
239
|
SEL moveSelector = NSSelectorFromString(@"moveToPoint:atOffset:");
|
|
312
240
|
SEL liftSelector = NSSelectorFromString(@"liftUpAtOffset:");
|
|
313
241
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (missing != nil) return missing;
|
|
318
|
-
missing = RunnerRequireSelector(recordClass, initRecordSelector, @"initWithName:interfaceOrientation:");
|
|
319
|
-
if (missing != nil) return missing;
|
|
320
|
-
missing = RunnerRequireSelector(recordClass, addPathSelector, @"addPointerEventPath:");
|
|
321
|
-
if (missing != nil) return missing;
|
|
322
|
-
missing = RunnerRequireSelector(recordClass, setTargetProcessIDSelector, @"setTargetProcessID:");
|
|
323
|
-
if (missing != nil) return missing;
|
|
324
|
-
missing = RunnerRequireSelector(recordClass, synthesizeSelector, @"synthesizeWithError:");
|
|
325
|
-
if (missing != nil) return missing;
|
|
326
|
-
missing = RunnerRequireSelector(pathClass, initPathSelector, @"initForTouchAtPoint:offset:");
|
|
242
|
+
missing = RunnerRequireSelector(
|
|
243
|
+
core.recordClass, initRecordSelector, @"initWithName:interfaceOrientation:", RunnerGestureSynthesisSurface
|
|
244
|
+
);
|
|
327
245
|
if (missing != nil) return missing;
|
|
328
|
-
missing = RunnerRequireSelector(
|
|
246
|
+
missing = RunnerRequireSelector(
|
|
247
|
+
core.pathClass, initPathSelector, @"initForTouchAtPoint:offset:", RunnerGestureSynthesisSurface
|
|
248
|
+
);
|
|
329
249
|
if (missing != nil) return missing;
|
|
330
|
-
missing = RunnerRequireSelector(
|
|
250
|
+
missing = RunnerRequireSelector(
|
|
251
|
+
core.pathClass, moveSelector, @"moveToPoint:atOffset:", RunnerGestureSynthesisSurface
|
|
252
|
+
);
|
|
331
253
|
if (missing != nil) return missing;
|
|
332
|
-
missing =
|
|
254
|
+
missing = RunnerRequireSelector(
|
|
255
|
+
core.pathClass, liftSelector, @"liftUpAtOffset:", RunnerGestureSynthesisSurface
|
|
256
|
+
);
|
|
333
257
|
if (missing != nil) return missing;
|
|
334
|
-
missing = RunnerRequireApplicationSelector(
|
|
258
|
+
missing = RunnerRequireApplicationSelector(
|
|
259
|
+
application, interfaceOrientationSelector, @"interfaceOrientation", RunnerGestureSynthesisSurface
|
|
260
|
+
);
|
|
335
261
|
if (missing != nil) return missing;
|
|
336
262
|
|
|
337
|
-
*bridge = (
|
|
338
|
-
.
|
|
339
|
-
.pathClass = pathClass,
|
|
263
|
+
*bridge = (RunnerGestureEventBridge){
|
|
264
|
+
.core = core,
|
|
340
265
|
.initRecordSelector = initRecordSelector,
|
|
341
|
-
.addPathSelector = addPathSelector,
|
|
342
|
-
.setTargetProcessIDSelector = setTargetProcessIDSelector,
|
|
343
|
-
.synthesizeSelector = synthesizeSelector,
|
|
344
266
|
.interfaceOrientationSelector = interfaceOrientationSelector,
|
|
345
|
-
.processIDSelector = processIDSelector,
|
|
346
267
|
.initPathSelector = initPathSelector,
|
|
347
268
|
.moveSelector = moveSelector,
|
|
348
269
|
.liftSelector = liftSelector,
|
|
@@ -350,47 +271,62 @@ static NSString * _Nullable RunnerResolveXCTestEventBridge(
|
|
|
350
271
|
return nil;
|
|
351
272
|
}
|
|
352
273
|
|
|
353
|
-
static NSString * _Nullable
|
|
354
|
-
|
|
355
|
-
|
|
274
|
+
static NSString * _Nullable RunnerCreateEventRecord(
|
|
275
|
+
id application,
|
|
276
|
+
NSString *recordName,
|
|
277
|
+
RunnerGestureEventBridge *bridge,
|
|
278
|
+
id *record
|
|
279
|
+
) {
|
|
280
|
+
NSString *missing = RunnerResolveGestureEventBridge(application, bridge);
|
|
281
|
+
if (missing != nil) return missing;
|
|
282
|
+
|
|
283
|
+
NSInteger interfaceOrientation =
|
|
284
|
+
((RunnerMsgSendInteger)objc_msgSend)(application, bridge->interfaceOrientationSelector);
|
|
285
|
+
NSInteger targetProcessID =
|
|
286
|
+
((RunnerMsgSendInteger)objc_msgSend)(application, bridge->core.processIDSelector);
|
|
287
|
+
if (targetProcessID <= 0) {
|
|
288
|
+
return @"private XCTest event synthesis unavailable: could not resolve target process ID";
|
|
356
289
|
}
|
|
357
|
-
return nil;
|
|
358
|
-
}
|
|
359
290
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
291
|
+
id eventRecord = ((RunnerMsgSendInitRecord)objc_msgSend)(
|
|
292
|
+
[bridge->core.recordClass alloc],
|
|
293
|
+
bridge->initRecordSelector,
|
|
294
|
+
recordName,
|
|
295
|
+
interfaceOrientation
|
|
296
|
+
);
|
|
297
|
+
if (eventRecord == nil) {
|
|
298
|
+
return @"private XCTest event synthesis failed: could not create event record";
|
|
367
299
|
}
|
|
300
|
+
((RunnerMsgSendSetInteger)objc_msgSend)(
|
|
301
|
+
eventRecord,
|
|
302
|
+
bridge->core.setTargetProcessIDSelector,
|
|
303
|
+
targetProcessID
|
|
304
|
+
);
|
|
305
|
+
*record = eventRecord;
|
|
368
306
|
return nil;
|
|
369
307
|
}
|
|
370
308
|
|
|
371
|
-
static NSString * _Nullable
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
NSString *selectorName
|
|
309
|
+
static NSString * _Nullable RunnerSynthesizeEventRecord(
|
|
310
|
+
const RunnerGestureEventBridge *bridge,
|
|
311
|
+
id record
|
|
375
312
|
) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
];
|
|
313
|
+
NSError *error = nil;
|
|
314
|
+
BOOL ok = ((RunnerMsgSendSynthesize)objc_msgSend)(record, bridge->core.synthesizeSelector, &error);
|
|
315
|
+
if (!ok) {
|
|
316
|
+
NSString *detail = error.localizedDescription ?: @"synthesizeWithError returned false";
|
|
317
|
+
return [NSString stringWithFormat:@"private XCTest event synthesis failed: %@", detail];
|
|
381
318
|
}
|
|
382
319
|
return nil;
|
|
383
320
|
}
|
|
384
321
|
|
|
385
|
-
|
|
386
322
|
static id RunnerSwipePointerPath(
|
|
387
|
-
const
|
|
323
|
+
const RunnerGestureEventBridge *bridge,
|
|
388
324
|
CGPoint start,
|
|
389
325
|
CGPoint end,
|
|
390
326
|
double durationMs
|
|
391
327
|
) {
|
|
392
328
|
id path =
|
|
393
|
-
((RunnerMsgSendInitPath)objc_msgSend)([bridge->pathClass alloc], bridge->initPathSelector, start, 0.0);
|
|
329
|
+
((RunnerMsgSendInitPath)objc_msgSend)([bridge->core.pathClass alloc], bridge->initPathSelector, start, 0.0);
|
|
394
330
|
if (path == nil) {
|
|
395
331
|
return nil;
|
|
396
332
|
}
|
|
@@ -411,17 +347,20 @@ static id RunnerSwipePointerPath(
|
|
|
411
347
|
}
|
|
412
348
|
|
|
413
349
|
static id RunnerContinuousDragPointerPath(
|
|
414
|
-
const
|
|
350
|
+
const RunnerGestureEventBridge *bridge,
|
|
415
351
|
CGPoint start,
|
|
416
352
|
CGPoint end,
|
|
417
353
|
double durationMs
|
|
418
354
|
) {
|
|
419
355
|
id path =
|
|
420
|
-
((RunnerMsgSendInitPath)objc_msgSend)([bridge->pathClass alloc], bridge->initPathSelector, start, 0.0);
|
|
356
|
+
((RunnerMsgSendInitPath)objc_msgSend)([bridge->core.pathClass alloc], bridge->initPathSelector, start, 0.0);
|
|
421
357
|
if (path == nil) {
|
|
422
358
|
return nil;
|
|
423
359
|
}
|
|
424
360
|
|
|
361
|
+
// This is velocity shaping, not just interpolation density: smoothstep's endpoint slope is zero,
|
|
362
|
+
// while a planned linear segment reaches lift with nonzero velocity unless a destination hold
|
|
363
|
+
// follows it. UIKit uses finger-up velocity for scroll deceleration. See ADR 0013 and issue #1586.
|
|
425
364
|
int frameCount = MAX(3, (int)(durationMs / 16.0));
|
|
426
365
|
NSTimeInterval durationSeconds = durationMs / 1000.0;
|
|
427
366
|
for (int index = 1; index <= frameCount; index += 1) {
|
|
@@ -439,11 +378,11 @@ static id RunnerContinuousDragPointerPath(
|
|
|
439
378
|
}
|
|
440
379
|
|
|
441
380
|
static id RunnerTapPointerPath(
|
|
442
|
-
const
|
|
381
|
+
const RunnerGestureEventBridge *bridge,
|
|
443
382
|
CGPoint point
|
|
444
383
|
) {
|
|
445
384
|
id path =
|
|
446
|
-
((RunnerMsgSendInitPath)objc_msgSend)([bridge->pathClass alloc], bridge->initPathSelector, point, 0.0);
|
|
385
|
+
((RunnerMsgSendInitPath)objc_msgSend)([bridge->core.pathClass alloc], bridge->initPathSelector, point, 0.0);
|
|
447
386
|
if (path == nil) {
|
|
448
387
|
return nil;
|
|
449
388
|
}
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
typedef NS_ENUM(NSInteger, RunnerSynthesizedTextEntryStatus) {
|
|
6
|
+
RunnerSynthesizedTextEntryStatusSucceeded,
|
|
7
|
+
RunnerSynthesizedTextEntryStatusUnavailable,
|
|
8
|
+
RunnerSynthesizedTextEntryStatusFailed,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
@interface RunnerSynthesizedTextEntryResult : NSObject
|
|
12
|
+
|
|
13
|
+
@property(nonatomic, readonly) RunnerSynthesizedTextEntryStatus status;
|
|
14
|
+
@property(nonatomic, readonly, nullable) NSString *message;
|
|
15
|
+
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
@interface RunnerSynthesizedTextEntry : NSObject
|
|
19
|
+
|
|
20
|
+
// Synthesizes keyboard input for the current first responder without resolving an
|
|
21
|
+
// XCUIElement or serializing the application's accessibility tree.
|
|
22
|
+
+ (RunnerSynthesizedTextEntryResult *)synthesizeTextWithApplication:(id)application
|
|
23
|
+
text:(NSString *)text;
|
|
24
|
+
|
|
25
|
+
// Replaces the current first responder's contents using one synthesized
|
|
26
|
+
// Command-A, Delete, and text-input event sequence.
|
|
27
|
+
+ (RunnerSynthesizedTextEntryResult *)replaceTextWithApplication:(id)application
|
|
28
|
+
text:(NSString *)text;
|
|
29
|
+
|
|
30
|
+
@end
|
|
31
|
+
|
|
32
|
+
NS_ASSUME_NONNULL_END
|