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
1 change: 1 addition & 0 deletions Inspector/js/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class Inspector extends React.Component {
{this.renderField('Rect', attributes.rect)}
{this.renderField('isEnabled', boolToString(attributes.isEnabled))}
{this.renderField('isVisible', boolToString(attributes.isVisible))}
{this.renderField('isFocused', typeof attributes.isFocused === 'undefined' ? null : boolToString(attributes.isFocused))}
{this.renderField('Tap', tapButton, false)}
</div>
);
Expand Down
1 change: 1 addition & 0 deletions Inspector/js/tree_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class TreeNode {
rect: node.frame,
isEnabled: node.isEnabled,
isVisible: node.isVisible,
isFocused: node.isFocused,
};
}
}
Expand Down
12 changes: 0 additions & 12 deletions WebDriverAgent.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,6 @@
641EE6F02240C5CA00173FCB /* WebDriverAgent.bundle in Resources */ = {isa = PBXBuildFile; fileRef = EEDBEBBA1CB2681900A790A2 /* WebDriverAgent.bundle */; };
641EE6FC2240C5FD00173FCB /* WebDriverAgentLib_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 641EE6F82240C5CA00173FCB /* WebDriverAgentLib_tvOS.framework */; };
641EE6FD2240C61D00173FCB /* WebDriverAgentLib_tvOS.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 641EE6F82240C5CA00173FCB /* WebDriverAgentLib_tvOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
641EE6FF2240CD4900173FCB /* XCUIApplication+FBFocused.h in Headers */ = {isa = PBXBuildFile; fileRef = 641EE6FE2240CD4900173FCB /* XCUIApplication+FBFocused.h */; };
641EE7002240CD4900173FCB /* XCUIApplication+FBFocused.h in Headers */ = {isa = PBXBuildFile; fileRef = 641EE6FE2240CD4900173FCB /* XCUIApplication+FBFocused.h */; };
641EE7022240CDA200173FCB /* XCUIApplication+FBFocused.m in Sources */ = {isa = PBXBuildFile; fileRef = 641EE7012240CDA200173FCB /* XCUIApplication+FBFocused.m */; };
641EE7032240CDA200173FCB /* XCUIApplication+FBFocused.m in Sources */ = {isa = PBXBuildFile; fileRef = 641EE7012240CDA200173FCB /* XCUIApplication+FBFocused.m */; };
641EE7052240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */ = {isa = PBXBuildFile; fileRef = 641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */; };
641EE7062240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */ = {isa = PBXBuildFile; fileRef = 641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */; };
641EE7082240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */ = {isa = PBXBuildFile; fileRef = 641EE7072240CDEB00173FCB /* XCUIElement+FBTVFocuse.m */; };
Expand Down Expand Up @@ -806,8 +802,6 @@
641EE2DA2240BBE300173FCB /* WebDriverAgentRunner_tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebDriverAgentRunner_tvOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
641EE6F82240C5CA00173FCB /* WebDriverAgentLib_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WebDriverAgentLib_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
641EE6F92240C5CB00173FCB /* WebDriverAgentLib copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "WebDriverAgentLib copy-Info.plist"; path = "/Users/kazu/GitHub/WebDriverAgent/WebDriverAgentLib copy-Info.plist"; sourceTree = "<absolute>"; };
641EE6FE2240CD4900173FCB /* XCUIApplication+FBFocused.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBFocused.h"; sourceTree = "<group>"; };
641EE7012240CDA200173FCB /* XCUIApplication+FBFocused.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIApplication+FBFocused.m"; sourceTree = "<group>"; };
641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBTVFocuse.h"; sourceTree = "<group>"; };
641EE7072240CDEB00173FCB /* XCUIElement+FBTVFocuse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBTVFocuse.m"; sourceTree = "<group>"; };
641EE70A2240CE2D00173FCB /* FBTVNavigationTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBTVNavigationTracker.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1386,8 +1380,6 @@
AD6C269B1CF2494200F8B5FF /* XCUIApplication+FBHelpers.m */,
EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */,
EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */,
641EE6FE2240CD4900173FCB /* XCUIApplication+FBFocused.h */,
641EE7012240CDA200173FCB /* XCUIApplication+FBFocused.m */,
719CD8FA2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h */,
719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */,
71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */,
Expand Down Expand Up @@ -1933,7 +1925,6 @@
641EE6782240C5CA00173FCB /* XCTNSNotificationExpectation.h in Headers */,
641EE6792240C5CA00173FCB /* XCUIRecorderNodeFinder.h in Headers */,
641EE67A2240C5CA00173FCB /* XCUIElement+FBAccessibility.h in Headers */,
641EE7002240CD4900173FCB /* XCUIApplication+FBFocused.h in Headers */,
641EE67B2240C5CA00173FCB /* XCUIRecorderUtilities.h in Headers */,
641EE67C2240C5CA00173FCB /* XCTestCaseRun.h in Headers */,
641EE67D2240C5CA00173FCB /* XCTestConfiguration.h in Headers */,
Expand Down Expand Up @@ -2133,7 +2124,6 @@
EE35AD5B1E3B77D600A02D78 /* XCTNSNotificationExpectation.h in Headers */,
EE35AD751E3B77D600A02D78 /* XCUIRecorderNodeFinder.h in Headers */,
EE158AAE1CBD456F00A3E3F0 /* XCUIElement+FBAccessibility.h in Headers */,
641EE6FF2240CD4900173FCB /* XCUIApplication+FBFocused.h in Headers */,
EE35AD781E3B77D600A02D78 /* XCUIRecorderUtilities.h in Headers */,
EE35AD421E3B77D600A02D78 /* XCTestCaseRun.h in Headers */,
EE35AD441E3B77D600A02D78 /* XCTestConfiguration.h in Headers */,
Expand Down Expand Up @@ -2571,7 +2561,6 @@
641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */,
641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */,
641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */,
641EE7032240CDA200173FCB /* XCUIApplication+FBFocused.m in Sources */,
641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */,
641EE5DD2240C5CA00173FCB /* FBAppiumActionsSynthesizer.m in Sources */,
641EE70F2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
Expand Down Expand Up @@ -2662,7 +2651,6 @@
7136A47A1E8918E60024FC3D /* XCUIElement+FBPickerWheel.m in Sources */,
6385F4A7220A40760095BBDB /* XCUIApplicationProcessDelay.m in Sources */,
711084451DA3AA7500F913D6 /* FBXPath.m in Sources */,
641EE7022240CDA200173FCB /* XCUIApplication+FBFocused.m in Sources */,
719CD8FD2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m in Sources */,
71241D781FAE31F100B9559F /* FBAppiumActionsSynthesizer.m in Sources */,
641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
Expand Down
21 changes: 0 additions & 21 deletions WebDriverAgentLib/Categories/XCUIApplication+FBFocused.m

