Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (NSDictionary *)fb_tree;

/**
@param excludedAttributes Set of possible attributes to be excluded i.e frame, enabled, visible, accessible, focused. If set to nil or an empty array then no attributes will be excluded from the resulting JSON
@return application elements tree in form of nested dictionaries
*/
- (NSDictionary *)fb_tree:(nullable NSSet<NSString *> *) excludedAttributes;

/**
Return application elements accessibility tree in form of nested dictionaries
*/
Expand Down
53 changes: 44 additions & 9 deletions WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,16 @@ - (BOOL)fb_deactivateWithDuration:(NSTimeInterval)duration error:(NSError **)err
}

- (NSDictionary *)fb_tree
{
return [self fb_tree:nil];
}

- (NSDictionary *)fb_tree:(nullable NSSet<NSString *> *) excludedAttributes
{
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
? self.lastSnapshot
: [self fb_snapshotWithAllAttributesAndMaxDepth:nil];
return [self.class dictionaryForElement:snapshot recursive:YES];
return [self.class dictionaryForElement:snapshot recursive:YES excludedAttributes:excludedAttributes];
}

- (NSDictionary *)fb_accessibilityTree
Expand All @@ -167,7 +172,9 @@ - (NSDictionary *)fb_accessibilityTree
return [self.class accessibilityInfoForElement:snapshot];
}

+ (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot recursive:(BOOL)recursive
+ (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
recursive:(BOOL)recursive
excludedAttributes:(nullable NSSet<NSString *> *) excludedAttributes
{
NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType];
Expand All @@ -177,11 +184,35 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot recursi
info[@"value"] = FBValueOrNull(wrappedSnapshot.wdValue);
info[@"label"] = FBValueOrNull(wrappedSnapshot.wdLabel);
info[@"rect"] = wrappedSnapshot.wdRect;
info[@"frame"] = NSStringFromCGRect(wrappedSnapshot.wdFrame);
info[@"isEnabled"] = [@([wrappedSnapshot isWDEnabled]) stringValue];
info[@"isVisible"] = [@([wrappedSnapshot isWDVisible]) stringValue];
info[@"isAccessible"] = [@([wrappedSnapshot isWDAccessible]) stringValue];
info[@"isFocused"] = [@([wrappedSnapshot isWDFocused]) stringValue];

NSDictionary<NSString *, NSString * (^)(void)> *attributeBlocks = @{
@"frame": ^{
return NSStringFromCGRect(wrappedSnapshot.wdFrame);
},
@"enabled": ^{
return [@([wrappedSnapshot isWDEnabled]) stringValue];
},
@"visible": ^{
return [@([wrappedSnapshot isWDVisible]) stringValue];
},
@"accessible": ^{
return [@([wrappedSnapshot isWDAccessible]) stringValue];
},
@"focused": ^{
return [@([wrappedSnapshot isWDFocused]) stringValue];
}
};

for (NSString *key in attributeBlocks) {
if (excludedAttributes == nil || ![excludedAttributes containsObject:key]) {
NSString *value = ((NSString * (^)(void))attributeBlocks[key])();
if ([key isEqualToString:@"frame"]) {
info[key] = value;
} else {
info[[NSString stringWithFormat:@"is%@", [key capitalizedString]]] = value;
}
}
}

if (!recursive) {
return info.copy;
Expand All @@ -191,7 +222,9 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot recursi
if ([childElements count]) {
info[@"children"] = [[NSMutableArray alloc] init];
for (id<FBXCElementSnapshot> childSnapshot in childElements) {
[info[@"children"] addObject:[self dictionaryForElement:childSnapshot recursive:YES]];
[info[@"children"] addObject:[self dictionaryForElement:childSnapshot
recursive:YES
excludedAttributes:excludedAttributes]];
}
}
return info;
Expand Down Expand Up @@ -379,7 +412,9 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray<NSString *> *)keyNames
id extractedElement = extractIssueProperty(issue, @"element");

id<FBXCElementSnapshot> elementSnapshot = [extractedElement fb_takeSnapshot];
NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO] : @{};
NSDictionary *elementAttributes = elementSnapshot
? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:nil]
: @{};

[resultArray addObject:@{
@"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"",
Expand Down
7 changes: 6 additions & 1 deletion WebDriverAgentLib/Commands/FBDebugCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ + (NSArray *)routes
withExcludedAttributes:excludedAttributes]
withScope:sourceScope]];
} else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_JSON] == NSOrderedSame) {
result = application.fb_tree;
NSString *excludedAttributesString = request.parameters[@"excluded_attributes"];
NSSet<NSString *> *excludedAttributes = (excludedAttributesString == nil)
? nil
: [NSSet setWithArray:[excludedAttributesString componentsSeparatedByString:@","]];

result = [application fb_tree:excludedAttributes];
} else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_DESCRIPTION] == NSOrderedSame) {
result = application.fb_descriptionRepresentation;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ - (void)testApplicationTree
XCTAssertNotNil(self.testedApplication.fb_accessibilityTree);
}

- (void)testApplicationTreeAttributesFiltering
{
NSDictionary *applicationTree = [self.testedApplication fb_tree:[NSSet setWithArray:@[@"visible"]]];
XCTAssertNotNil(applicationTree);
XCTAssertNil([applicationTree objectForKey:@"isVisible"], @"'isVisible' key should not be present in the application tree");
}

- (void)testDeactivateApplication
{
NSError *error;
Expand Down