diff --git a/app/android.js b/app/android.js index 4763cbc0b..48cef30ac 100644 --- a/app/android.js +++ b/app/android.js @@ -792,6 +792,10 @@ Android.prototype.swipe = function(startX, startY, endX, endY, duration, touchCo } }; +Android.prototype.rotate = function(x, y, radius, rotation, duration, touchCount, elId, cb) { + cb(new NotYetImplementedError(), null); +}; + Android.prototype.flick = function(startX, startY, endX, endY, touchCount, elId, cb) { if (startX === 'null') { startX = 0.5; diff --git a/app/controller.js b/app/controller.js index ae5ed5589..4179196b2 100644 --- a/app/controller.js +++ b/app/controller.js @@ -470,6 +470,30 @@ exports.mobileSwipe = function(req, res) { } }; +exports.mobileRotation = function(req, res) { + req.body = _.defaults(req.body, { + x: 0.5 + , y: 0.5 + , radius: 0.5 + , rotation: 3.14159265359 + , touchCount: 2 + , duration: 1 + , element: null + }); + var element = req.body.element + , duration = req.body.duration + , x = req.body.x + , y = req.body.y + , radius = req.body.radius + , touchCount = req.body.touchCount + , rotation = req.body.rotation; + + if(checkMissingParams(res, {x: x, y: y})) { + req.device.rotate(x, y, radius, rotation, duration, touchCount, + element, getResponseHandler(req, res)); + } +}; + exports.mobileScrollTo = function(req, res) { req.body = _.defaults(req.body, { element: null @@ -968,7 +992,9 @@ var mobileCmdMap = { , 'isAppInstalled': exports.isAppInstalled , 'launchApp': exports.launchApp , 'closeApp': exports.closeApp + , 'rotate': exports.mobileRotation , 'longClick' : exports.touchLongClick + , 'touchLongClick': exports.touchLongClick }; exports.produceError = function(req, res) { diff --git a/app/ios.js b/app/ios.js index 82bb58dc3..2d8f2eb95 100644 --- a/app/ios.js +++ b/app/ios.js @@ -1517,6 +1517,18 @@ IOS.prototype.swipe = function(startX, startY, endX, endY, duration, touchCount, }); }; +IOS.prototype.rotate = function(x, y, radius, rotation, duration, touchCount, elId, cb) { + var command; + var location = {'x' : x, 'y' : y}; + var options = {'duration' : duration, 'radius' : radius, 'rotation' : rotation, 'touchCount' : touchCount}; + if (elId) { + command = ["au.getElement('", elId, "').rotateWithOptions("+ JSON.stringify(location) + "," + JSON.stringify(options) + ")"]; + this.proxy(command, cb); + } else { + this.proxy("target.rotateWithOptions("+ JSON.stringify(location) + "," + JSON.stringify(options) + ")", cb); + } +}; + IOS.prototype.flick = function(startX, startY, endX, endY, touchCount, elId, cb) { var command; if (elId) { diff --git a/sample-code/apps/RobotCalibration/RobotCalibration.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sample-code/apps/RobotCalibration/RobotCalibration.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..f51919ac6 --- /dev/null +++ b/sample-code/apps/RobotCalibration/RobotCalibration.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/sample-code/apps/TestApp/Test App 2/GestureTestViewController.h b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.h new file mode 100644 index 000000000..4f42a3efc --- /dev/null +++ b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.h @@ -0,0 +1,18 @@ +// +// GestureTestViewController.h +// TestApp +// +// Created by ThinkSys- Amit on 12/07/13. +// +// + +#import +#import + +@interface GestureTestViewController : UIViewController +@property (retain, nonatomic) IBOutlet MKMapView *mapView; + + +- (IBAction)handleRotation:(UIRotationGestureRecognizer*)sender; + +@end diff --git a/sample-code/apps/TestApp/Test App 2/GestureTestViewController.m b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.m new file mode 100644 index 000000000..dd7d314a4 --- /dev/null +++ b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.m @@ -0,0 +1,48 @@ +// +// GestureTestViewController.m +// TestApp +// +// Created by ThinkSys- Amit on 12/07/13. +// +// + +#import "GestureTestViewController.h" + +@interface GestureTestViewController () + +@end + +@implementation GestureTestViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (IBAction)handleRotation:(UIRotationGestureRecognizer*)sender +{ + NSLog(@"Rotation Starts"); + sender.view.transform = CGAffineTransformRotate(sender.view.transform, sender.rotation); + sender.rotation = 0; +} +- (void)dealloc { + [_mapView release]; + [super dealloc]; +} +@end diff --git a/sample-code/apps/TestApp/Test App 2/GestureTestViewController.xib b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.xib new file mode 100644 index 000000000..f5d38a083 --- /dev/null +++ b/sample-code/apps/TestApp/Test App 2/GestureTestViewController.xib @@ -0,0 +1,334 @@ + + + + 1552 + 11G63b + 3084 + 1138.51 + 569.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 2083 + + + IBMKMapView + IBNSLayoutConstraint + IBProxyObject + IBUIRotationGestureRecognizer + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 274 + {{35, 83}, {250, 250}} + + + _NS:9 + YES + YES + + IBCocoaTouchFramework + YES + + + {{0, 20}, {320, 548}} + + + + + 3 + MQA + + 2 + + + + + IBUIScreenMetrics + + YES + + + + + + {320, 568} + {568, 320} + + + IBCocoaTouchFramework + Retina 4 Full Screen + 2 + + IBCocoaTouchFramework + + + + + + + + view + + + + 3 + + + + mapView + + + + 24 + + + + gestureRecognizers + + + NSArray + YES + + 15 + + + + handleRotation: + + + + 16 + + + + delegate + + + + 25 + + + + + + 0 + + + + + + 1 + + + + + 9 + 0 + + 9 + 1 + + 0.0 + + 1000 + + 5 + 22 + 2 + + + + 3 + 0 + + 3 + 1 + + 83 + + 1000 + + 3 + 9 + 3 + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + 8 + 0 + + 0 + 1 + + 250 + + 1000 + + 3 + 9 + 1 + + + + 7 + 0 + + 0 + 1 + + 250 + + 1000 + + 3 + 9 + 1 + + + + + + 14 + + + + + 18 + + + + + 20 + + + + + 22 + + + + + 23 + + + + + + + GestureTestViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + + + + + + 25 + + + + + GestureTestViewController + UIViewController + + handleRotation: + UIRotationGestureRecognizer + + + handleRotation: + + handleRotation: + UIRotationGestureRecognizer + + + + mapView + MKMapView + + + mapView + + mapView + MKMapView + + + + IBProjectSource + ./Classes/GestureTestViewController.h + + + + NSLayoutConstraint + NSObject + + IBProjectSource + ./Classes/NSLayoutConstraint.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + YES + 2083 + + diff --git a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.h b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.h index 861ae5892..71c22b5ec 100644 --- a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.h +++ b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.h @@ -20,12 +20,14 @@ */ #import +#import "GestureTestViewController.h" @interface MyViewControllerViewController : UIViewController @property (retain, nonatomic) IBOutlet UITextField *firstArg; @property (retain, nonatomic) IBOutlet UITextField *secondArg; @property (retain, nonatomic) IBOutlet UILabel *answerLabel; @property (retain, nonatomic) IBOutlet UIButton *computeSumButton; +- (IBAction)testGesture:(id)sender; - (IBAction)computeAction:(id)sender; - (IBAction)showAlert:(id)sender; diff --git a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.m b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.m index 9fe58f042..ad752ec4d 100644 --- a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.m +++ b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.m @@ -81,6 +81,12 @@ [computeSumButton release]; [super dealloc]; } +- (IBAction)testGesture:(id)sender +{ + GestureTestViewController *test = [[GestureTestViewController alloc] initWithNibName:@"GestureTestViewController" bundle:nil]; + [self presentViewController:test animated:YES completion:NULL]; +} + - (IBAction)computeAction:(id)sender { int a = [[firstArg text] intValue]; int b = [[secondArg text] intValue]; diff --git a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.xib b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.xib index 16c3db388..80fc415d7 100644 --- a/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.xib +++ b/sample-code/apps/TestApp/Test App 2/MyViewControllerViewController.xib @@ -2,10 +2,10 @@ 1552 - 12D78 + 11G63b 3084 - 1187.37 - 626.00 + 1138.51 + 569.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 2083 @@ -43,7 +43,6 @@ 292 {{94, 122}, {113, 37}} - _NS:9 NO @@ -82,7 +81,6 @@ 292 {{102, 38}, {97, 31}} - _NS:9 NO @@ -121,7 +119,6 @@ 292 {{102, 77}, {97, 31}} - _NS:9 NO @@ -151,7 +148,6 @@ 292 {{129, 167}, {42, 21}} - _NS:9 NO @@ -186,7 +182,6 @@ 292 {{94, 208}, {113, 44}} - _NS:9 NO @@ -209,7 +204,6 @@ 292 {{122, 259}, {56, 21}} - _NS:9 NO @@ -233,7 +227,6 @@ 292 {{91, 288}, {118, 23}} - _NS:9 NO @@ -250,7 +243,6 @@ 292 {{122, 318}, {56, 21}} - _NS:9 NO @@ -274,8 +266,6 @@ 292 {{83, 347}, {136, 44}} - - _NS:9 NO IBCocoaTouchFramework @@ -293,10 +283,30 @@ + + + 292 + {{93, 397}, {116, 44}} + + _NS:9 + NO + IBCocoaTouchFramework + 0 + 0 + 1 + Test Gesture + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + {{0, 20}, {320, 460}} - 3 @@ -367,6 +377,15 @@ 18 + + + testGesture: + + + 7 + + 26 + @@ -389,6 +408,7 @@ + @@ -448,6 +468,11 @@ + + 25 + + + @@ -475,6 +500,7 @@ com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -484,58 +510,9 @@ - 24 - - - - - MyViewControllerViewController - UIViewController - - id - id - - - - computeAction: - id - - - showAlert: - id - - - - UILabel - UIButton - UITextField - UITextField - - - - answerLabel - UILabel - - - computeSumButton - UIButton - - - firstArg - UITextField - - - secondArg - UITextField - - - - IBProjectSource - ./Classes/MyViewControllerViewController.h - - - + 26 + 0 IBCocoaTouchFramework diff --git a/sample-code/apps/TestApp/TestApp.xcodeproj/project.pbxproj b/sample-code/apps/TestApp/TestApp.xcodeproj/project.pbxproj index f46042391..33e1a62ac 100644 --- a/sample-code/apps/TestApp/TestApp.xcodeproj/project.pbxproj +++ b/sample-code/apps/TestApp/TestApp.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 255BAFEC1790223300DE7158 /* GestureTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 255BAFEA1790223300DE7158 /* GestureTestViewController.m */; }; + 255BAFED1790223300DE7158 /* GestureTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 255BAFEB1790223300DE7158 /* GestureTestViewController.xib */; }; + 255BAFEF1790249F00DE7158 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 255BAFEE1790249F00DE7158 /* MapKit.framework */; }; 3647AE1315CA0082006F70D6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3647AE1215CA0082006F70D6 /* UIKit.framework */; }; 3647AE1515CA0082006F70D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3647AE1415CA0082006F70D6 /* Foundation.framework */; }; 3647AE1715CA0082006F70D6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3647AE1615CA0082006F70D6 /* CoreGraphics.framework */; }; @@ -19,6 +22,10 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 255BAFE91790223300DE7158 /* GestureTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GestureTestViewController.h; sourceTree = ""; }; + 255BAFEA1790223300DE7158 /* GestureTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GestureTestViewController.m; sourceTree = ""; }; + 255BAFEB1790223300DE7158 /* GestureTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GestureTestViewController.xib; sourceTree = ""; }; + 255BAFEE1790249F00DE7158 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 3647AE0E15CA0082006F70D6 /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3647AE1215CA0082006F70D6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 3647AE1415CA0082006F70D6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -40,6 +47,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 255BAFEF1790249F00DE7158 /* MapKit.framework in Frameworks */, 3647AE1315CA0082006F70D6 /* UIKit.framework in Frameworks */, 3647AE1515CA0082006F70D6 /* Foundation.framework in Frameworks */, 3647AE1715CA0082006F70D6 /* CoreGraphics.framework in Frameworks */, @@ -52,6 +60,7 @@ 3647AE0315CA0082006F70D6 = { isa = PBXGroup; children = ( + 255BAFEE1790249F00DE7158 /* MapKit.framework */, 36FEEFED1656DD6000100C04 /* Default-568h@2x.png */, 3647AE1815CA0082006F70D6 /* TestApp */, 3647AE1115CA0082006F70D6 /* Frameworks */, @@ -86,6 +95,9 @@ 3647AE2915CA00D5006F70D6 /* MyViewControllerViewController.h */, 3647AE2A15CA00D5006F70D6 /* MyViewControllerViewController.m */, 3647AE2B15CA00D5006F70D6 /* MyViewControllerViewController.xib */, + 255BAFE91790223300DE7158 /* GestureTestViewController.h */, + 255BAFEA1790223300DE7158 /* GestureTestViewController.m */, + 255BAFEB1790223300DE7158 /* GestureTestViewController.xib */, ); name = TestApp; path = "Test App 2"; @@ -156,6 +168,7 @@ 3647AE1D15CA0082006F70D6 /* InfoPlist.strings in Resources */, 3647AE2D15CA00D5006F70D6 /* MyViewControllerViewController.xib in Resources */, 36FEEFEE1656DD6000100C04 /* Default-568h@2x.png in Resources */, + 255BAFED1790223300DE7158 /* GestureTestViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -169,6 +182,7 @@ 3647AE1F15CA0082006F70D6 /* main.m in Sources */, 3647AE2315CA0082006F70D6 /* TA2AppDelegate.m in Sources */, 3647AE2C15CA00D5006F70D6 /* MyViewControllerViewController.m in Sources */, + 255BAFEC1790223300DE7158 /* GestureTestViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/sample-code/examples/java/testng/src/test/java/com/saucelabs/appium/SimpleTest.java b/sample-code/examples/java/testng/src/test/java/com/saucelabs/appium/SimpleTest.java index cfda55060..c36103377 100644 --- a/sample-code/examples/java/testng/src/test/java/com/saucelabs/appium/SimpleTest.java +++ b/sample-code/examples/java/testng/src/test/java/com/saucelabs/appium/SimpleTest.java @@ -296,6 +296,28 @@ public class SimpleTest { Dimension text2 = driver.findElement(By.xpath("//textfield[2]")).getSize(); assertEquals(text1.getWidth(), text2.getWidth()); assertEquals(text1.getHeight(), text2.getHeight()); + }@Test + @SuppressWarnings("serial") + public void testRotation() throws Exception { + WebElement button = driver.findElement(By.name("Test Gesture")); + button.click(); + ((JavascriptExecutor) driver).executeScript("mobile: rotate", new HashMap() {{ put("x", (double)114); put("y", (double)198); put("radius", (double)3); put("touchCount", (double)2); put("duration", 5.0); put("rotation", 220.0); }}); + } + + @Test + @SuppressWarnings("serial") + public void testPinchClose() throws Exception { + WebElement button = driver.findElement(By.name("Test Gesture")); + button.click(); + ((JavascriptExecutor) driver).executeScript("mobile: pinchClose", new HashMap() {{ put("startX", (double)150); put("startY", (double)230); put("endX", (double)200); put("endY", (double)260); put("duration", 2.0); }}); + } + + @Test + @SuppressWarnings("serial") + public void testPinchOpen() throws Exception { + WebElement button = driver.findElement(By.name("Test Gesture")); + button.click(); + ((JavascriptExecutor) driver).executeScript("mobile: pinchOpen", new HashMap() {{ put("startX", (double)114); put("startY", (double)198); put("endX", (double)257); put("endY", (double)256); put("duration", 2.0); }}); } public class SwipeableWebDriver extends RemoteWebDriver implements HasTouchScreen { diff --git a/test/functional/testapp/pinchGesture.js b/test/functional/testapp/pinchGesture.js new file mode 100644 index 000000000..edd7911ec --- /dev/null +++ b/test/functional/testapp/pinchGesture.js @@ -0,0 +1,29 @@ +/*global it:true */ +"use strict"; + +var assert = require("assert") + , describeWd = require("../../helpers/driverblock.js").describeForApp('TestApp') + , should = require("should"); + +describeWd('pinchOpen and pinchClose gesture', function(h) { + return it('should pinchOpen and pinchClose map after tapping Test Gesture', function(done) { + var driver = h.driver; + driver.elementsByTagName('button', function(err, buttons) { + buttons[3].click(function(err) { + should.not.exist(err); + driver.elementByXPath('//window[1]/UIAMapView[1]', function(err) { + should.not.exist(err); + driver.execute("mobile: pinchOpen", [{startX: 114.0, startY: 198.0, endX: 257.0, endY: 256.0, duration: 5.0}], function(err) { + driver.elementByXPath('//window[1]/UIAMapView[1]', function(err) { + should.not.exist(err); + driver.execute("mobile: pinchClose", [{startX: 114.0, startY: 198.0, endX: 257.0, endY: 256.0, duration: 5.0}], function(err) { + should.not.exist(err); + done(); + }); + }); + }); + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/functional/testapp/rotationGesture.js b/test/functional/testapp/rotationGesture.js new file mode 100644 index 000000000..2dcd6bb1a --- /dev/null +++ b/test/functional/testapp/rotationGesture.js @@ -0,0 +1,23 @@ +/*global it:true */ +"use strict"; + +var assert = require("assert") + , describeWd = require("../../helpers/driverblock.js").describeForApp('TestApp') + , should = require("should"); + +describeWd('rotation gesture', function(h) { + return it('should rotate map after tapping Test Gesture', function(done) { + var driver = h.driver; + driver.elementsByTagName('button', function(err, buttons) { + buttons[3].click(); + should.not.exist(err); + }); + driver.elementsByTagName('Map', function(err) { + should.not.exist(err); + driver.execute("mobile: rotate", [{x: 114, y: 198, duration: 5, radius: 3, rotation: 220, touchCount: 2}], function(err) { + should.not.exist(err); + done(); + }); + }); + }); +}); \ No newline at end of file