This file was deleted.

7 changes: 7 additions & 0 deletions WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (nullable XCUIElement *)fb_activeElement;

#if TARGET_OS_TV
/**
Returns the element, which currently focused.
*/
- (nullable XCUIElement *)fb_focusedElement;
#endif

@end

NS_ASSUME_NONNULL_END
11 changes: 11 additions & 0 deletions WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ + (NSDictionary *)dictionaryForElement:(XCElementSnapshot *)snapshot recursive:(
info[@"frame"] = NSStringFromCGRect(snapshot.wdFrame);
info[@"isEnabled"] = [@([snapshot isWDEnabled]) stringValue];
info[@"isVisible"] = [@([snapshot isWDVisible]) stringValue];
#if TARGET_OS_TV
info[@"isFocused"] = [@([snapshot isWDFocused]) stringValue];
#endif

if (!recursive) {
return info.copy;
Expand Down Expand Up @@ -165,4 +167,13 @@ - (XCUIElement *)fb_activeElement
fb_firstMatch];
}

#if TARGET_OS_TV
- (XCUIElement *)fb_focusedElement
{
return [[[self descendantsMatchingType:XCUIElementTypeAny]
matchingPredicate:[NSPredicate predicateWithFormat:@"hasFocus == true"]]
fb_firstMatch];
}
#endif

@end
3 changes: 2 additions & 1 deletion WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ @implementation XCUIElement (FBTVFocuse)

