appium-webdriveragent 5.4.0 → 5.5.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 +14 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +20 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +104 -0
- package/WebDriverAgentLib/Commands/FBCustomCommands.m +20 -0
- package/WebDriverAgentLib/FBApplication.m +1 -0
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +10 -6
- package/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +21 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [5.5.0](https://github.com/appium/WebDriverAgent/compare/v5.4.1...v5.5.0) (2023-06-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Add accessibility audit extension ([#727](https://github.com/appium/WebDriverAgent/issues/727)) ([78321dd](https://github.com/appium/WebDriverAgent/commit/78321dd3dafdb142eed136b48ec101f1daed50a4))
|
|
7
|
+
|
|
8
|
+
## [5.4.1](https://github.com/appium/WebDriverAgent/compare/v5.4.0...v5.4.1) (2023-06-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Return default testmanagerd version if the info is not available ([#728](https://github.com/appium/WebDriverAgent/issues/728)) ([e6e2dbd](https://github.com/appium/WebDriverAgent/commit/e6e2dbd86fc0c48ae146905f0e69a6223360e856))
|
|
14
|
+
|
|
1
15
|
## [5.4.0](https://github.com/appium/WebDriverAgent/compare/v5.3.3...v5.4.0) (2023-06-09)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -103,6 +103,26 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
103
103
|
- (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray<NSString *> *)keyNames
|
|
104
104
|
error:(NSError **)error;
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
A wrapper over https://developer.apple.com/documentation/xctest/xcuiapplication/4190847-performaccessibilityauditwithaud?language=objc
|
|
108
|
+
|
|
109
|
+
@param auditTypes Combination of https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc
|
|
110
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
111
|
+
@return List of found issues or nil if there was a failure
|
|
112
|
+
*/
|
|
113
|
+
- (nullable NSArray<NSDictionary<NSString *, NSString*> *> *)fb_performAccessibilityAuditWithAuditTypesSet:(NSSet<NSString *> *)auditTypes
|
|
114
|
+
error:(NSError **)error;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
A wrapper over https://developer.apple.com/documentation/xctest/xcuiapplication/4190847-performaccessibilityauditwithaud?language=objc
|
|
118
|
+
|
|
119
|
+
@param auditTypes Combination of https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc
|
|
120
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
121
|
+
@return List of found issues or nil if there was a failure
|
|
122
|
+
*/
|
|
123
|
+
- (nullable NSArray<NSDictionary<NSString *, NSString*> *> *)fb_performAccessibilityAuditWithAuditTypes:(uint64_t)auditTypes
|
|
124
|
+
error:(NSError **)error;
|
|
125
|
+
|
|
106
126
|
@end
|
|
107
127
|
|
|
108
128
|
NS_ASSUME_NONNULL_END
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#import "FBElementTypeTransformer.h"
|
|
13
13
|
#import "FBKeyboard.h"
|
|
14
14
|
#import "FBLogger.h"
|
|
15
|
+
#import "FBExceptions.h"
|
|
15
16
|
#import "FBMacros.h"
|
|
16
17
|
#import "FBMathUtils.h"
|
|
17
18
|
#import "FBActiveAppDetectionPoint.h"
|
|
@@ -33,6 +34,54 @@
|
|
|
33
34
|
|
|
34
35
|
static NSString* const FBUnknownBundleId = @"unknown";
|
|
35
36
|
|
|
37
|
+
_Nullable id extractIssueProperty(id issue, NSString *propertyName) {
|
|
38
|
+
SEL selector = NSSelectorFromString(propertyName);
|
|
39
|
+
NSMethodSignature *methodSignature = [issue methodSignatureForSelector:selector];
|
|
40
|
+
if (nil == methodSignature) {
|
|
41
|
+
return nil;
|
|
42
|
+
}
|
|
43
|
+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
|
44
|
+
[invocation setSelector:selector];
|
|
45
|
+
[invocation invokeWithTarget:issue];
|
|
46
|
+
id __unsafe_unretained result;
|
|
47
|
+
[invocation getReturnValue:&result];
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
NSDictionary<NSString *, NSNumber *> *auditTypeNamesToValues(void) {
|
|
52
|
+
static dispatch_once_t onceToken;
|
|
53
|
+
static NSDictionary *result;
|
|
54
|
+
dispatch_once(&onceToken, ^{
|
|
55
|
+
// https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc
|
|
56
|
+
result = @{
|
|
57
|
+
@"XCUIAccessibilityAuditTypeAction": @(1UL << 32),
|
|
58
|
+
@"XCUIAccessibilityAuditTypeAll": @(~0UL),
|
|
59
|
+
@"XCUIAccessibilityAuditTypeContrast": @(1UL << 0),
|
|
60
|
+
@"XCUIAccessibilityAuditTypeDynamicType": @(1UL << 16),
|
|
61
|
+
@"XCUIAccessibilityAuditTypeElementDetection": @(1UL << 1),
|
|
62
|
+
@"XCUIAccessibilityAuditTypeHitRegion": @(1UL << 2),
|
|
63
|
+
@"XCUIAccessibilityAuditTypeParentChild": @(1UL << 33),
|
|
64
|
+
@"XCUIAccessibilityAuditTypeSufficientElementDescription": @(1UL << 3),
|
|
65
|
+
@"XCUIAccessibilityAuditTypeTextClipped": @(1UL << 17),
|
|
66
|
+
@"XCUIAccessibilityAuditTypeTrait": @(1UL << 18),
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
NSDictionary<NSNumber *, NSString *> *auditTypeValuesToNames(void) {
|
|
73
|
+
static dispatch_once_t onceToken;
|
|
74
|
+
static NSDictionary *result;
|
|
75
|
+
dispatch_once(&onceToken, ^{
|
|
76
|
+
NSMutableDictionary *inverted = [NSMutableDictionary new];
|
|
77
|
+
[auditTypeNamesToValues() enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber *value, BOOL *stop) {
|
|
78
|
+
inverted[value] = key;
|
|
79
|
+
}];
|
|
80
|
+
result = inverted.copy;
|
|
81
|
+
});
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
36
85
|
|
|
37
86
|
@implementation XCUIApplication (FBHelpers)
|
|
38
87
|
|
|
@@ -281,4 +330,59 @@ static NSString* const FBUnknownBundleId = @"unknown";
|
|
|
281
330
|
error:error];
|
|
282
331
|
}
|
|
283
332
|
|
|
333
|
+
- (NSArray<NSDictionary<NSString *, NSString*> *> *)fb_performAccessibilityAuditWithAuditTypesSet:(NSSet<NSString *> *)auditTypes
|
|
334
|
+
error:(NSError **)error;
|
|
335
|
+
{
|
|
336
|
+
uint64_t numTypes = 0;
|
|
337
|
+
NSDictionary *namesMap = auditTypeNamesToValues();
|
|
338
|
+
for (NSString *value in auditTypes) {
|
|
339
|
+
NSNumber *typeValue = namesMap[value];
|
|
340
|
+
if (nil == typeValue) {
|
|
341
|
+
NSString *reason = [NSString stringWithFormat:@"Audit type value '%@' is not known. Only the following audit types are supported: %@", value, namesMap.allKeys];
|
|
342
|
+
@throw [NSException exceptionWithName:FBInvalidArgumentException reason:reason userInfo:@{}];
|
|
343
|
+
}
|
|
344
|
+
numTypes |= [typeValue unsignedLongLongValue];
|
|
345
|
+
}
|
|
346
|
+
return [self fb_performAccessibilityAuditWithAuditTypes:numTypes error:error];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
- (NSArray<NSDictionary<NSString *, NSString*> *> *)fb_performAccessibilityAuditWithAuditTypes:(uint64_t)auditTypes
|
|
350
|
+
error:(NSError **)error;
|
|
351
|
+
{
|
|
352
|
+
SEL selector = NSSelectorFromString(@"performAccessibilityAuditWithAuditTypes:issueHandler:error:");
|
|
353
|
+
if (![self respondsToSelector:selector]) {
|
|
354
|
+
[[[FBErrorBuilder alloc]
|
|
355
|
+
withDescription:@"Accessibility audit is only supported since iOS 17/Xcode 15"]
|
|
356
|
+
buildError:error];
|
|
357
|
+
return nil;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
NSMutableArray<NSDictionary *> *resultArray = [NSMutableArray array];
|
|
361
|
+
NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector];
|
|
362
|
+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
|
363
|
+
[invocation setSelector:selector];
|
|
364
|
+
[invocation setArgument:&auditTypes atIndex:2];
|
|
365
|
+
BOOL (^issueHandler)(id) = ^BOOL(id issue) {
|
|
366
|
+
NSString *auditType = @"";
|
|
367
|
+
NSDictionary *valuesToNamesMap = auditTypeValuesToNames();
|
|
368
|
+
NSNumber *auditTypeValue = [issue valueForKey:@"auditType"];
|
|
369
|
+
if (nil != auditTypeValue) {
|
|
370
|
+
auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue];
|
|
371
|
+
}
|
|
372
|
+
[resultArray addObject:@{
|
|
373
|
+
@"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"",
|
|
374
|
+
@"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"",
|
|
375
|
+
@"auditType": auditType,
|
|
376
|
+
@"element": [extractIssueProperty(issue, @"element") description] ?: @"",
|
|
377
|
+
}];
|
|
378
|
+
return YES;
|
|
379
|
+
};
|
|
380
|
+
[invocation setArgument:&issueHandler atIndex:3];
|
|
381
|
+
[invocation setArgument:&error atIndex:4];
|
|
382
|
+
[invocation invokeWithTarget:self];
|
|
383
|
+
BOOL isSuccessful;
|
|
384
|
+
[invocation getReturnValue:&isSuccessful];
|
|
385
|
+
return isSuccessful ? resultArray.copy : nil;
|
|
386
|
+
}
|
|
387
|
+
|
|
284
388
|
@end
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
[[FBRoute GET:@"/wda/batteryInfo"] respondWithTarget:self action:@selector(handleGetBatteryInfo:)],
|
|
59
59
|
#endif
|
|
60
60
|
[[FBRoute POST:@"/wda/pressButton"] respondWithTarget:self action:@selector(handlePressButtonCommand:)],
|
|
61
|
+
[[FBRoute POST:@"/wda/performAccessibilityAudit"] respondWithTarget:self action:@selector(handlePerformAccessibilityAudit:)],
|
|
61
62
|
[[FBRoute POST:@"/wda/performIoHidEvent"] respondWithTarget:self action:@selector(handlePeformIOHIDEvent:)],
|
|
62
63
|
[[FBRoute POST:@"/wda/expectNotification"] respondWithTarget:self action:@selector(handleExpectNotification:)],
|
|
63
64
|
[[FBRoute POST:@"/wda/siri/activate"] respondWithTarget:self action:@selector(handleActivateSiri:)],
|
|
@@ -544,4 +545,23 @@
|
|
|
544
545
|
}
|
|
545
546
|
#endif
|
|
546
547
|
|
|
548
|
+
+ (id<FBResponsePayload>)handlePerformAccessibilityAudit:(FBRouteRequest *)request
|
|
549
|
+
{
|
|
550
|
+
NSError *error;
|
|
551
|
+
NSArray *requestedTypes = request.arguments[@"auditTypes"];
|
|
552
|
+
NSMutableSet *typesSet = [NSMutableSet set];
|
|
553
|
+
if (nil == requestedTypes || 0 == [requestedTypes count]) {
|
|
554
|
+
[typesSet addObject:@"XCUIAccessibilityAuditTypeAll"];
|
|
555
|
+
} else {
|
|
556
|
+
[typesSet addObjectsFromArray:requestedTypes];
|
|
557
|
+
}
|
|
558
|
+
NSArray *result = [request.session.activeApplication fb_performAccessibilityAuditWithAuditTypesSet:typesSet.copy
|
|
559
|
+
error:&error];
|
|
560
|
+
if (nil == result) {
|
|
561
|
+
return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description
|
|
562
|
+
traceback:nil]);
|
|
563
|
+
}
|
|
564
|
+
return FBResponseWithObject(result);
|
|
565
|
+
}
|
|
566
|
+
|
|
547
567
|
@end
|
|
@@ -123,12 +123,16 @@ NSInteger FBTestmanagerdVersion(void)
|
|
|
123
123
|
static NSInteger testmanagerdVersion;
|
|
124
124
|
dispatch_once(&getTestmanagerdVersion, ^{
|
|
125
125
|
id<XCTestManager_ManagerInterface> proxy = [FBXCTestDaemonsProxy testRunnerProxy];
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
if ([(NSObject *)proxy respondsToSelector:@selector(_XCT_exchangeProtocolVersion:reply:)]) {
|
|
127
|
+
[FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){
|
|
128
|
+
[proxy _XCT_exchangeProtocolVersion:testmanagerdVersion reply:^(unsigned long long code) {
|
|
129
|
+
testmanagerdVersion = (NSInteger) code;
|
|
130
|
+
completion();
|
|
131
|
+
}];
|
|
132
|
+
}];
|
|
133
|
+
} else {
|
|
134
|
+
testmanagerdVersion = 0xFFFF;
|
|
135
|
+
}
|
|
132
136
|
});
|
|
133
137
|
return testmanagerdVersion;
|
|
134
138
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#import "FBApplication.h"
|
|
15
15
|
#import "FBIntegrationTestCase.h"
|
|
16
16
|
#import "FBElement.h"
|
|
17
|
+
#import "FBMacros.h"
|
|
17
18
|
#import "FBTestMacros.h"
|
|
18
19
|
#import "XCUIApplication+FBHelpers.h"
|
|
19
20
|
#import "XCUIElement+FBIsVisible.h"
|
|
@@ -94,4 +95,24 @@
|
|
|
94
95
|
XCTAssertGreaterThan(FBTestmanagerdVersion(), 0);
|
|
95
96
|
}
|
|
96
97
|
|
|
98
|
+
- (void)testAccessbilityAudit
|
|
99
|
+
{
|
|
100
|
+
if (SYSTEM_VERSION_LESS_THAN(@"17.0")) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
NSError *error;
|
|
105
|
+
NSArray *auditIssues1 = [FBApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypes:~0UL
|
|
106
|
+
error:&error];
|
|
107
|
+
XCTAssertNotNil(auditIssues1);
|
|
108
|
+
XCTAssertNil(error);
|
|
109
|
+
|
|
110
|
+
NSMutableSet *set = [NSMutableSet new];
|
|
111
|
+
[set addObject:@"XCUIAccessibilityAuditTypeAll"];
|
|
112
|
+
NSArray *auditIssues2 = [FBApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypesSet:set.copy
|
|
113
|
+
error:&error];
|
|
114
|
+
XCTAssertEqualObjects(auditIssues1, auditIssues2);
|
|
115
|
+
XCTAssertNil(error);
|
|
116
|
+
}
|
|
117
|
+
|
|
97
118
|
@end
|