diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 2e08880f1..4c9d8fc31 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -325,6 +325,8 @@ EEEA70152110605600C8ADE2 /* XCTAutomationSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE8980D321105B49001789ED /* XCTAutomationSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; EEEC7C921F21F27A0053426C /* FBPredicate.h in Headers */ = {isa = PBXBuildFile; fileRef = EEEC7C901F21F27A0053426C /* FBPredicate.h */; }; EEEC7C931F21F27A0053426C /* FBPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEEC7C911F21F27A0053426C /* FBPredicate.m */; }; + F529DF15223A080D00558D4B /* FBPrivateCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = F529DF13223A080D00558D4B /* FBPrivateCommands.m */; }; + F529DF16223A080D00558D4B /* FBPrivateCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = F529DF14223A080D00558D4B /* FBPrivateCommands.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -745,6 +747,8 @@ EEEC7C901F21F27A0053426C /* FBPredicate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBPredicate.h; sourceTree = ""; }; EEEC7C911F21F27A0053426C /* FBPredicate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBPredicate.m; sourceTree = ""; }; EEF9882A1C486603005CA669 /* WebDriverAgentRunner.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebDriverAgentRunner.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + F529DF13223A080D00558D4B /* FBPrivateCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBPrivateCommands.m; sourceTree = ""; }; + F529DF14223A080D00558D4B /* FBPrivateCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBPrivateCommands.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -959,6 +963,8 @@ EE9AB74F1CAEDF0C008C271F /* Commands */ = { isa = PBXGroup; children = ( + F529DF14223A080D00558D4B /* FBPrivateCommands.h */, + F529DF13223A080D00558D4B /* FBPrivateCommands.m */, EE9AB7501CAEDF0C008C271F /* FBAlertViewCommands.h */, EE9AB7511CAEDF0C008C271F /* FBAlertViewCommands.m */, EE9AB7521CAEDF0C008C271F /* FBCustomCommands.h */, @@ -1433,6 +1439,7 @@ EE158AD21CBD456F00A3E3F0 /* FBElementCache.h in Headers */, EE35AD5A1E3B77D600A02D78 /* XCTMetric.h in Headers */, EE35AD461E3B77D600A02D78 /* XCTestContextScope.h in Headers */, + F529DF16223A080D00558D4B /* FBPrivateCommands.h in Headers */, 71A7EAF51E20516B001DA4F2 /* XCUIElement+FBClassChain.h in Headers */, EE158ADA1CBD456F00A3E3F0 /* FBResponseJSONPayload.h in Headers */, EE35AD3D1E3B77D600A02D78 /* XCTAutomationTarget-Protocol.h in Headers */, @@ -1817,6 +1824,7 @@ EE158ACD1CBD456F00A3E3F0 /* FBUnknownCommands.m in Sources */, EE158AC51CBD456F00A3E3F0 /* FBOrientationCommands.m in Sources */, EEC9EED720064FAA00BC0D5B /* XCUICoordinate+FBFix.m in Sources */, + F529DF15223A080D00558D4B /* FBPrivateCommands.m in Sources */, EE158AEB1CBD456F00A3E3F0 /* FBRuntimeUtils.m in Sources */, EEE376461D59F81400ED88DD /* XCUIElement+FBUtilities.m in Sources */, EE9B76A91CF7A43900275851 /* FBLogger.m in Sources */, diff --git a/WebDriverAgentLib/Commands/FBPrivateCommands.h b/WebDriverAgentLib/Commands/FBPrivateCommands.h new file mode 100755 index 000000000..c9a56c485 --- /dev/null +++ b/WebDriverAgentLib/Commands/FBPrivateCommands.h @@ -0,0 +1,20 @@ +/** + * 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. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXPrivateCommands : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Commands/FBPrivateCommands.m b/WebDriverAgentLib/Commands/FBPrivateCommands.m new file mode 100755 index 000000000..cca79632d --- /dev/null +++ b/WebDriverAgentLib/Commands/FBPrivateCommands.m @@ -0,0 +1,119 @@ +/** + * 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. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "FBPrivateCommands.h" + +#import "FBApplication.h" +#import "FBKeyboard.h" +#import "FBPredicate.h" +#import "FBRoute.h" +#import "FBRouteRequest.h" +#import "FBRunLoopSpinner.h" +#import "FBElementCache.h" +#import "FBErrorBuilder.h" +#import "FBSession.h" +#import "FBApplication.h" +#import "FBMacros.h" +#import "FBMathUtils.h" +#import "FBRuntimeUtils.h" +#import "NSPredicate+FBFormat.h" +#import "XCUICoordinate.h" +#import "XCUIDevice.h" +#import "XCUIElement+FBIsVisible.h" +#import "XCUIElement+FBPickerWheel.h" +#import "XCUIElement+FBScrolling.h" +#import "XCUIElement+FBTap.h" +#import "XCUIElement+FBTyping.h" +#import "XCUIElement+FBUtilities.h" +#import "XCUIElement+FBWebDriverAttributes.h" +#import "FBElementTypeTransformer.h" +#import "XCUIElement.h" +#import "XCUIElementQuery.h" +#import "XCEventGenerator.h" + +@implementation QXPrivateCommands ++ (NSArray *)routes{ + return + @[ + [[FBRoute POST:@"/private/tap"] respondWithTarget:self action:@selector(handlePrivateTap:)], + [[FBRoute POST:@"/private/swipe"] respondWithTarget:self action:@selector(handlePrivateSwipe:)], + [[FBRoute POST:@"/private/pinch"] respondWithTarget:self action:@selector(handlePrivatePinch:)], + [[FBRoute POST:@"/private/touchAndHold"] respondWithTarget:self action:@selector(handlePrivateTouchAndHold:)], + ]; +} + +#pragma mark - Commands + ++ (id)handlePrivateTap:(FBRouteRequest *)request { + FBApplication *application = request.session.application; + CGPoint tapPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); + if (isSDKVersionLessThan(@"11.0")) { + tapPoint = FBInvertPointForApplication(tapPoint, application.frame.size, application.interfaceOrientation); + } + XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:application normalizedOffset:CGVectorMake(0, 0)]; + tapPoint = [[XCUICoordinate alloc] initWithCoordinate:appCoordinate pointsOffset:CGVectorMake(tapPoint.x, tapPoint.y)].screenPoint; + dispatch_semaphore_t t = dispatch_semaphore_create(0); + [[XCEventGenerator sharedGenerator] pressAtPoint:tapPoint forDuration:0 orientation:application.interfaceOrientation handler:^(XCSynthesizedEventRecord *record, NSError *error) { + dispatch_semaphore_signal(t); + }]; + dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER); + return FBResponseWithOK(); +} + + ++ (id)handlePrivateSwipe:(FBRouteRequest *)request{ + FBApplication *application = request.session.application; + CGPoint fromPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); + CGPoint toPoint = CGPointMake((CGFloat)[request.arguments[@"x1"] doubleValue], (CGFloat)[request.arguments[@"y1"] doubleValue]); + if (isSDKVersionLessThan(@"11.0")) { + fromPoint = FBInvertPointForApplication(fromPoint, application.frame.size, application.interfaceOrientation); + toPoint = FBInvertPointForApplication(toPoint, application.frame.size, application.interfaceOrientation); + } + XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:application normalizedOffset:CGVectorMake(0, 0)]; + fromPoint = [[XCUICoordinate alloc] initWithCoordinate:appCoordinate pointsOffset:CGVectorMake(fromPoint.x, fromPoint.y)].screenPoint; + toPoint = [[XCUICoordinate alloc] initWithCoordinate:appCoordinate pointsOffset:CGVectorMake(toPoint.x, toPoint.y)].screenPoint; + + dispatch_semaphore_t t = dispatch_semaphore_create(0); + [[XCEventGenerator sharedGenerator] pressAtPoint:fromPoint forDuration:[request.arguments[@"duration"] doubleValue] liftAtPoint:toPoint velocity:1000 orientation:application.interfaceOrientation name:@"MonkeySwipe" handler:^(XCSynthesizedEventRecord *record, NSError *error) { + dispatch_semaphore_signal(t); + }]; + dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER); + return FBResponseWithOK(); +} + + ++ (id)handlePrivatePinch:(FBRouteRequest *)request{ + FBApplication *application = request.session.application; + CGRect rect = CGRectMake((CGFloat)[request.arguments[@"x"] doubleValue], + (CGFloat)[request.arguments[@"y"] doubleValue], + (CGFloat)[request.arguments[@"width"] doubleValue], + (CGFloat)[request.arguments[@"height"] doubleValue]); + + dispatch_semaphore_t t = dispatch_semaphore_create(0); + [[XCEventGenerator sharedGenerator] pinchInRect:rect withScale:[request.arguments[@"scale"] doubleValue] velocity:1000 orientation:application.interfaceOrientation handler:^(XCSynthesizedEventRecord *record, NSError *error) { + dispatch_semaphore_signal(t); + }]; + dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER); + return FBResponseWithOK(); +} + + ++ (id)handlePrivateTouchAndHold:(FBRouteRequest *)request{ + FBApplication *application = request.session.application; + CGPoint tapPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); + + dispatch_semaphore_t t = dispatch_semaphore_create(0); + [[XCEventGenerator sharedGenerator] pressAtPoint:tapPoint forDuration:[request.arguments[@"duration"] doubleValue] orientation:application.interfaceOrientation handler:^(XCSynthesizedEventRecord *record, NSError *error) { + dispatch_semaphore_signal(t); + }]; + dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER); + return FBResponseWithOK(); +} + +@end