Merge pull request #2449 from bootstraponline/1.0-beta

Document appium bindings & remove incorrect docs
This commit is contained in:
bootstraponline
2014-04-30 21:49:31 -04:00
5 changed files with 669 additions and 623 deletions
+668
View File
@@ -0,0 +1,668 @@
# Appium Client Libraries
Appium has libraries for:
Language | Source
:--|--:
[Ruby][rubygems] | [GitHub](https://github.com/appium/ruby_lib)
[Python][pypi] | [GitHub](https://github.com/appium/python-client)
[Java][maven] | [GitHub](https://github.com/appium/java-client)
[JavaScript][npm] | [GitHub](https://github.com/admc/wd)
[PHP][php] | [GitHub](https://github.com/appium/php-client)
[C#][nuget] | [GitHub](https://github.com/appium/appium-dotnet-driver)
[rubygems]: http://rubygems.org/gems/appium_lib
[pypi]: https://pypi.python.org/pypi/Appium-Python-Client
[maven]: https://search.maven.org/#search%7Cga%7C1%7Cg%3Aio.appium%20a%3Ajava-client
[npm]: https://www.npmjs.org/package/wd
[php]: https://github.com/appium/php-client
[nuget]: http://www.nuget.org/packages/Appium.WebDriver/
Note that some methods such as `endTestCoverage()` and `complexFind()` are
not generally useful. Proper coverage support will be added once [this issue](https://github.com/appium/appium/issues/2448)
is resolved. `complexFind()` will be removed once [this issue](https://github.com/appium/appium/issues/2264)
is resolved. If you want to use them anyway, consult the documentation for the bindings on GitHub.
## Lock
Lock the screen.
```ruby
lock 5
```
```python
self.driver.lock(5)
```
```java
driver.lockScreen(3);
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.LockDevice(3);
```
## Background app
Send the currently active app to the background.
```ruby
background_app 5
```
```python
self.driver.background_app(5)
```
```java
driver.runAppInBackground(5);
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.BackgroundApp(5);
```
## Hide Keyboard (iOS only)
Hide the keyboard on iOS
```ruby
hide_keyboard
```
```python
self.driver.hide_keyboard()
```
```java
driver.hideKeyboard();
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.HideKeyboard("Done");
```
## Is installed
Check if an app is installed
```ruby
is_installed? "com.example.android.apis"
```
```python
self.driver.is_app_installed('com.example.android.apis')
```
```java
driver.isAppInstalled("com.example.android.apis")
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.IsAppInstalled("com.example.android.apis-");
```
## Install App
Install an app to the device.
```ruby
install 'path/to/my.apk'
```
```python
self.driver.install_app('path/to/my.apk')
```
```java
driver.installApp("path/to/my.apk")
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.InstallApp("path/to/my.apk");
```
## Remove App
Remove an app from the device.
```ruby
remove 'com.example.android.apis'
```
```python
self.driver.remove_app('com.example.android.apis')
```
```java
driver.removeApp("com.example.android.apis")
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.RemoveApp("com.example.android.apis");
```
## Shake
Simulate the device shaking.
```ruby
shake
```
```python
self.driver.shake()
```
```java
driver.shake()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.ShakeDevice();
```
## Close app
Close the app
```ruby
close_app
```
```python
self.driver.close_app();
```
```java
driver.closeApp()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.CloseApp();
```
## Launch
Launch the app
```ruby
launch
```
```python
self.driver.launch_app()
```
```java
driver.launchApp()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.LaunchApp();
```
## Reset
Reset the app.
```ruby
reset
```
```python
self.driver.reset()
```
```java
driver.resetApp()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.ResetApp();
```
## Available Contexts
List all available contexts
```ruby
context_array = available_contexts
```
```python
self.driver.contexts
```
```java
driver.getContextHandles()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.GetContexts()
```
## Current context
List the current context
```ruby
context = current_context
```
```python
self.driver.current_context
```
```java
driver.getContext()
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.GetContext()
```
## Switch to default context
Change the context to the default.
```ruby
switch_to_default_context
```
```python
self.driver.switch_to.context(None)
```
```java
driver.context();
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.SetContext();
```
## App Strings
Get the app's strings.
```ruby
strings = app_strings
```
```python
self.driver.app_strings
```
```java
driver.getAppString();
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.GetAppStrings();
```
## Key Event
Send a key event to the device.
```ruby
key_event 176
```
```python
self.driver.keyevent(176)
```
```java
driver.sendKeyEvent(AndroidKeyCode.HOME);
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.KeyEvent("176");
```
## Current Activity
Android only. Get the current activity.
```ruby
current_activity
```
```python
self.driver.current_activity
```
```java
driver.currentActivity();
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.GetCurrentActivity();
```
## TouchAction / MultiTouchAction
An API for generating touch actions. This section of the documentation will be
expanded upon soon.
```ruby
touch_action = Appium::TouchAction.new
element = find_element :name, 'Buttons, Various uses of UIButton'
touch_action.press(element: element, x: 10, y: 10).perform
```
```python
self._touch_action.tap(element, 10, 10)
```
```java
TouchAction action = new TouchAction(driver)
.press(mapview, 10, 10)
.release().
perform();
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
var touchAction1 = new TouchActions(this);
touchAction1.Down(10, 10).Up(10, 10);
var multiTouchAction = new MultiTouchAction(this);
multiTouchAction.Add(touchAction1);
PerformMultiTouchAction(multiTouchAction);
```
## Swipe
Simulate a user swipe.
```ruby
swipe start_x: 75, start_y: 500, end_x: 75, end_y: 0, duration: 0.8
```
```python
self.driver.swipe(75, 500, 75, 0, 0.8)
```
```java
driver.swipe(75, 500, 75, 0, 800)
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
todo: c#
```
## Pinch
Pinch the screen.
```ruby
pinch 75
```
```python
self.driver.pinch(element=el)
```
```java
driver.pinch(element);
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.Pinch(25, 25)
```
## Zoom
Zoom the screen.
```ruby
zoom 200
```
```python
self.driver.zoom(element=el)
```
```java
driver.zoom(element);
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.Zoom(100, 200);
```
## Pull file
Pulls a file from the device.
```ruby
pull_file 'Library/AddressBook/AddressBook.sqlitedb'
```
```python
self.driver.pull_file('Library/AddressBook/AddressBook.sqlitedb')
```
```java
driver.pullFile("Library/AddressBook/AddressBook.sqlitedb");
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.PullFile("Library/AddressBook/AddressBook.sqlitedb");
```
## Push File
Pushes a file to the device.
```ruby
data = "some data for the file"
path = "/data/local/tmp/file.txt"
push_file path, data
```
```python
data = "some data for the file"
path = "/data/local/tmp/file.txt"
self.driver.push_file(path, data.encode('base64'))
```
```java
byte[] data = Base64.encodeBase64("some data for the file".getBytes());
String path = "/data/local/tmp/file.txt";
driver.pushFile(path, data)
```
```javascript
todo: javascript
```
```php
todo: php
```
```csharp
driver.PushFile("/data/local/tmp/file.txt", "some data for the file");
```
## Appium Desktop Apps
Appium's desktop app supports OS X and Windows.
- [Appium.app for OS X][bitbucket]
- [Appium.exe for Windows][bitbucket]
[bitbucket]: https://bitbucket.org/appium/appium.app/downloads/
+1 -137
View File
@@ -2,11 +2,7 @@
Appium supports a subset of the WebDriver locator strategies:
* find by "tag name" (i.e., ui component type)
* find by "name" (i.e., the text, label, or developer-generated ID a.k.a
'accessibilityIdentifier' of an element)
NOTE: the "name" locator strategy will be deprecated on mobile devices,
and will not be a part of Appium v1.0
* find by "class" (i.e., ui component type)
* find by "xpath" (i.e., an abstract representation of a path to an element,
with certain constraints)
@@ -19,143 +15,11 @@ search using the UiAutomator Api (Android-only)
* `accessibility id`: a string corresponding to a recursive element search
using the Id/Name that the native Accessibility options utilize.
## Tag name mapping
You can use the direct UIAutomation component type name for the tag name,
or use the simplified mapping (used in some examples below) found here:
https://github.com/appium/appium-uiauto/blob/master/uiauto/lib/mechanic.js#L30
## Issues
There's a known issue with table cell elements becoming invalidated before
there's time to interact with them. We're working on a fix
## Examples
### Find all the UIAButtons on the screen
WD.js:
```js
driver.elementsByTagName('button', function(err, buttons) {
// tap all the buttons
var tapNextButton = function() {
var button = buttons.shift();
if (typeof button !== "undefined") {
button.click(function(err) {
tapNextButton();
})
} else {
driver.quit();
}
}
tapNextButton();
});
```
Ruby:
```ruby
buttons = @driver.find_elements :tag_name, :button
buttons.each { |b| b.click }
```
Python:
```python
[button.click() for button in driver.find_elements_by_tag_name('button')]
```
### Find the element with the text (or accessibilityIdentifier) "Go"
WD.js:
```js
driver.elementByName('Go', function(err, el) {
el.tap(function(err) {
driver.quit();
});
});
```
Ruby:
```ruby
@driver.find_element(:name, 'Go').click
```
Python:
```python
driver.find_element_by_name('Go').click()
```
### Find the nav bar text element where the text begins with "Hi, "
WD.js:
```js
driver.elementByXpath('//navigationBar/text[contains(@value, "Hi, ")]', function(err, el) {
el.text(function(err, text) {
console.log(text);
driver.quit();
});
});
```
Ruby:
```ruby
@driver.find_element :xpath, '//navigationBar/text[contains(@value, "Hi, ")]'
```
### Find an element by tagName
Java:
```java
driver.findElement(By.tagName("button")).sendKeys("Hi");
WebELement element = findElement(By.tagName("button"));
element.sendKeys("Hi");
List<WebElement> elems = findElements(By.tagName("button"));
elems.get(0).sendKeys("Hi");
```
Python:
```python
driver.find_elements_by_tag_name('tableCell')[5].click()
```
### Using the "-ios uiautomation" locator strategy
WD.js:
```js
driver.element('-ios uiautomation', '.elements()[1].cells()[2]').getAttribute('name');
```
### Using the "-android uiautomator" locator strategy
WD.js:
```js
driver.element('-android uiautomator', 'new UiSelector().clickable(true)').getAttribute('name');
```
### Pull to refresh using a swipe gesture
Python:
```python
js_snippet = "mobile: swipe"
args = {'startX':0.5, 'startY':0.2, 'startX':0.5, 'startY':0.95, 'tapCount':1, 'duration':10}
driver.execute_script(js_snippet, args)
```
## Using The Appium Inspector To Locate Elements
Appium provides you with a neat tool that allows you to find the the elements
-369
View File
@@ -1,369 +0,0 @@
# Automating mobile gestures
While the Selenium WebDriver spec has support for certain kinds of mobile
interaction, its parameters are not always easily mappable to the
functionality that the underlying device automation (like UIAutomation in the
case of iOS) provides. To that end, Appium augments the WebDriver spec with
extra commands and parameters for mobile gestures:
* **tap** (on screen or on element) with options:
* how many fingers
* how long to tap
* how many taps
* where precisely to tap on the screen or element
* **flick** (on screen or on element) with options:
* how many fingers
* where to start the flick on screen or element
* where to end the flick on screen or element
* **swipe/drag** (on screen or on element) with options:
* how many fingers
* how long the swipe/drag takes in seconds
* where to start the swipe on screen or element
* where to end the swipe on screen or element
* **scroll to** (element)
* **slider**
* **shake**
* **longTap** (element)
* set the **orientation** with option:
* new orientation (landscape or portrait)
## JSON Wire Protocol server extensions
Here are the endpoints with which we have implemented these additions to the
spec.
**Note on coordinates:** All the X and Y parameters listed below can be used
in two ways. If they are between 0 and 1 (e.g., 0.5), they are taken to be
percentage of screen or element size. In other words,
`{x: 0.5, y: 0.25}` means a coordinate that is 50% from the left side of the
screen/element, and 25% from the top of the screen/element. If the values are
greater than 1, they are taken as pixels. So, `{x: 100,
y: 300}` means a coordinate that is 100 pixels from the left and 300 from
the top of the screen/element.
**Note on performing actions on screen vs elements:** These methods all take
an optional `element` parameter. If present, this is taken to be the ID of an
element which has already been retrieved. So in this case,
the coordinates will be taken to refer to the rectangle of that element only
. So `{x: 0.5, y: 0.5, element: '3'}` means "the exact middle point of the
element with ID '3'".
* `POST session/:sessionId/touch/tap` - perform a tap on the screen or an element
* URL Parameter: sessionId of session to route to
* JSON parameters:
* `tapCount` (optional, default `1`): how many times to tap
* `touchCount` (optional, default `1`): how many fingers to tap with
* `duration` (optional, default `0.1`): how long (in seconds) to tap
* `x` (optional, default `0.5`): x coordinate to tap (in pixels or relative units)
* `y` (optional, default `0.5`): y coordinate to tap (in pixels or relative units)
* `element` (optional): ID of element to scope this command to
* `POST session:/sessionId/touch/flick_precise` - perform a flick on the screen or an element
* URL Parameter: sessionId of session to route to
* JSON parameters:
* `touchCount` (optional, default `1`): how many fingers to flick with
* `startX` (optional, default `0.5`): x coordinate where flick begins (in pixels or relative units)
* `startY` (optional, default `0.5`): y coordinate where flick begins (in pixels or relative units)
* `endX` (required): x coordinate where flick ends (in pixels or relative units)
* `endY` (required): y coordinate where flick ends (in pixels or relative units)
* `element` (optional): ID of element to scope this command to
* `POST session:/sessionId/touch/swipe` - perform a swipe/drag on the screen or an element
* URL Parameter: sessionId of session to route to
* JSON parameters:
* `touchCount` (optional, default `1`): how many fingers to flick with
* `startX` (optional, default `0.5`): x coordinate where swipe begins (in pixels or relative units)
* `startY` (optional, default `0.5`): y coordinate where swipe begins (in pixels or relative units)
* `endX` (required): x coordinate where swipe ends (in pixels or relative units)
* `endY` (required): y coordinate where swipe ends (in pixels or relative units)
* `duration` (optional, default `0.8`): time (in seconds) to spend performing the swipe/drag
* `element` (optional): ID of element to scope this command to
**Note on setting orientation:** Setting the orientation takes different
parameters than the tap, flick, and swipe methods. This action is performed
by setting the orientation of the browser to "LANDSCAPE" or "PORTRAIT". The
alternative access method below does not apply to setting orientation.
* `POST /session/:sessionId/orientation` - set the orientation of the browser
* URL Parameter: sessionId of session to route to
* JSON parameters:
* `orientation` (required): new orientation, either "LANDSCAPE" or "PORTRAIT"
## Alternative access method
Extending the JSON Wire Protocol is great, but it means that the various
WebDriver language bindings will have to implement access to these endpoints
in their own way. Naturally, this will take different amounts of time
depending on the project. We have instituted a way to get around this delay,
by using `driver.execute()` with special parameters.
`POST session/:sessionId/execute` takes two JSON parameters:
* `script` (usually a snippet of javascript)
* `args` (usually an array of arguments passed to that snippet in the javascript engine)
In the case of these new mobile methods, `script` must be one of:
* `mobile: tap`
* `mobile: flick`
* `mobile: swipe`
* `mobile: scrollTo`
* `mobile: scroll`
* `mobile: shake`
(The `mobile:` prefix allows us to route these requests to the appropriate
endpoint).
And `args` will be an array with one element: a Javascript object defining
the parameters for the corresponding function. So, let's say I want to call
`tap` on a certain screen position. I can do so by calling `driver.execute`
with these JSON parameters:
```json
{
"script": "mobile: tap",
"args": [{
"x": 0.8,
"y": 0.4
}]
}
```
In this example, our new `tap` method will be called with the `x` and `y`
params as described above.
## Code examples
In these examples, note that the element parameter is always optional.
## Tap
* **WD.js:**
```js
driver.elementsByTagName('tableCell', function(err, els) {
var tapOpts = {
x: 150 // in pixels from left
, y: 30 // in pixels from top
, element: els[4].value // the id of the element we want to tap
};
driver.execute("mobile: tap", [tapOpts], function(err) {
// continue testing
});
});
```
* **Java:**
```java
WebElement row = driver.findElements(By.tagName("tableCell")).get(4);
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, Double> tapObject = new HashMap<String, Double>();
tapObject.put("x", 150); // in pixels from left
tapObject.put("y", 30); // in pixels from top
tapObject.put("element", ((RemoteWebElement) row).getId()); // the id of the element we want to tap
js.executeScript("mobile: tap", tapObject);
```
```java
//In iOS app, if UI element visbile property is "false".
//Using element location tap on it.
WebElement element = wd.findElement(By.xpath("//window[1]/scrollview[1]/image[1]"));
JavascriptExecutor js = (JavascriptExecutor) wd;
HashMap<String, Double> tapObject = new HashMap<String, Double>();
tapObject.put("x", (double) element.getLocation().getX());
tapObject.put("y", (double) element.getLocation().getY());
tapObject.put("duration", 0.1);
js.executeScript("mobile: tap", tapObject);
```
* **Python:**
```python
driver.execute_script("mobile: tap", {"touchCount":"1", "x":"0.9", "y":"0.8", "element":element.id})
```
* **Ruby:**
```ruby
@driver.execute_script 'mobile: tap', :x => 150, :y => 30
```
* **Ruby:**
```ruby
b = @driver.find_element :name, 'Sign In'
@driver.execute_script 'mobile: tap', :element => b.ref
```
* **C#:**
```c#
Dictionary<String, Double> coords = new Dictionary<string, double>();
coords.Add("x", 12);
coords.Add("y", 12);
driver.ExecuteScript("mobile: tap", coords);
```
## Flick
* **WD.js:**
```js
// options for a 2-finger flick from the center of the screen to the top left
var flickOpts = {
endX: 0
, endY: 0
, touchCount: 2
};
driver.execute("mobile: flick", [flickOpts], function(err) {
// continue testing
});
```
* **Java:**
```java
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, Double> flickObject = new HashMap<String, Double>();
flickObject.put("endX", 0);
flickObject.put("endY", 0);
flickObject.put("touchCount", 2);
js.executeScript("mobile: flick", flickObject);
```
## Swipe
*Note*: Swiping is unfortunately broken in iOS7, because of a bug in Apple's
frameworks. For iOS7, see `mobile: scroll` as a workaround that works for most
cases.
* **WD.js:**
```js
// options for a slow swipe from the right edge of the screen to the left
var swipeOpts = {
startX: 0.95
, startY: 0.5
, endX: 0.05
, endY: 0.5
, duration: 1.8
};
driver.execute("mobile: swipe", [swipeOpts], function(err) {
// continue testing
});
```
* **Java:**
```java
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, Double> swipeObject = new HashMap<String, Double>();
swipeObject.put("startX", 0.95);
swipeObject.put("startY", 0.5);
swipeObject.put("endX", 0.05);
swipeObject.put("endY", 0.5);
swipeObject.put("duration", 1.8);
js.executeScript("mobile: swipe", swipeObject);
```
## Scroll
* **WD.js:**
```js
// scroll the view down
driver.execute("mobile: scroll", [{direction: 'down'}], function(err) {
// continue testing
});
```
* **Java:**
```java
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("direction", "down");
scrollObject.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: scroll", scrollObject);
```
## Slider
**iOS**
* **Java**
```java
// slider values can be string representations of numbers between 0 and 1
// e.g., "0.1" is 10%, "1.0" is 100%
WebElement slider = wd.findElement(By.xpath("//window[1]/slider[1]"));
slider.sendKeys("0.1");
```
**Android**
The best way to interact with the slider on Android is with the 'mobile:
tap' gesture. It is difficult to find a reliable way to set a specific
percentage that works on all screen sizes, however. Therefore,
it is recommended to write tests that focus on minimum, 50%, and maximum.
* **Ruby**
```ruby
# 0%
@driver.execute_script 'mobile: tap', :x =>slider.location.x, :y =>slider.location.y
# 100%
@driver.execute_script 'mobile: tap', :x =>slider.location.x + slider.size.width - 1, :y =>slider.location.y
# 50%
slider.click
```
## Set orientation
* **WD.js:**
```js
driver.setOrientation("LANDSCAPE", function(err) {
// continue testing
});
```
* **Python:**
```python
driver.orientation = "LANDSCAPE"
```
## Scroll To
```ruby
b = @driver.find_element :name, 'Sign In'
@driver.execute_script 'mobile: scrollTo', :element => b.ref
```
```java
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement element = wd.findElement(By.name("Log In"));;
HashMap<String, String> scrollToObject = new HashMap<String, String>();
scrollToObject.put("element",((RemoteWebElement) element).getId());
js.executeScript("mobile: scrollTo", scrollToObject);
```
## longTap
* **c#**
```c#
// long tap an element
//
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("using", _attributeType);
parameters.Add("value", _attribute);
Response response = rm.executescript(DriverCommand.FindElement, parameters);
Dictionary<string, object> elementDictionary = response.Value as Dictionary<string, object>;
string id = null;
if (elementDictionary != null)
{
id = (string)elementDictionary["ELEMENT"];
}
IJavaScriptExecutor js = (IJavaScriptExecutor)remoteDriver;
Dictionary<String, String> longTapObject = new Dictionary<String, String>();
longTapObject.Add("element", id);
js.ExecuteScript("mobile: longClick", longTapObject);
```
-78
View File
@@ -1,78 +0,0 @@
# Cross platform mobile methods
## Reset
Mobile reset will reset the app's state.
Ruby + [appium_lib gem](https://github.com/appium/ruby_lib)
```ruby
mobile :reset
```
Ruby without the gem
```ruby
@driver.execute_script 'mobile: reset'
```
## pullFile
Fetch a file from the device's filesystem, returning it base64 encoded.
Takes a single argument, `path`. On Android and iOS, this is either the path
to the file (relative to the root of the app's file system). On iOS only,
if path starts with `/AppName.app`, which will be replaced with the
application's .app directory
```ruby
# Android and iOS
@driver.execute_script 'mobile: pullFile', {path: '/Library/AddressBook/AddressBook.sqlitedb'} #=> /Library/AddressBook/AddressBook.sqlitedb
# iOS only
@driver.execute_script 'mobile: pullFile, {path: '/UICatalog.app/logfile.log'} #=> /Applications/12323-452262-24241-23-124124/UICatalog.app/logfile.log
```
Ruby
```ruby
@driver.execute_script('mobile: pullFile', {path: '/Library/AddressBook/AddressBook.sqlitedb'})
```
## Android mobile methods
## KeyEvent
[KeyEvent](http://developer.android.com/reference/android/view/KeyEvent.html) enables sending a keycode to Android.
Press the system menu button in Java.
```java
HashMap<String, Integer> keycode = new HashMap<String, Integer>();
keycode.put("keycode", 82);
((JavascriptExecutor)driver).executeScript("mobile: keyevent", keycode);
```
Ruby + [appium_lib gem](https://github.com/appium/ruby_lib)
```ruby
mobile :keyevent, keycode: 82
```
Ruby without the gem
```ruby
@driver.execute_script 'mobile: keyevent', :keycode => 82
```
## Mobile find
Java
See [MobileFindJavaTest.java](/sample-code/examples/java/junit/src/test/java/com/saucelabs/appium/MobileFindJavaTest.java)
Ruby + [appium_lib gem](https://github.com/appium/ruby_lib)
```ruby
scroll_to 'Gallery'
```
-39
View File
@@ -1,39 +0,0 @@
# Touch Actions
WebDriver provides an API to send some kinds of touch gestures to the devices,
for example, to long press an element you can do:
For iOS Application:
```java
final WebElement imageView = searchResults.findElement(By.tagName("ImageView"));
new TouchActions(driver).longPress(imageView).perform();
```
For Android Application:
Java:
```java
WebElement element = wd.findElement(By.name("API Demo"));
JavascriptExecutor js = (JavascriptExecutor) wd;
HashMap<String, String> tapObject = new HashMap<String, String>();
tapObject.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: longClick", tapObject);
```
Python:
```python
element = wd.find_element_by_xpath("your_element_xpath")
wd.execute_script("mobile: longClick",{ "touchCount": 1, "x": 0, "y": 300, "element":element.id })
```
Currently Appium support some of the gestures in the Touch Actions API:
* flick
* long press
* single tap
Some other gestures are supported through the "Alternative access method"
explained in [Automating mobile gestures](gestures.md)