- (BOOL)fb_setFocusWithError:(NSError**) error
{
[[FBApplication fb_activeApplication] fb_waitUntilSnapshotIsStable];
[FBApplication.fb_activeApplication fb_waitUntilSnapshotIsStable];

if (!self.wdEnabled) {
if (error) {
Expand All @@ -36,6 +36,7 @@ - (BOOL)fb_setFocusWithError:(NSError**) error

FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:self];
for (int i = 0; i < MAX_ITERATIONS_COUNT; i++) {
// Here hasFocus works so far. Maybe, it is because it is handled by `XCUIRemote`...
if (self.hasFocus) {
return YES;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ - (BOOL)isWDVisible
return [[self fb_cachedValueWithAttributeName:@"isWDVisible" valueGetter:getter] boolValue];
}

#if TARGET_OS_TV
- (BOOL)isWDFocused
{
id (^getter)(void) = ^id(void) {
Expand All @@ -199,6 +200,7 @@ - (BOOL)isWDFocused

return [[self fb_cachedValueWithAttributeName:@"hasFocus" valueGetter:getter] boolValue];
}
#endif

- (BOOL)isWDAccessible
{
Expand Down
16 changes: 14 additions & 2 deletions WebDriverAgentLib/Commands/FBCustomCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ + (NSArray *)routes

+ (id<FBResponsePayload>)handleDismissKeyboardCommand:(FBRouteRequest *)request
{
#if TARGET_OS_TV
if ([self isKeyboardPresent]) {
[[XCUIRemote sharedRemote] pressButton: XCUIRemoteButtonMenu];
}
#else
[request.session.activeApplication dismissKeyboard];
#endif
NSError *error;
NSString *errorDescription = @"The keyboard cannot be dismissed. Try to dismiss it in the way supported by your application under test.";
if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
Expand All @@ -100,8 +106,7 @@ + (NSArray *)routes
timeout:5]
timeoutErrorMessage:errorDescription]
spinUntilTrue:^BOOL{
XCUIElement *foundKeyboard = [request.session.activeApplication descendantsMatchingType:XCUIElementTypeKeyboard].fb_firstMatch;
return !(foundKeyboard && foundKeyboard.fb_isVisible);
return ![self isKeyboardPresent];
}
error:&error];
if (!isKeyboardNotPresent) {
Expand All @@ -110,6 +115,13 @@ + (NSArray *)routes
return FBResponseWithOK();
}

#pragma mark - Helpers

+ (BOOL)isKeyboardPresent {
XCUIElement *foundKeyboard = [[FBApplication fb_activeApplication].query descendantsMatchingType:XCUIElementTypeKeyboard].fb_firstMatch;
return foundKeyboard && foundKeyboard.fb_isVisible;
}

+ (id<FBResponsePayload>)handleGetScreen:(FBRouteRequest *)request
{
FBSession *session = request.session;
Expand Down
95 changes: 66 additions & 29 deletions WebDriverAgentLib/Commands/FBElementCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ + (NSArray *)routes
[[FBRoute GET:@"/screenshot/:uuid"] respondWithTarget:self action:@selector(handleElementScreenshot:)],
[[FBRoute GET:@"/wda/element/:uuid/accessible"] respondWithTarget:self action:@selector(handleGetAccessible:)],
[[FBRoute GET:@"/wda/element/:uuid/accessibilityContainer"] respondWithTarget:self action:@selector(handleGetIsAccessibilityContainer:)],
#if !TARGET_OS_TV
#if TARGET_OS_TV
[[FBRoute GET:@"/element/:uuid/attribute/focused"] respondWithTarget:self action:@selector(handleGetFocused:)],
[[FBRoute POST:@"/wda/element/:uuid/focuse"] respondWithTarget:self action:@selector(handleFocuse:)],
#else
[[FBRoute POST:@"/wda/element/:uuid/swipe"] respondWithTarget:self action:@selector(handleSwipe:)],
[[FBRoute POST:@"/wda/element/:uuid/pinch"] respondWithTarget:self action:@selector(handlePinch:)],
[[FBRoute POST:@"/wda/element/:uuid/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTap:)],
Expand Down Expand Up @@ -193,7 +196,11 @@ + (NSArray *)routes
NSString *elementUUID = request.parameters[@"uuid"];
XCUIElement *element = [elementCache elementForUUID:elementUUID];
NSError *error = nil;
#if TARGET_OS_IOS
if (![element fb_tapWithError:&error]) {
#elif TARGET_OS_TV
if (![element fb_selectWithError:&error]) {
#endif
return FBResponseWithError(error);
}
return FBResponseWithElementUUID(elementUUID);
Expand All @@ -211,7 +218,43 @@ + (NSArray *)routes
return FBResponseWithElementUUID(elementUUID);
}

#if !TARGET_OS_TV
#if TARGET_OS_TV
+ (id<FBResponsePayload>)handleGetFocused:(FBRouteRequest *)request
{
// `BOOL isFocused = [elementCache elementForUUID:request.parameters[@"uuid"]];`
// returns wrong true/false after moving focus by key up/down, for example.
// Thus, ensure the focus compares the status with `fb_focusedElement`.
BOOL isFocused = NO;
XCUIElement *focusedElement = request.session.activeApplication.fb_focusedElement;
if (focusedElement != nil) {
FBElementCache *elementCache = request.session.elementCache;
NSString *focusedUUID = [elementCache storeElement:focusedElement];
if ([focusedUUID isEqualToString:request.parameters[@"uuid"]]) {
isFocused = YES;
}
}

return FBResponseWithStatus(FBCommandStatusNoError, isFocused ? @YES : @NO);
}

+ (id<FBResponsePayload>)handleFocuse:(FBRouteRequest *)request
{
NSString *elementUUID = request.parameters[@"uuid"];
FBElementCache *elementCache = request.session.elementCache;
XCUIElement *element = [elementCache elementForUUID:elementUUID];
NSError *error;

if (!element) {
return FBResponseWithErrorFormat(@"'%@' element uuid didn't match any elements. Try find the element again.",
elementUUID);
}

if (![element fb_setFocusWithError:&error]) {
return FBResponseWithError(error);
}
return FBResponseWithElementUUID(elementUUID);
}
#else
+ (id<FBResponsePayload>)handleDoubleTap:(FBRouteRequest *)request
{
FBElementCache *elementCache = request.session.elementCache;
Expand Down Expand Up @@ -251,29 +294,7 @@ + (NSArray *)routes
[pressCoordinate pressForDuration:[request.arguments[@"duration"] doubleValue]];
return FBResponseWithOK();
}
#endif

+ (id<FBResponsePayload>)handleForceTouch:(FBRouteRequest *)request
{
FBElementCache *elementCache = request.session.elementCache;
XCUIElement *element = [elementCache elementForUUID:request.parameters[@"uuid"]];
double pressure = [request.arguments[@"pressure"] doubleValue];
double duration = [request.arguments[@"duration"] doubleValue];
NSError *error;
if (nil != request.arguments[@"x"] && nil != request.arguments[@"y"]) {
CGPoint forceTouchPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]);
if (![element fb_forceTouchCoordinate:forceTouchPoint pressure:pressure duration:duration error:&error]) {
return FBResponseWithError(error);
}
} else {
if (![element fb_forceTouchWithPressure:pressure duration:duration error:&error]) {
return FBResponseWithError(error);
}
}
return FBResponseWithOK();
}

#if !TARGET_OS_TV
+ (id<FBResponsePayload>)handleScroll:(FBRouteRequest *)request
{
FBElementCache *elementCache = request.session.elementCache;
Expand Down Expand Up @@ -399,6 +420,26 @@ + (NSArray *)routes
}
#endif

+ (id<FBResponsePayload>)handleForceTouch:(FBRouteRequest *)request
{
FBElementCache *elementCache = request.session.elementCache;
XCUIElement *element = [elementCache elementForUUID:request.parameters[@"uuid"]];
double pressure = [request.arguments[@"pressure"] doubleValue];
double duration = [request.arguments[@"duration"] doubleValue];
NSError *error;
if (nil != request.arguments[@"x"] && nil != request.arguments[@"y"]) {
CGPoint forceTouchPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]);
if (![element fb_forceTouchCoordinate:forceTouchPoint pressure:pressure duration:duration error:&error]) {
return FBResponseWithError(error);
}
} else {
if (![element fb_forceTouchWithPressure:pressure duration:duration error:&error]) {
return FBResponseWithError(error);
}
}
return FBResponseWithOK();
}

+ (id<FBResponsePayload>)handleKeys:(FBRouteRequest *)request
{
NSString *textToType = [request.arguments[@"value"] componentsJoinedByString:@""];
Expand Down Expand Up @@ -437,9 +478,9 @@ + (NSArray *)routes
return FBResponseWithObject(screenshot);
}

static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;

#if !TARGET_OS_TV
static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;

+ (id<FBResponsePayload>)handleWheelSelect:(FBRouteRequest *)request
{
Expand Down Expand Up @@ -471,12 +512,8 @@ + (NSArray *)routes
return FBResponseWithOK();
}

#endif

#pragma mark - Helpers

#if !TARGET_OS_TV

+ (id<FBResponsePayload>)handleScrollElementToVisible:(XCUIElement *)element withRequest:(FBRouteRequest *)request
{
NSError *error;
Expand Down
12 changes: 12 additions & 0 deletions WebDriverAgentLib/Commands/FBFindElementCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ + (NSArray *)routes
[[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:@"/wda/element/focused"] respondWithTarget:self action:@selector(handleGetFocusedElement:)],
#endif
];
}

Expand Down Expand Up @@ -117,6 +120,15 @@ + (NSArray *)routes
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

Expand Down
2 changes: 2 additions & 0 deletions WebDriverAgentLib/Routing/FBElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ NS_ASSUME_NONNULL_BEGIN
/*! Whether element is an accessibility container (contains children of any depth that are accessible) */
@property (nonatomic, readonly, getter = isWDAccessibilityContainer) BOOL wdAccessibilityContainer;

#if TARGET_OS_TV
/*! Whether element is focused */
@property (nonatomic, readonly, getter = isWDFocused) BOOL wdFocused;
#endif

/**
Returns value of given property specified in WebDriver Spec
Expand Down
Loading