appium-webdriveragent 11.1.7 → 11.3.0
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/CHANGELOG.md +12 -0
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h +10 -1
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +82 -78
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [11.3.0](https://github.com/appium/WebDriverAgent/compare/v11.2.0...v11.3.0) (2026-03-05)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* add 6 tvOS button values for `mobile: pressButton` ([#1116](https://github.com/appium/WebDriverAgent/issues/1116)) ([efd64ed](https://github.com/appium/WebDriverAgent/commit/efd64ede7212b322f412cd6b25eab9c8097c286d))
|
|
6
|
+
|
|
7
|
+
## [11.2.0](https://github.com/appium/WebDriverAgent/compare/v11.1.7...v11.2.0) (2026-03-04)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add `action` and `camera` values for `mobile: pressButton` ([#1115](https://github.com/appium/WebDriverAgent/issues/1115)) ([3df0284](https://github.com/appium/WebDriverAgent/commit/3df0284d741f8b4a36a9e12e130ecf0711b60366))
|
|
12
|
+
|
|
1
13
|
## [11.1.7](https://github.com/appium/WebDriverAgent/compare/v11.1.6...v11.1.7) (2026-03-03)
|
|
2
14
|
|
|
3
15
|
### Miscellaneous Chores
|
|
@@ -95,10 +95,19 @@ typedef NS_ENUM(NSUInteger, FBUIInterfaceAppearance) {
|
|
|
95
95
|
*/
|
|
96
96
|
- (BOOL)fb_openUrl:(NSString *)url withApplication:(NSString *)bundleId error:(NSError **)error;
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
Checks if the device has a specific hardware button available.
|
|
100
|
+
|
|
101
|
+
@param buttonName The name of the button to check (e.g., "home", "volumeUp", "volumeDown", "action", "camera")
|
|
102
|
+
@return YES if the button is available on the device, otherwise NO
|
|
103
|
+
*/
|
|
104
|
+
- (BOOL)fb_hasButton:(NSString *)buttonName;
|
|
105
|
+
|
|
98
106
|
/**
|
|
99
107
|
Presses the corresponding hardware button on the device with duration.
|
|
100
108
|
|
|
101
|
-
@param buttonName One of the supported button names: volumeUp (real devices only), volumeDown (real device only),
|
|
109
|
+
@param buttonName One of the supported button names: volumeUp (real devices only), volumeDown (real device only),
|
|
110
|
+
camera (supported iOS 16+ real devices only), action (supported iOS 16+ devices only), home
|
|
102
111
|
@param duration Duration in seconds or nil.
|
|
103
112
|
This argument works only on tvOS. When this argument is nil on tvOS,
|
|
104
113
|
https://developer.apple.com/documentation/xctest/xcuiremote/1627476-pressbutton will be called.
|
|
@@ -26,6 +26,66 @@
|
|
|
26
26
|
static const NSTimeInterval FBHomeButtonCoolOffTime = 1.;
|
|
27
27
|
static const NSTimeInterval FBScreenLockTimeout = 5.;
|
|
28
28
|
|
|
29
|
+
#if TARGET_OS_TV
|
|
30
|
+
NSDictionary<NSString *, NSNumber *> *fb_availableButtonNames(void) {
|
|
31
|
+
static dispatch_once_t onceToken;
|
|
32
|
+
static NSDictionary *result;
|
|
33
|
+
dispatch_once(&onceToken, ^{
|
|
34
|
+
NSMutableDictionary *buttons = [NSMutableDictionary dictionary];
|
|
35
|
+
// https://developer.apple.com/design/human-interface-guidelines/remotes
|
|
36
|
+
buttons[@"up"] = @(XCUIRemoteButtonUp); // 0
|
|
37
|
+
buttons[@"down"] = @(XCUIRemoteButtonDown); // 1
|
|
38
|
+
buttons[@"left"] = @(XCUIRemoteButtonLeft); // 2
|
|
39
|
+
buttons[@"right"] = @(XCUIRemoteButtonRight); // 3
|
|
40
|
+
buttons[@"select"] = @(XCUIRemoteButtonSelect); // 4
|
|
41
|
+
buttons[@"menu"] = @(XCUIRemoteButtonMenu); // 5
|
|
42
|
+
buttons[@"playpause"] = @(XCUIRemoteButtonPlayPause); // 6
|
|
43
|
+
buttons[@"home"] = @(XCUIRemoteButtonHome); // 7
|
|
44
|
+
#if __clang_major__ >= 15 // Xcode 15+
|
|
45
|
+
buttons[@"pageup"] = @(XCUIRemoteButtonPageUp); // 9
|
|
46
|
+
buttons[@"pagedown"] = @(XCUIRemoteButtonPageDown); // 10
|
|
47
|
+
buttons[@"guide"] = @(XCUIRemoteButtonGuide); // 11
|
|
48
|
+
#endif
|
|
49
|
+
#if __clang_major__ >= 17 // likely Xcode 16.3+
|
|
50
|
+
if (@available(tvOS 18.1, *)) {
|
|
51
|
+
buttons[@"fourcolors"] = @(XCUIRemoteButtonFourColors); // 12
|
|
52
|
+
buttons[@"onetwothree"] = @(XCUIRemoteButtonOneTwoThree); // 13
|
|
53
|
+
buttons[@"tvprovider"] = @(XCUIRemoteButtonTVProvider); // 14
|
|
54
|
+
}
|
|
55
|
+
#endif
|
|
56
|
+
result = [buttons copy];
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
#else
|
|
61
|
+
NSDictionary<NSString *, NSNumber *> *fb_availableButtonNames(void) {
|
|
62
|
+
static dispatch_once_t onceToken;
|
|
63
|
+
static NSDictionary *result;
|
|
64
|
+
dispatch_once(&onceToken, ^{
|
|
65
|
+
NSMutableDictionary *buttons = [NSMutableDictionary dictionary];
|
|
66
|
+
buttons[@"home"] = @(XCUIDeviceButtonHome); // 1
|
|
67
|
+
#if !TARGET_OS_SIMULATOR
|
|
68
|
+
buttons[@"volumeup"] = @(XCUIDeviceButtonVolumeUp); // 2
|
|
69
|
+
buttons[@"volumedown"] = @(XCUIDeviceButtonVolumeDown); // 3
|
|
70
|
+
#endif
|
|
71
|
+
if (@available(iOS 16.0, *)) {
|
|
72
|
+
#if __clang_major__ >= 15 // likely Xcode 15+
|
|
73
|
+
if ([XCUIDevice.sharedDevice hasHardwareButton:XCUIDeviceButtonAction]) {
|
|
74
|
+
buttons[@"action"] = @(XCUIDeviceButtonAction); // 4
|
|
75
|
+
}
|
|
76
|
+
#endif
|
|
77
|
+
#if (!TARGET_OS_SIMULATOR && __clang_major__ >= 16) // likely Xcode 16+
|
|
78
|
+
if ([XCUIDevice.sharedDevice hasHardwareButton:XCUIDeviceButtonCamera]) {
|
|
79
|
+
buttons[@"camera"] = @(XCUIDeviceButtonCamera);
|
|
80
|
+
}
|
|
81
|
+
#endif
|
|
82
|
+
}
|
|
83
|
+
result = [buttons copy];
|
|
84
|
+
});
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
#endif
|
|
88
|
+
|
|
29
89
|
@implementation XCUIDevice (FBHelpers)
|
|
30
90
|
|
|
31
91
|
static bool fb_isLocked;
|
|
@@ -210,6 +270,11 @@ static bool fb_isLocked;
|
|
|
210
270
|
}
|
|
211
271
|
}
|
|
212
272
|
|
|
273
|
+
- (BOOL)fb_hasButton:(NSString *)buttonName
|
|
274
|
+
{
|
|
275
|
+
return fb_availableButtonNames()[buttonName.lowercaseString] != nil;
|
|
276
|
+
}
|
|
277
|
+
|
|
213
278
|
- (BOOL)fb_pressButton:(NSString *)buttonName
|
|
214
279
|
forDuration:(nullable NSNumber *)duration
|
|
215
280
|
error:(NSError **)error
|
|
@@ -217,71 +282,23 @@ static bool fb_isLocked;
|
|
|
217
282
|
#if !TARGET_OS_TV
|
|
218
283
|
return [self fb_pressButton:buttonName error:error];
|
|
219
284
|
#else
|
|
220
|
-
NSMutableArray<NSString *> *supportedButtonNames = [NSMutableArray array];
|
|
221
|
-
NSInteger remoteButton = -1; // no remote button
|
|
222
|
-
if ([buttonName.lowercaseString isEqualToString:@"home"]) {
|
|
223
|
-
// XCUIRemoteButtonHome = 7
|
|
224
|
-
remoteButton = XCUIRemoteButtonHome;
|
|
225
|
-
}
|
|
226
|
-
[supportedButtonNames addObject:@"home"];
|
|
227
|
-
|
|
228
|
-
// https://developer.apple.com/design/human-interface-guidelines/tvos/remote-and-controllers/remote/
|
|
229
|
-
if ([buttonName.lowercaseString isEqualToString:@"up"]) {
|
|
230
|
-
// XCUIRemoteButtonUp = 0,
|
|
231
|
-
remoteButton = XCUIRemoteButtonUp;
|
|
232
|
-
}
|
|
233
|
-
[supportedButtonNames addObject:@"up"];
|
|
234
285
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
if ([buttonName.lowercaseString isEqualToString:@"left"]) {
|
|
242
|
-
// XCUIRemoteButtonLeft = 2,
|
|
243
|
-
remoteButton = XCUIRemoteButtonLeft;
|
|
244
|
-
}
|
|
245
|
-
[supportedButtonNames addObject:@"left"];
|
|
246
|
-
|
|
247
|
-
if ([buttonName.lowercaseString isEqualToString:@"right"]) {
|
|
248
|
-
// XCUIRemoteButtonRight = 3,
|
|
249
|
-
remoteButton = XCUIRemoteButtonRight;
|
|
250
|
-
}
|
|
251
|
-
[supportedButtonNames addObject:@"right"];
|
|
252
|
-
|
|
253
|
-
if ([buttonName.lowercaseString isEqualToString:@"menu"]) {
|
|
254
|
-
// XCUIRemoteButtonMenu = 5,
|
|
255
|
-
remoteButton = XCUIRemoteButtonMenu;
|
|
256
|
-
}
|
|
257
|
-
[supportedButtonNames addObject:@"menu"];
|
|
258
|
-
|
|
259
|
-
if ([buttonName.lowercaseString isEqualToString:@"playpause"]) {
|
|
260
|
-
// XCUIRemoteButtonPlayPause = 6,
|
|
261
|
-
remoteButton = XCUIRemoteButtonPlayPause;
|
|
262
|
-
}
|
|
263
|
-
[supportedButtonNames addObject:@"playpause"];
|
|
264
|
-
|
|
265
|
-
if ([buttonName.lowercaseString isEqualToString:@"select"]) {
|
|
266
|
-
// XCUIRemoteButtonSelect = 4,
|
|
267
|
-
remoteButton = XCUIRemoteButtonSelect;
|
|
268
|
-
}
|
|
269
|
-
[supportedButtonNames addObject:@"select"];
|
|
270
|
-
|
|
271
|
-
if (remoteButton == -1) {
|
|
286
|
+
NSDictionary<NSString *, NSNumber *> *availableButtons = fb_availableButtonNames();
|
|
287
|
+
NSNumber *buttonValue = availableButtons[buttonName.lowercaseString];
|
|
288
|
+
|
|
289
|
+
if (!buttonValue) {
|
|
290
|
+
NSArray *sortedKeys = [availableButtons.allKeys sortedArrayUsingSelector:@selector(compare:)];
|
|
272
291
|
return [[[FBErrorBuilder builder]
|
|
273
|
-
withDescriptionFormat:@"The button '%@' is
|
|
292
|
+
withDescriptionFormat:@"The button '%@' is not supported. The device under test only supports the following buttons: %@", buttonName, sortedKeys]
|
|
274
293
|
buildError:error];
|
|
275
294
|
}
|
|
276
|
-
|
|
277
295
|
if (duration) {
|
|
278
|
-
// https://developer.apple.com/documentation/
|
|
279
|
-
[[XCUIRemote sharedRemote] pressButton:
|
|
296
|
+
// https://developer.apple.com/documentation/xcuiautomation/xcuiremote/press(_:forduration:)
|
|
297
|
+
[[XCUIRemote sharedRemote] pressButton:(XCUIRemoteButton)[buttonValue unsignedIntegerValue] forDuration:duration.doubleValue];
|
|
280
298
|
} else {
|
|
281
|
-
// https://developer.apple.com/documentation/
|
|
282
|
-
[[XCUIRemote sharedRemote] pressButton:
|
|
299
|
+
// https://developer.apple.com/documentation/xcuiautomation/xcuiremote/press(_:)
|
|
300
|
+
[[XCUIRemote sharedRemote] pressButton:(XCUIRemoteButton)[buttonValue unsignedIntegerValue]];
|
|
283
301
|
}
|
|
284
|
-
|
|
285
302
|
return YES;
|
|
286
303
|
#endif
|
|
287
304
|
}
|
|
@@ -290,29 +307,16 @@ static bool fb_isLocked;
|
|
|
290
307
|
- (BOOL)fb_pressButton:(NSString *)buttonName
|
|
291
308
|
error:(NSError **)error
|
|
292
309
|
{
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
[supportedButtonNames addObject:@"home"];
|
|
299
|
-
#if !TARGET_OS_SIMULATOR
|
|
300
|
-
if ([buttonName.lowercaseString isEqualToString:@"volumeup"]) {
|
|
301
|
-
dstButton = XCUIDeviceButtonVolumeUp;
|
|
302
|
-
}
|
|
303
|
-
if ([buttonName.lowercaseString isEqualToString:@"volumedown"]) {
|
|
304
|
-
dstButton = XCUIDeviceButtonVolumeDown;
|
|
305
|
-
}
|
|
306
|
-
[supportedButtonNames addObject:@"volumeUp"];
|
|
307
|
-
[supportedButtonNames addObject:@"volumeDown"];
|
|
308
|
-
#endif
|
|
309
|
-
|
|
310
|
-
if (dstButton == 0) {
|
|
310
|
+
NSDictionary<NSString *, NSNumber *> *availableButtons = fb_availableButtonNames();
|
|
311
|
+
NSNumber *buttonValue = availableButtons[buttonName.lowercaseString];
|
|
312
|
+
|
|
313
|
+
if (!buttonValue) {
|
|
314
|
+
NSArray *sortedKeys = [availableButtons.allKeys sortedArrayUsingSelector:@selector(compare:)];
|
|
311
315
|
return [[[FBErrorBuilder builder]
|
|
312
|
-
withDescriptionFormat:@"The button '%@' is
|
|
316
|
+
withDescriptionFormat:@"The button '%@' is not supported. The device under test only supports the following buttons: %@", buttonName, sortedKeys]
|
|
313
317
|
buildError:error];
|
|
314
318
|
}
|
|
315
|
-
[self pressButton:
|
|
319
|
+
[self pressButton:(XCUIDeviceButton)[buttonValue unsignedIntegerValue]];
|
|
316
320
|
return YES;
|
|
317
321
|
}
|
|
318
322
|
#endif
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>11.
|
|
18
|
+
<string>11.3.0</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>11.
|
|
22
|
+
<string>11.3.0</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -186,6 +186,22 @@
|
|
|
186
186
|
XCTAssertNil(error);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
- (void)testPressingDeviceSpecificButton
|
|
190
|
+
{
|
|
191
|
+
NSError *error;
|
|
192
|
+
BOOL hasActionButton = [XCUIDevice.sharedDevice fb_hasButton:@"action"];
|
|
193
|
+
BOOL didPressButton = [XCUIDevice.sharedDevice fb_pressButton:@"action"
|
|
194
|
+
forDuration:nil
|
|
195
|
+
error:&error];
|
|
196
|
+
if (hasActionButton) {
|
|
197
|
+
XCTAssertTrue(didPressButton);
|
|
198
|
+
XCTAssertNil(error);
|
|
199
|
+
} else {
|
|
200
|
+
XCTAssertFalse(didPressButton);
|
|
201
|
+
XCTAssertNotNil(error);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
189
205
|
- (void)testPressingSupportedButtonNumber
|
|
190
206
|
{
|
|
191
207
|
NSError *error;
|