初始化提交
This commit is contained in:
186
WebDriverAgentLib/Commands/FBFindElementCommands.m
Normal file
186
WebDriverAgentLib/Commands/FBFindElementCommands.m
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "FBFindElementCommands.h"
|
||||
|
||||
#import "FBAlert.h"
|
||||
#import "FBConfiguration.h"
|
||||
#import "FBElementCache.h"
|
||||
#import "FBExceptions.h"
|
||||
#import "FBMacros.h"
|
||||
#import "FBRouteRequest.h"
|
||||
#import "FBSession.h"
|
||||
#import "XCTestPrivateSymbols.h"
|
||||
#import "XCUIApplication+FBHelpers.h"
|
||||
#import "XCUIElement+FBClassChain.h"
|
||||
#import "XCUIElement+FBFind.h"
|
||||
#import "XCUIElement+FBIsVisible.h"
|
||||
#import "XCUIElement+FBUID.h"
|
||||
#import "XCUIElement+FBUtilities.h"
|
||||
#import "XCUIElement+FBWebDriverAttributes.h"
|
||||
|
||||
static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteRequest *request)
|
||||
{
|
||||
return FBResponseWithStatus([FBCommandStatus noSuchElementErrorWithMessage:[NSString stringWithFormat:@"unable to find an element using '%@', value '%@'", request.arguments[@"using"], request.arguments[@"value"]]
|
||||
traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
|
||||
}
|
||||
|
||||
@implementation FBFindElementCommands
|
||||
|
||||
#pragma mark - <FBCommandHandler>
|
||||
|
||||
+ (NSArray *)routes
|
||||
{
|
||||
return
|
||||
@[
|
||||
[[FBRoute POST:@"/element"] respondWithTarget:self action:@selector(handleFindElement:)],
|
||||
[[FBRoute POST:@"/elements"] respondWithTarget:self action:@selector(handleFindElements:)],
|
||||
[[FBRoute POST:@"/element/:uuid/element"] respondWithTarget:self action:@selector(handleFindSubElement:)],
|
||||
[[FBRoute POST:@"/element/:uuid/elements"] respondWithTarget:self action:@selector(handleFindSubElements:)],
|
||||
[[FBRoute GET:@"/wda/element/:uuid/getVisibleCells"] respondWithTarget:self action:@selector(handleFindVisibleCells:)],
|
||||
#if TARGET_OS_TV
|
||||
[[FBRoute GET:@"/element/active"] respondWithTarget:self action:@selector(handleGetFocusedElement:)],
|
||||
#else
|
||||
[[FBRoute GET:@"/element/active"] respondWithTarget:self action:@selector(handleGetActiveElement:)],
|
||||
#endif
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Commands
|
||||
|
||||
+ (id<FBResponsePayload>)handleFindElement:(FBRouteRequest *)request
|
||||
{
|
||||
FBSession *session = request.session;
|
||||
XCUIElement *element = [self.class elementUsing:request.arguments[@"using"]
|
||||
withValue:request.arguments[@"value"]
|
||||
under:session.activeApplication];
|
||||
if (!element) {
|
||||
return FBNoSuchElementErrorResponseForRequest(request);
|
||||
}
|
||||
return FBResponseWithCachedElement(element, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)handleFindElements:(FBRouteRequest *)request
|
||||
{
|
||||
FBSession *session = request.session;
|
||||
NSArray *elements = [self.class elementsUsing:request.arguments[@"using"]
|
||||
withValue:request.arguments[@"value"]
|
||||
under:session.activeApplication
|
||||
shouldReturnAfterFirstMatch:NO];
|
||||
return FBResponseWithCachedElements(elements, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)handleFindVisibleCells:(FBRouteRequest *)request
|
||||
{
|
||||
FBElementCache *elementCache = request.session.elementCache;
|
||||
XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
|
||||
id<FBXCElementSnapshot> snapshot = [element fb_customSnapshot];
|
||||
NSArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [snapshot descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> shot) {
|
||||
return shot.elementType == XCUIElementTypeCell
|
||||
&& [FBXCElementSnapshotWrapper ensureWrapped:shot].wdVisible;
|
||||
}];
|
||||
NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots
|
||||
onlyChildren:NO];
|
||||
return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)handleFindSubElement:(FBRouteRequest *)request
|
||||
{
|
||||
FBElementCache *elementCache = request.session.elementCache;
|
||||
XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
|
||||
checkStaleness:NO];
|
||||
XCUIElement *foundElement = [self.class elementUsing:request.arguments[@"using"]
|
||||
withValue:request.arguments[@"value"]
|
||||
under:element];
|
||||
if (!foundElement) {
|
||||
return FBNoSuchElementErrorResponseForRequest(request);
|
||||
}
|
||||
return FBResponseWithCachedElement(foundElement, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)handleFindSubElements:(FBRouteRequest *)request
|
||||
{
|
||||
FBElementCache *elementCache = request.session.elementCache;
|
||||
XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
|
||||
checkStaleness:NO];
|
||||
NSArray *foundElements = [self.class elementsUsing:request.arguments[@"using"]
|
||||
withValue:request.arguments[@"value"]
|
||||
under:element
|
||||
shouldReturnAfterFirstMatch:NO];
|
||||
return FBResponseWithCachedElements(foundElements, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)handleGetActiveElement:(FBRouteRequest *)request
|
||||
{
|
||||
XCUIElement *element = request.session.activeApplication.fb_activeElement;
|
||||
if (nil == element) {
|
||||
return FBNoSuchElementErrorResponseForRequest(request);
|
||||
}
|
||||
return FBResponseWithCachedElement(element, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV
|
||||
+ (id<FBResponsePayload>)handleGetFocusedElement:(FBRouteRequest *)request
|
||||
{
|
||||
XCUIElement *element = request.session.activeApplication.fb_focusedElement;
|
||||
return element == nil
|
||||
? FBNoSuchElementErrorResponseForRequest(request)
|
||||
: FBResponseWithCachedElement(element, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
+ (XCUIElement *)elementUsing:(NSString *)usingText withValue:(NSString *)value under:(XCUIElement *)element
|
||||
{
|
||||
return [[self elementsUsing:usingText
|
||||
withValue:value
|
||||
under:element
|
||||
shouldReturnAfterFirstMatch:YES] firstObject];
|
||||
}
|
||||
|
||||
+ (NSArray *)elementsUsing:(NSString *)usingText
|
||||
withValue:(NSString *)value
|
||||
under:(XCUIElement *)element
|
||||
shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
|
||||
{
|
||||
if ([usingText isEqualToString:@"partial link text"]
|
||||
|| [usingText isEqualToString:@"link text"]) {
|
||||
NSArray *components = [value componentsSeparatedByString:@"="];
|
||||
NSString *propertyValue = components.lastObject;
|
||||
NSString *propertyName = (components.count < 2 ? @"name" : components.firstObject);
|
||||
return [element fb_descendantsMatchingProperty:propertyName
|
||||
value:propertyValue
|
||||
partialSearch:[usingText containsString:@"partial"]];
|
||||
} else if ([usingText isEqualToString:@"class name"]) {
|
||||
return [element fb_descendantsMatchingClassName:value
|
||||
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
||||
} else if ([usingText isEqualToString:@"class chain"]) {
|
||||
return [element fb_descendantsMatchingClassChain:value
|
||||
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
||||
} else if ([usingText isEqualToString:@"xpath"]) {
|
||||
return [element fb_descendantsMatchingXPathQuery:value
|
||||
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
||||
} else if ([usingText isEqualToString:@"predicate string"]) {
|
||||
return [element fb_descendantsMatchingPredicate:[NSPredicate predicateWithFormat:value]
|
||||
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
||||
} else if ([usingText isEqualToString:@"name"]
|
||||
|| [usingText isEqualToString:@"id"]
|
||||
|| [usingText isEqualToString:@"accessibility id"]) {
|
||||
return [element fb_descendantsMatchingIdentifier:value
|
||||
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
||||
} else {
|
||||
@throw [NSException exceptionWithName:FBElementAttributeUnknownException
|
||||
reason:[NSString stringWithFormat:@"Invalid locator requested: %@", usingText]
|
||||
userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user