From 37fbb527dfe626124d714cd4ddf302b42f0aa85d Mon Sep 17 00:00:00 2001 From: bootstraponline Date: Wed, 9 Apr 2014 18:14:14 -0400 Subject: [PATCH] Fix docs to work with jekyll --- docs/cn/README.md | 5 + docs/cn/android-hax-emulator.cn.md | 5 + docs/cn/android_coverage.cn.md | 5 + docs/cn/caps.cn.md | 5 + docs/cn/credits.cn.md | 5 + docs/cn/finding-elements.cn.md | 6 + docs/cn/gestures.cn.md | 11 +- docs/cn/grid.cn.md | 5 + docs/cn/grunt.cn.md | 5 + docs/cn/hybird.cn.md | 7 + docs/cn/index.md | 9 + docs/cn/ios-deploy.cn.md | 12 + docs/cn/mobile-web.cn.md | 8 + docs/cn/mobile_methods.cn.md | 6 + docs/cn/real-devices.cn.md | 6 + docs/cn/running-on-linux.cn.md | 5 + docs/cn/running-on-osx.cn.md | 5 + docs/cn/running-on-windows.cn.md | 5 + docs/cn/running-tests.cn.md | 5 + docs/cn/server-args.cn.md | 5 + docs/cn/touch-actions.cn.md | 7 + docs/cn/troubleshooting.cn.md | 5 + docs/{ => en}/android-hax-emulator.md | 14 +- docs/{ => en}/android_coverage.md | 23 +- docs/{ => en}/caps.md | 5 + docs/{ => en}/credits.md | 5 + docs/{ => en}/finding-elements.md | 52 +++- docs/en/gestures.md | 375 ++++++++++++++++++++++++++ docs/{ => en}/grid.md | 22 +- docs/{ => en}/grunt.md | 8 +- docs/{ => en}/hybrid.md | 173 +++++++----- docs/en/index.md | 9 + docs/{ => en}/ios-deploy.md | 39 ++- docs/{ => en}/mobile-web.md | 34 ++- docs/{ => en}/mobile_methods.md | 17 +- docs/{ => en}/real-devices.md | 5 + docs/{ => en}/running-on-linux.md | 25 +- docs/{ => en}/running-on-osx.md | 7 +- docs/en/running-on-windows.md | 60 +++++ docs/{ => en}/running-tests.md | 21 +- docs/{ => en}/server-args.md | 7 +- docs/{ => en}/style-guide.md | 34 ++- docs/{ => en}/touch-actions.md | 12 +- docs/{ => en}/troubleshooting.md | 82 ++++-- docs/gestures.md | 330 ----------------------- docs/running-on-windows.md | 37 --- 46 files changed, 1007 insertions(+), 526 deletions(-) create mode 100644 docs/cn/index.md rename docs/{ => en}/android-hax-emulator.md (52%) rename docs/{ => en}/android_coverage.md (85%) rename docs/{ => en}/caps.md (98%) rename docs/{ => en}/credits.md (94%) rename docs/{ => en}/finding-elements.md (76%) create mode 100644 docs/en/gestures.md rename docs/{ => en}/grid.md (65%) rename docs/{ => en}/grunt.md (94%) rename docs/{ => en}/hybrid.md (51%) create mode 100644 docs/en/index.md rename docs/{ => en}/ios-deploy.md (71%) rename docs/{ => en}/mobile-web.md (83%) rename docs/{ => en}/mobile_methods.md (80%) rename docs/{ => en}/real-devices.md (97%) rename docs/{ => en}/running-on-linux.md (52%) rename docs/{ => en}/running-on-osx.md (97%) create mode 100644 docs/en/running-on-windows.md rename docs/{ => en}/running-tests.md (92%) rename docs/{ => en}/server-args.md (98%) rename docs/{ => en}/style-guide.md (78%) rename docs/{ => en}/touch-actions.md (91%) rename docs/{ => en}/troubleshooting.md (61%) delete mode 100644 docs/gestures.md delete mode 100644 docs/running-on-windows.md diff --git a/docs/cn/README.md b/docs/cn/README.md index e71dd8075..5415002a1 100644 --- a/docs/cn/README.md +++ b/docs/cn/README.md @@ -1,3 +1,8 @@ +--- +layout: default +title: readme +--- + # Appium > Appium是一个支持原生,混合和移动web apps的开源的跨平台测试框架工具 diff --git a/docs/cn/android-hax-emulator.cn.md b/docs/cn/android-hax-emulator.cn.md index ceeccee5a..4fb46ecee 100644 --- a/docs/cn/android-hax-emulator.cn.md +++ b/docs/cn/android-hax-emulator.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Intel 硬件加速器管理 +--- + # Intel® 硬件加速器管理 如果你发现android虚拟机太慢, 并且你的系统运行在Intel® 的cpu上. 那么你可以尝试下HAXM, HAXM能够让你充分利用硬件虚拟化技术来加速android模拟器 diff --git a/docs/cn/android_coverage.cn.md b/docs/cn/android_coverage.cn.md index 9c6a4ab73..be44ae298 100644 --- a/docs/cn/android_coverage.cn.md +++ b/docs/cn/android_coverage.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Android Coverage +--- + Android 覆盖率需要使用模拟器或者 root 过的机器。使用 instrument target 构建应用,比如 `$ ant instrument` 将 `androidCoverage` 传给你设备的 capabilities,并设置为你的 instrument 的 class。 diff --git a/docs/cn/caps.cn.md b/docs/cn/caps.cn.md index f42f72a2d..a2fcac272 100644 --- a/docs/cn/caps.cn.md +++ b/docs/cn/caps.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Appium 服务关键字 +--- + Appium 服务关键字 ========== diff --git a/docs/cn/credits.cn.md b/docs/cn/credits.cn.md index 451f6b0e1..dfbfa0ce7 100644 --- a/docs/cn/credits.cn.md +++ b/docs/cn/credits.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 名单 +--- + 名单 ======= diff --git a/docs/cn/finding-elements.cn.md b/docs/cn/finding-elements.cn.md index c7545dc3b..ffa31c06a 100644 --- a/docs/cn/finding-elements.cn.md +++ b/docs/cn/finding-elements.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 元素定位与交互 +--- + 元素定位与交互 ===================================== @@ -71,6 +76,7 @@ Ruby: ```ruby @driver.find_element(:name, 'Go').click ``` + Python: ```python diff --git a/docs/cn/gestures.cn.md b/docs/cn/gestures.cn.md index 8370c8df6..91fd7f20e 100644 --- a/docs/cn/gestures.cn.md +++ b/docs/cn/gestures.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 使移动手势自动化 +--- + 使移动手势自动化 ========================== 当selenium webDriver 提供某些交互功能的支持时,它的参数并不总是能很容易的映射到底层自动化设备(比如ios中的UIAutomation)所提供的功能。为此,Appium在WebDriver 之上为移动手势增加了额外的命令和参数。 @@ -92,6 +97,7 @@ }] } ``` + 在这个例子中,`tap`方法被调用,使用上面定义的`x` and `y`参数。 ##示例代码 @@ -124,6 +130,7 @@ tapObject.put("element", ((RemoteWebElement) row).getId()); // 想要执行tap事件的元素id js.executeScript("mobile: tap", tapObject); ``` + ```java //在iOS app中,如果UI 控件的visible属性为“false”,通过元素的位置进行点击. WebElement element = wd.findElement(By.xpath("//window[1]/scrollview[1]/image[1]")); @@ -134,6 +141,7 @@ tapObject.put("duration", 0.1); js.executeScript("mobile: tap", tapObject); ``` + * **Python:** ```python @@ -155,7 +163,7 @@ * **C#:** - ```C# + ```c# Dictionary coords = new Dictionary(); coords.Add("x", 12); coords.Add("y", 12); @@ -234,6 +242,7 @@ ### 设置方向 * **WD.js:** + ```js driver.setOrientation("LANDSCAPE", function(err) { // continue testing diff --git a/docs/cn/grid.cn.md b/docs/cn/grid.cn.md index 7e6afadc3..0af2784ed 100644 --- a/docs/cn/grid.cn.md +++ b/docs/cn/grid.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Selenium Grid +--- + Selenium Grid ====================== diff --git a/docs/cn/grunt.cn.md b/docs/cn/grunt.cn.md index 62c9b6a79..6fbbc8f90 100644 --- a/docs/cn/grunt.cn.md +++ b/docs/cn/grunt.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Appium grunt 命令 +--- + Appium grunt 命令 ============= diff --git a/docs/cn/hybird.cn.md b/docs/cn/hybird.cn.md index 3f843c2d0..0005a52ed 100644 --- a/docs/cn/hybird.cn.md +++ b/docs/cn/hybird.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 自动化混合应用 +--- + 自动化混合应用 ====================== @@ -23,6 +28,7 @@ appium 使用一个远程调试器建立连接来实现和 web 视图的交互 当在真机上运行用例时,appium 无法直接访问 web 视图,所以我们需要通过 USB 线缆来建立连接。我们使用 [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy)建立连接。 使用 brew 安装最新的 ios-webkit-debug-proxy。在终端运行一下命令: + ``` bash # 如果你没有安装 brew 的话,先安装 brew。 > ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)" @@ -43,6 +49,7 @@ appium 使用一个远程调试器建立连接来实现和 web 视图的交互 ``` 一旦安装好了, 你就可以启动代理: + ``` bash # 将udid替换成你的设备的udid。确保端口 27753 没有被占用 # remote-debugger 将会使用这个端口。 diff --git a/docs/cn/index.md b/docs/cn/index.md new file mode 100644 index 000000000..87047a092 --- /dev/null +++ b/docs/cn/index.md @@ -0,0 +1,9 @@ +--- +layout: default +title: Documentation +description: Appium v0.18.0 Chinese Documentation +--- + +- Documentation + +{% include doc_list.md url="/docs/cn/0.18.0" %} \ No newline at end of file diff --git a/docs/cn/ios-deploy.cn.md b/docs/cn/ios-deploy.cn.md index 3ac582081..90607dad0 100644 --- a/docs/cn/ios-deploy.cn.md +++ b/docs/cn/ios-deploy.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: iOS Deploy +--- + 部署ios app 到手机上 ===================================== 准备在真机上执行appium测试, 需要如下准备: @@ -29,6 +34,7 @@ PROVISIONING_PROFILE 已经从可用的的命令中消失了,但还是有必 ``` xcodebuild -sdk -target -configuration CODE_SIGN_IDENTITY="iPhone Developer: Mister Smith" PROVISIONING_PROFILE="XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX" ``` + 成功的话, app会构建到如下目录 ```/build/-iphoneos/.app``` ## 用Fruitstrap进行部署 @@ -38,14 +44,19 @@ clone成功的话, 执行 ``make fruitstrap`` 然后, 然后复制生成的 ``fruitstrap``到app的所在的目录或上级目录下。 运行fruitstrap 通过输入以下命令 (命令是否可用依赖于你fork的 fruitstrap): + ``` ./fruitstrap -d -b -i ``` + 如果是为了持续集成,你可以发现很有用的方法来记录fruitstrap命令行和日志文件中的记录, 像这样: + ``` ./fruitstrap -d -b -i 2>&1 | tee fruit.out ``` + 在node服务启动前fruitstrap进行需要被结束, 一个方法是扫描fruitstrap的输出来得知app完成启动。 有一个有效的方法是通过一个Rakefile 和一个 ``go_device.sh`` 脚本: + ``` bundle exec rake ci:fruit_deploy_app | while read line ; do echo "$line" | grep "text to identify successful launch" @@ -58,6 +69,7 @@ bundle exec rake ci:fruit_deploy_app | while read line ; do fi done ``` + 一旦fruitstrap的进程被结束, node 服务就可以启动并且appium测试可以被执行! 下一步: diff --git a/docs/cn/mobile-web.cn.md b/docs/cn/mobile-web.cn.md index ba8e009a1..5c7f85663 100644 --- a/docs/cn/mobile-web.cn.md +++ b/docs/cn/mobile-web.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 自动化手机网页应用 +--- + 自动化手机网页应用 ====================== @@ -10,6 +15,7 @@ 如果你打算在模拟器或真机上使用Appium的话,你必须先开发Safari。 然后设置如下显示的这些信息以便于在设备中的Safari执行测试: + ```js { app: 'safari' @@ -40,6 +46,7 @@ * 第六步: 寻找并牢记你的UUID 现在你有了自己的profile文件,可以在终端中输入如下的命令: + ```bash $ git clone https://github.com/appium/appium.git $ cd appium @@ -62,6 +69,7 @@ $ node /lib/server/main.js -U ##### Java 举例 + ```java //setup the web driver and launch the webview app. DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); diff --git a/docs/cn/mobile_methods.cn.md b/docs/cn/mobile_methods.cn.md index ed634b3c0..c306d152c 100644 --- a/docs/cn/mobile_methods.cn.md +++ b/docs/cn/mobile_methods.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 跨平台的移动测试方法 +--- + #### 跨平台的移动测试方法 ##### 移动测试的重置方法reset @@ -5,6 +10,7 @@ reset方法会重置待测应用的状态 Ruby + [appium_lib gem](https://github.com/appium/ruby_lib) + ```ruby mobile :reset ``` diff --git a/docs/cn/real-devices.cn.md b/docs/cn/real-devices.cn.md index 8a7faa2c5..25e333639 100644 --- a/docs/cn/real-devices.cn.md +++ b/docs/cn/real-devices.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Appium 在真机上 +--- + Appium在真机上 ====================== Appium已经初步支持真机测试。 @@ -28,6 +33,7 @@ Provisioning Profile ``` node . -U --app ``` + 这将会启动Appium并且开始在真机上测试应用。 疑问解答思路 diff --git a/docs/cn/running-on-linux.cn.md b/docs/cn/running-on-linux.cn.md index 9c2e38df0..33ecc6baf 100644 --- a/docs/cn/running-on-linux.cn.md +++ b/docs/cn/running-on-linux.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 在 Linux 上运行 Appium +--- + 在 Linux 上运行 Appium ======================= diff --git a/docs/cn/running-on-osx.cn.md b/docs/cn/running-on-osx.cn.md index 6466b58db..141bc7490 100644 --- a/docs/cn/running-on-osx.cn.md +++ b/docs/cn/running-on-osx.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 在 Mac OS X 上使用 Appium +--- + 在 Mac OS X 上使用 Appium ======= diff --git a/docs/cn/running-on-windows.cn.md b/docs/cn/running-on-windows.cn.md index 86ff46cd9..0145f4476 100644 --- a/docs/cn/running-on-windows.cn.md +++ b/docs/cn/running-on-windows.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 在windows上运行appium +--- + 在windows上运行appium ======================= diff --git a/docs/cn/running-tests.cn.md b/docs/cn/running-tests.cn.md index 44808b407..16346b6ea 100644 --- a/docs/cn/running-tests.cn.md +++ b/docs/cn/running-tests.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 執行測試 +--- + 執行測試 ============= diff --git a/docs/cn/server-args.cn.md b/docs/cn/server-args.cn.md index 8c93b6d67..674196eba 100644 --- a/docs/cn/server-args.cn.md +++ b/docs/cn/server-args.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Appium 服务器参数 +--- + Appium 服务器参数 ========== diff --git a/docs/cn/touch-actions.cn.md b/docs/cn/touch-actions.cn.md index c81fa201d..288e88b2c 100644 --- a/docs/cn/touch-actions.cn.md +++ b/docs/cn/touch-actions.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: 触摸动作(touch actions) +--- + # 触摸动作(touch actions) @@ -14,6 +19,7 @@ new TouchActions(driver).longPress(imageView).perform(); Android 应用: Java: + ```java WebElement element = wd.findElement(By.name("API Demo")); JavascriptExecutor js = (JavascriptExecutor) wd; @@ -23,6 +29,7 @@ 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 }) diff --git a/docs/cn/troubleshooting.cn.md b/docs/cn/troubleshooting.cn.md index 3817fa39b..4c3efb826 100644 --- a/docs/cn/troubleshooting.cn.md +++ b/docs/cn/troubleshooting.cn.md @@ -1,3 +1,8 @@ +--- +layout: default +title: Appium 故障调试 +--- + Appium 故障调试 ====================== diff --git a/docs/android-hax-emulator.md b/docs/en/android-hax-emulator.md similarity index 52% rename from docs/android-hax-emulator.md rename to docs/en/android-hax-emulator.md index 1243212d4..2546a377d 100644 --- a/docs/android-hax-emulator.md +++ b/docs/en/android-hax-emulator.md @@ -1,11 +1,17 @@ +--- +title: Intel Hardware Accelerated Execution Manager +layout: default +--- + # Intel® Hardware Accelerated Execution Manager -If you find the android emulator a slow and your system runs on an Intel® cpu, you can check out HAXM. HAXM let's you leverage your hardware for virtualization accelerating the emulator. +If you find the android emulator a slow and your system runs on an Intel® +cpu, you can check out HAXM. HAXM let's you leverage your hardware for +virtualization accelerating the emulator. * To install HAXM open the Android SDK Manager, you will find the package under Extras. -* You can find all relevent documentation on [Intel's website][1] +* You can find all relevant documentation on [Intel's website][1] * This will require an x86 emulator image * Use Intel's package to install HAXM; The Android SDK Manager appears to not do so successfully. -[1]: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/ "Hax" -[2]: http://software.intel.com/en-us/search/site/language/en?query=Intel%20Hardware%20Accelerated%20Execution%20Manager%20%28HAXM%29 "Hax all" +[1]: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/ \ No newline at end of file diff --git a/docs/android_coverage.md b/docs/en/android_coverage.md similarity index 85% rename from docs/android_coverage.md rename to docs/en/android_coverage.md index 9cd579b5f..e507b95f7 100644 --- a/docs/android_coverage.md +++ b/docs/en/android_coverage.md @@ -1,14 +1,24 @@ -Android coverage requires the emulator or a rooted device. Build your app using the instrument target, for example `$ ant instrument` +--- +title: Android coverage +layout: default +--- -Pass `androidCoverage` to your device capabilities and set it to your instrumentation class. +Android coverage requires the emulator or a rooted device. Build your app +using the instrument target, for example `$ ant instrument` + +Pass `androidCoverage` to your device capabilities and set it to your +instrumentation class. ```ruby caps = { androidCoverage: 'com.example.pkg/com.example.pkg.instrumentation.MyInstrumentation' } ``` -Appium will start your app like this: `adb shell am instrument -e coverage true -w com.example.pkg/com.example.pkg.instrumentation.MyInstrumentation` +Appium will start your app like this: -After your test completes, it's time to end the coverage collection and pull the coverage.ec file from the device. +`adb shell am instrument -e coverage true -w com.example.pkg/com.example.pkg.instrumentation.MyInstrumentation` + +After your test completes, it's time to end the coverage collection and pull +the coverage.ec file from the device. ```ruby mobile :endCoverage, intent: 'com.example.pkg.END_EMMA', path: '/mnt/sdcard/coverage.ec' @@ -101,6 +111,9 @@ public class MyInstrumentation extends Instrumentation { #### Reports -`ant instrument` generates a `coverage.em` file. The `mobile :endCoverage` will download the coverage.ec file for that particular run. Note that you can have any number of coverage.ec files. To merge them all together into a report, use this command: +`ant instrument` generates a `coverage.em` file. The `mobile :endCoverage` +will download the coverage.ec file for that particular run. Note that you can + have any number of coverage.ec files. To merge them all together into a + report, use this command: > java -cp /path/to/android-sdk-macosx/tools/lib/emma_device.jar emma report -r html -in coverage.em,coverage0.ec,coverage1.ec -sp /path/to/your-app/src diff --git a/docs/caps.md b/docs/en/caps.md similarity index 98% rename from docs/caps.md rename to docs/en/caps.md index cbf95c41d..7c0b19396 100644 --- a/docs/caps.md +++ b/docs/en/caps.md @@ -1,3 +1,8 @@ +--- +title: Appium server capabilities +layout: default +--- + Appium server capabilities ========== diff --git a/docs/credits.md b/docs/en/credits.md similarity index 94% rename from docs/credits.md rename to docs/en/credits.md index 1e1cd8fb1..f113ee466 100644 --- a/docs/credits.md +++ b/docs/en/credits.md @@ -1,3 +1,8 @@ +--- +title: Credits +layout: default +--- + Credits ======= diff --git a/docs/finding-elements.md b/docs/en/finding-elements.md similarity index 76% rename from docs/finding-elements.md rename to docs/en/finding-elements.md index b17e184bf..7a1b85c69 100644 --- a/docs/finding-elements.md +++ b/docs/en/finding-elements.md @@ -1,29 +1,42 @@ +--- +title: Finding and interacting with elements +layout: default +--- + Finding and interacting with elements ===================================== 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 "xpath" (i.e., an abstract representation of a path to an element, with certain constraints) +* 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 "xpath" (i.e., an abstract representation of a path to an element, +with certain constraints) Appium additionally supports some of the [Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) locator strategies -* `-ios uiautomation`: a string corresponding to a recursive element search using the UIAutomation library (iOS-only) -* `-android uiautomator`: a string corresponding to a recursive element 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. +* `-ios uiautomation`: a string corresponding to a recursive element search +using the UIAutomation library (iOS-only) +* `-android uiautomator`: a string corresponding to a recursive element +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: +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 +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 -------- @@ -79,6 +92,7 @@ Ruby: ```ruby @driver.find_element(:name, 'Go').click ``` + Python: ```python @@ -143,7 +157,8 @@ driver.element('-android uiautomator', 'new UiSelector().clickable(true)').getAt # FindAndAct If you want, you can find and act on an element in a single command (iOS-only). -For example, you can find and click on an element in one call to Appium, using a special `mobile: findAndAct` command. +For example, you can find and click on an element in one call to Appium, +using a special `mobile: findAndAct` command. Python: @@ -167,20 +182,29 @@ Note: driver.execute_script() is explained in [Automating Mobile Gestures: Alter Using The Appium Inspector To Locate Elements -------- -Appium provides you with a neat tool that allows you to find the the elements you're looking for without leaving the Appium app. With the Appium Inspector (the i symbol next to the start test button) you can find any element and it's name by either clicking the element on the preview page provided, or locating it in the UI navigator. +Appium provides you with a neat tool that allows you to find the the elements +you're looking for without leaving the Appium app. With the Appium Inspector +(the i symbol next to the start test button) you can find any element and +it's name by either clicking the element on the preview page provided, +or locating it in the UI navigator. ### Overview -The Appium inspector has a simple layout, complete with a UI navigator, a preview, and record and refresh buttons, and interaction tools. +The Appium inspector has a simple layout, complete with a UI navigator, +a preview, and record and refresh buttons, and interaction tools. ![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Overview.png) ### Example -After launching the Appium Inspector (you can do this by clicking the small "i" button in the top right of the app) you can locate any element in the preview. In this test, I'm looking for the id of the "show alert" button. +After launching the Appium Inspector (you can do this by clicking the small +"i" button in the top right of the app) you can locate any element in the +preview. In this test, I'm looking for the id of the "show alert" button. ![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Step1.png) -To find the id of this button, I click the "show alert" button in the inspector preview. The Appium inspector then highlights the element in the UI navigator, showing me both the id and element type of the button I clicked. +To find the id of this button, I click the "show alert" button in the +inspector preview. The Appium inspector then highlights the element in the UI +navigator, showing me both the id and element type of the button I clicked. -![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Step2.png) +![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Step2.png) \ No newline at end of file diff --git a/docs/en/gestures.md b/docs/en/gestures.md new file mode 100644 index 000000000..10beeeb96 --- /dev/null +++ b/docs/en/gestures.md @@ -0,0 +1,375 @@ +--- +title: Automating mobile gestures +layout: default +--- + +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 tapObject = new HashMap(); +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 tapObject = new HashMap(); +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 coords = new Dictionary(); +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 flickObject = new HashMap(); +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 swipeObject = new HashMap(); +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 scrollObject = new HashMap(); +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 scrollToObject = new HashMap(); +scrollToObject.put("element",((RemoteWebElement) element).getId()); +js.executeScript("mobile: scrollTo", scrollToObject); +``` + +### longTap + + * **c#** + +```c# +// long tap an element +// +Dictionary parameters = new Dictionary(); +parameters.Add("using", _attributeType); +parameters.Add("value", _attribute); +Response response = rm.executescript(DriverCommand.FindElement, parameters); +Dictionary elementDictionary = response.Value as Dictionary; +string id = null; +if (elementDictionary != null) +{ + id = (string)elementDictionary["ELEMENT"]; +} +IJavaScriptExecutor js = (IJavaScriptExecutor)remoteDriver; +Dictionary longTapObject = new Dictionary(); +longTapObject.Add("element", id); +js.ExecuteScript("mobile: longClick", longTapObject); +``` \ No newline at end of file diff --git a/docs/grid.md b/docs/en/grid.md similarity index 65% rename from docs/grid.md rename to docs/en/grid.md index 518ccb982..84f42d26d 100644 --- a/docs/grid.md +++ b/docs/en/grid.md @@ -1,15 +1,27 @@ +--- +title: Selenium Grid +layout: default +--- + Selenium Grid ====================== -You are able to register your appium server with a local grid by using the "--nodeconfig" server parameter. +You are able to register your appium server with a local grid by using the +"--nodeconfig" server parameter. ```bash > node . -V --nodeconfig /path/to/nodeconfig.json ``` -In the node config file you have to define the "browserName", "version" and "platform" and based on these parameters the grid will re-direct your test to the right device. You will also need to configure you host details and the selenium grid details. For a full list of all parameters and descriptions look here. +In the node config file you have to define the "browserName", +"version" and "platform" and based on these parameters the grid + will re-direct your test to the right device. You will also need to + configure you host details and the selenium grid details. For + a full list of all parameters and descriptions look + [here](http://code.google.com/p/selenium/source/browse/java/server/src/org/openqa/grid/common/defaults/GridParameters.properties) -Once you start the appium server and it registers with the grid, you will see your device on the grid console page: +Once you start the appium server and it registers with the grid, +you will see your device on the grid console page: "http://\:\/grid/console" @@ -43,6 +55,6 @@ Once you start the appium server and it registers with the grid, you will see yo } ``` -Valid platforms are listed here +Valid platforms are listed [here](http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/Platform.html) -If `url`, `host`, and `port` are not given, the config will be auto updated to point to localhost:whatever-port-Appium-started-on. +If `url`, `host`, and `port` are not given, the config will be auto updated to point to localhost:whatever-port-Appium-started-on. \ No newline at end of file diff --git a/docs/grunt.md b/docs/en/grunt.md similarity index 94% rename from docs/grunt.md rename to docs/en/grunt.md index 72c6b0feb..6f052e334 100644 --- a/docs/grunt.md +++ b/docs/en/grunt.md @@ -1,3 +1,8 @@ +--- +title: Appium grunt commands +layout: default +--- + Appium grunt commands ============= @@ -30,5 +35,4 @@ By default, `grunt buildApp` builds apps using the iPhone 6.1 simulator SDK. You can overwrite the simulator by passing another SDK to grunt (to figure out which SDKs you have available, try `xcodebuild -showsdks`: - > grunt buildApp:UICatalog:iphonesimulator6.0 - + > grunt buildApp:UICatalog:iphonesimulator6.0 \ No newline at end of file diff --git a/docs/hybrid.md b/docs/en/hybrid.md similarity index 51% rename from docs/hybrid.md rename to docs/en/hybrid.md index 45ec5b64d..05bed7574 100644 --- a/docs/hybrid.md +++ b/docs/en/hybrid.md @@ -1,7 +1,18 @@ +--- +title: Automating hybrid apps +layout: default +--- + Automating hybrid apps ====================== -One of the core principles of Appium is that you shouldn't have to change your app to test it. In line with that methodology, it is possible to test hybrid web apps (e.g., the "UIWebView" elements in an iOS app) the same* way you can with Selenium for web apps. There is a bit of technical complexity required so that Appium knows whether you want to automate the native aspects of the app or the web views, but thankfully, we can stay within the WebDriver protocol for everything. +One of the core principles of Appium is that you shouldn't have to change +your app to test it. In line with that methodology, it is possible to test +hybrid web apps (e.g., the "UIWebView" elements in an iOS app) the same* way +you can with Selenium for web apps. There is a bit of technical complexity +required so that Appium knows whether you want to automate the native aspects + of the app or the web views, but thankfully, we can stay within the + WebDriver protocol for everything. * [Hybrid iOS apps](#ios) * [Hybrid Android apps](#android) @@ -14,14 +25,31 @@ Here are the steps required to talk to a web view in your Appium test: 1. Navigate to a portion of your app where a web view is active 1. Call [GET session/:sessionId/window_handles](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window_handles) 1. This returns a list of web view ids we can access -1. Call [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window) with the id of the web view you want to access -1. (This puts your Appium session into a mode where all commands are interpreted as being intended for automating the web view, rather than the native portion of the app. For example, if you run getElementByTagName, it will operate on the DOM of the web view, rather than return UIAElements. Of course, certain WebDriver methods only make sense in one context or another, so in the wrong context you will receive an error message). -1. To stop automating in the web view context and go back to automating the native portion of the app, simply call `"mobile: leaveWebView"` with execute_script to leave the web frame. +1. Call [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window) +with the id of the web view you want to access +1. (This puts your Appium session into a mode where all commands are +interpreted as being intended for automating the web view, +rather than the native portion of the app. For example, +if you run getElementByTagName, it will operate on the DOM of the web view, +rather than return UIAElements. Of course, certain WebDriver methods only +make sense in one context or another, so in the wrong context you will +receive an error message). +1. To stop automating in the web view context and go back to automating the +native portion of the app, simply call `"mobile: leaveWebView"` with +execute_script to leave the web frame. ## Execution against a real iOS device -To interrogate and interact with a web view appium establishes a connection using a remote debugger. When executing the examples below against a simulator this connection can be established directly as the simulator and the appium server are on the same machine. When executing against a real device appium is unable to access the web view directly. Therefore the connection has to be established through the USB lead. To establish this connection we use the [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy). +To interrogate and interact with a web view appium establishes a connection +using a remote debugger. When executing the examples below against a +simulator this connection can be established directly as the simulator and +the appium server are on the same machine. When executing against a real +device appium is unable to access the web view directly. Therefore the +connection has to be established through the USB lead. To establish this +connection we use the [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy). + +To install the latest tagged version of the ios-webkit-debug-proxy using +brew, run the following commands in the terminal: -To install the latest tagged version of the ios-webkit-debug-proxy using brew, run the following commands in the terminal: ``` bash # The first command is only required if you don't have brew installed. > ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)" @@ -29,7 +57,9 @@ To install the latest tagged version of the ios-webkit-debug-proxy using brew, r > brew install ios-webkit-debug-proxy ``` -You can also install the latest proxy by cloning it from git and installing it yourself: +You can also install the latest proxy by cloning it from git and installing +it yourself: + ``` bash # Please be aware that this will install the proxy with the latest code (and not a tagged version). > git clone https://github.com/google/ios-webkit-debug-proxy.git @@ -41,6 +71,7 @@ You can also install the latest proxy by cloning it from git and installing it y ``` Once installed you can start the proxy with the following command: + ``` bash # Change the udid to be the udid of the attached device and make sure to set the port to 27753 # as that is the port the remote-debugger uses. @@ -79,28 +110,28 @@ Once installed you can start the proxy with the following command: ## Wd.java Code example ```java - //setup the web driver and launch the webview app. - DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); - desiredCapabilities.setCapability("device", "iPhone Simulator"); - desiredCapabilities.setCapability("app", "http://appium.s3.amazonaws.com/WebViewApp6.0.app.zip"); - URL url = new URL("http://127.0.0.1:4723/wd/hub"); - RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities); - - //switch to the latest web view - for(String winHandle : remoteWebDriver.getWindowHandles()){ - remoteWebDriver.switchTo().window(winHandle); - } - - //Interact with the elements on the guinea-pig page using id. - WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id")); - Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value - remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id. - - //leave the webview to go back to native app. - remoteWebDriver.executeScript("mobile: leaveWebView"); - - //close the app. - remoteWebDriver.quit(); +//setup the web driver and launch the webview app. +DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); +desiredCapabilities.setCapability("device", "iPhone Simulator"); +desiredCapabilities.setCapability("app", "http://appium.s3.amazonaws.com/WebViewApp6.0.app.zip"); +URL url = new URL("http://127.0.0.1:4723/wd/hub"); +RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities); + +//switch to the latest web view +for(String winHandle : remoteWebDriver.getWindowHandles()){ +remoteWebDriver.switchTo().window(winHandle); +} + +//Interact with the elements on the guinea-pig page using id. +WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id")); +Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value +remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id. + +//leave the webview to go back to native app. +remoteWebDriver.executeScript("mobile: leaveWebView"); + +//close the app. +remoteWebDriver.quit(); ``` ## Wd.rb Code example using cucumber @@ -119,9 +150,11 @@ capabilities = } @driver = Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => SERVER_URL) -## I switch to the last window because its always the webview in our case, in other cases you may need to specify a window number -## View the appium logs while running @driver.window_handles to figure out which window is the one you want and find the associated number -## Then switch to it using @driver.switch_to_window("6") +# I switch to the last window because its always the webview in our case, +# in other cases you may need to specify a window number +# View the appium logs while running @driver.window_handles to figure out +# which window is the one you want and find the associated number +# Then switch to it using @driver.switch_to_window("6") Given(/^I switch to webview$/) do webview = @driver.window_handles.last @@ -138,21 +171,41 @@ And(/^I click a webview button $/) do @driver.find_element(:css, ".green_button").click end ``` + #### Troubleshooting Webview with Ruby: -I created a quick function in my helper class to find web elements no matter what window its in (this is useful if your webview id changes or if you are using the same codebase to test android and ios) -https://gist.github.com/feelobot/7309729 + +I created a quick function in [my helper class](https://gist.github.com/feelobot/7309729) +to find web elements no matter what window its in (this is useful if your +webview id changes or if you are using the same codebase to test android and +ios) + Automating hybrid Android apps -------------------------- -Appium comes with built-in hybrid support via Chromedriver. Appium also uses Selendroid under the hood for webview support on devices older than 4.4. (In that case, you'll want to specify `"device": "selendroid"` as a desired capability). Then: +Appium comes with built-in hybrid support via Chromedriver. Appium also uses +Selendroid under the hood for webview support on devices older than 4.4. (In +that case, you'll want to specify `"device": "selendroid"` as a desired +capability). Then: 1. Navigate to a portion of your app where a web view is active -1. Call [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window) with the string "WEBVIEW" as the window handle, e.g., `driver.window("WEBVIEW")`. -1. (This puts your Appium session into a mode where all commands are interpreted as being intended for automating the web view, rather than the native portion of the app. For example, if you run getElementByTagName, it will operate on the DOM of the web view, rather than return UIAElements. Of course, certain WebDriver methods only make sense in one context or another, so in the wrong context you will receive an error message). -1. To stop automating in the web view context and go back to automating the native portion of the app, simply call `window` again with the string "NATIVE_APP", e.g., `driver.window("NATIVE_APP")`. +1. Call [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window) +with the string "WEBVIEW" as the window handle, e.g., `driver.window("WEBVIEW")`. +1. (This puts your Appium session into a mode where all commands are +interpreted as being intended for automating the web view, +rather than the native portion of the app. For example, +if you run getElementByTagName, it will operate on the DOM of the web view, +rather than return UIAElements. Of course, certain WebDriver methods only +make sense in one context or another, so in the wrong context you will +receive an error message). +1. To stop automating in the web view context and go back to automating the +native portion of the app, simply call `window` again with the string +"NATIVE_APP", e.g., `driver.window("NATIVE_APP")`. -Note: We could have used the same strategy as above for leaving the webview (calling `mobile: leaveWebView`), however Selendroid uses the `WEBVIEW`/`NATIVE_APP` window setting strategy, which also works with regular Appium hybrid support, so we show that here for parity. +Note: We could have used the same strategy as above for leaving the webview +(calling `mobile: leaveWebView`), however Selendroid uses the +`WEBVIEW`/`NATIVE_APP` window setting strategy, which also works with regular + Appium hybrid support, so we show that here for parity. ## Wd.js Code example @@ -175,24 +228,24 @@ driver.window("WEBVIEW", function(err) { // choose the only available view ## Wd.java Code example ```java - //setup the web driver and launch the webview app. - DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); - desiredCapabilities.setCapability("device", "Selendroid"); - desiredCapabilities.setCapability("app", "/path/to/some.apk"); - URL url = new URL("http://127.0.0.1:4723/wd/hub"); - RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities); - - //switch to the web view - remoteWebDriver.switchTo().window("WEBVIEW"); - - //Interact with the elements on the guinea-pig page using id. - WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id")); - Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value - remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id. - - //leave the webview to go back to native app. - remoteWebDriver.switchTo().window("NATIVE_APP"); - - //close the app. - remoteWebDriver.quit(); -``` +//setup the web driver and launch the webview app. +DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); +desiredCapabilities.setCapability("device", "Selendroid"); +desiredCapabilities.setCapability("app", "/path/to/some.apk"); +URL url = new URL("http://127.0.0.1:4723/wd/hub"); +RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities); + +//switch to the web view +remoteWebDriver.switchTo().window("WEBVIEW"); + +//Interact with the elements on the guinea-pig page using id. +WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id")); +Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value +remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id. + +//leave the webview to go back to native app. +remoteWebDriver.switchTo().window("NATIVE_APP"); + +//close the app. +remoteWebDriver.quit(); +``` \ No newline at end of file diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 000000000..899850c13 --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,9 @@ +--- +layout: default +title: Documentation +description: Appium v0.18.0 English Documentation +--- + +- Documentation + +{% include doc_list.md url="/docs/en/0.18.0" %} \ No newline at end of file diff --git a/docs/ios-deploy.md b/docs/en/ios-deploy.md similarity index 71% rename from docs/ios-deploy.md rename to docs/en/ios-deploy.md index f55e0cf6e..a57bf0df7 100644 --- a/docs/ios-deploy.md +++ b/docs/en/ios-deploy.md @@ -1,9 +1,15 @@ +--- +title: Deploying your iOS app to your device +layout: default +--- + Deploying your iOS app to your device ===================================== To prepare for your Appium tests to run on a real device, you will need to: 1. Build your app with specific device-targeted parameters -1. Use [fruitstrap](https://github.com/ghughes/fruitstrap), a 3rd-party tool, to deploy this build to your device +1. Use [fruitstrap](https://github.com/ghughes/fruitstrap), a 3rd-party tool, + to deploy this build to your device ## Xcodebuild with parameters: A newer xcodebuild now allows settings to be specified. Taken from [developer.apple.com](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html): @@ -29,23 +35,39 @@ Specify "CODE_SIGN_IDENTITY" & "PROVISIONING_PROFILE" settings in the xcodebuild ``` xcodebuild -sdk -target -configuration CODE_SIGN_IDENTITY="iPhone Developer: Mister Smith" PROVISIONING_PROFILE="XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX" ``` + On success, the app will be built to your ```/build/-iphoneos/.app``` ## Deploy using Fruitstrap -Go clone a forked version of fruitstrap as the [ghughes version](https://github.com/ghughes/fruitstrap) is no longer maintained. Success has been confirmed with the [unprompted fork](https://github.com/unprompted/fruitstrap), but others are reportedly functional. -Once cloned, run ``make fruitstrap`` -Now, copy the resulting ``fruitstrap`` executable to your app's project or a parent directory. +Go clone a forked version of fruitstrap as the [ghughes version](https://github.com/ghughes/fruitstrap) +is no longer maintained. Success has been confirmed with the [unprompted fork](https://github.com/unprompted/fruitstrap), +but others are reportedly functional. + +Once cloned, run `make fruitstrap` +Now, copy the resulting `fruitstrap` executable to your app's project or a +parent directory. + +Execute fruitstrap after a clean build by running (commands available depend +on your fork of fruitstrap): -Execute fruitstrap after a clean build by running (commands available depend on your fork of fruitstrap): ``` ./fruitstrap -d -b -i ``` -If you are aiming to use continuous integration in this setup, you may find it useful to want to log the output of fruitstrap to both command line and log, like so: + +If you are aiming to use continuous integration in this setup, +you may find it useful to want to log the output of fruitstrap to both +command line and log, like so: + ``` ./fruitstrap -d -b -i 2>&1 | tee fruit.out ``` -Since fruitstrap will need to be killed before the node server can be launched, an option is to scan the output of the fruitstrap launch for some telling sign that the app has completed launching. This may prove useful if you are doing this via a Rakefile and a ``go_device.sh`` script: + +Since fruitstrap will need to be killed before the node server can be +launched, an option is to scan the output of the fruitstrap launch for some +telling sign that the app has completed launching. This may prove useful if +you are doing this via a Rakefile and a ``go_device.sh`` script: + ``` bundle exec rake ci:fruit_deploy_app | while read line ; do echo "$line" | grep "text to identify successful launch" @@ -58,7 +80,8 @@ bundle exec rake ci:fruit_deploy_app | while read line ; do fi done ``` + Once fruitstrap is killed, node server can be launched and Appium tests can run! Next: -[Running Appium on Real Devices](https://github.com/appium/appium/wiki/Running-Appium-on-Real-Devices) +[Running Appium on Real Devices](./real-devices.html) \ No newline at end of file diff --git a/docs/mobile-web.md b/docs/en/mobile-web.md similarity index 83% rename from docs/mobile-web.md rename to docs/en/mobile-web.md index 0232422f5..35d59dbaa 100644 --- a/docs/mobile-web.md +++ b/docs/en/mobile-web.md @@ -1,13 +1,23 @@ +--- +title: Automating mobile web apps +layout: default +--- + Automating mobile web apps ====================== -If you're interested in automating your web app in Mobile Safari on iOS or Chrome on Android, Appium can help you. Basically, you write a normal WebDriver test, and use Appium as the Selenium server with a special set of desired capabilities. +If you're interested in automating your web app in Mobile Safari on iOS or +Chrome on Android, Appium can help you. Basically, you write a normal WebDriver +test, and use Appium as the Selenium server with a special set of desired +capabilities. ### Mobile Safari on Simulator -First of all, make sure developer mode is turned on in your Safari preferences so that the remote debugger port is open. +First of all, make sure developer mode is turned on in your Safari +preferences so that the remote debugger port is open. -If you are using the simulator or a real device, you MUST run Safari before attempting to use Appium. +If you are using the simulator or a real device, you MUST run Safari before +attempting to use Appium. Then, use desired capabilities like these to run your test in mobile Safari: @@ -21,15 +31,22 @@ Then, use desired capabilities like these to run your test in mobile Safari: ### Mobile Safari on a Real iOS Device -To be able to run your tests against mobile Safari we use the [SafariLauncher App](https://github.com/snevesbarros/SafariLauncher) to launch Safari. Once Safari has been launched the Remote Debugger automatically connects using the [ios-webkit-webkit-proxy](https://github.com/google/ios-webkit-debug-proxy). +To be able to run your tests against mobile Safari we use the [SafariLauncher + App](https://github.com/snevesbarros/SafariLauncher) to launch Safari. Once + Safari has been launched the Remote Debugger automatically connects using + the [ios-webkit-webkit-proxy](https://github.com/google/ios-webkit-debug-proxy). -NOTE: There is currently [a bug](https://github.com/google/ios-webkit-debug-proxy/issues/38) in the ios-webkit-debug-proxy. You have to trust the machine before you can run the ios-webkit-debug-proxy against your iOS device. +NOTE: There is currently [a bug](https://github +.com/google/ios-webkit-debug-proxy/issues/38) in the ios-webkit-debug-proxy. +You have to trust the machine before you can run the ios-webkit-debug-proxy +against your iOS device. #### Setup Before you can run your tests against Safari on a real device you will need to: * Have the ios-webkit-debug-proxy installed and running (see the [hybrid docs](https://github.com/appium/appium/blob/master/docs/hybrid.md) for instructions) -* Turn on web inspector on iOS device (settings > safari > advanced, only for iOS 6.0 and up) +* Turn on web inspector on iOS device (settings > safari > +advanced, only for iOS 6.0 and up) * Create a provisioning profile that can be used to deploy the SafariLauncherApp. To create a profile for the launcher go into the Apple Developers Member Center and: @@ -41,6 +58,7 @@ To create a profile for the launcher go into the Apple Developers Member Cent * Step 6: Search for the UUID and the string for it is your identity code. Now that you have a profile open a terminal and run the following commands: + ```bash $ git clone https://github.com/appium/appium.git $ cd appium @@ -59,9 +77,11 @@ $ node /lib/server/main.js -U ``` #### Running your test + To configure you test to run against safari simpley set the "app" to be "safari". ##### Java Example + ```java //setup the web driver and launch the webview app. DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); @@ -93,4 +113,4 @@ Then, use desired capabilities like these to run your test in Chrome: app: 'chrome' , device: 'Android' }; -``` +``` \ No newline at end of file diff --git a/docs/mobile_methods.md b/docs/en/mobile_methods.md similarity index 80% rename from docs/mobile_methods.md rename to docs/en/mobile_methods.md index 3eb4ba9b0..9cf939d28 100644 --- a/docs/mobile_methods.md +++ b/docs/en/mobile_methods.md @@ -1,3 +1,8 @@ +--- +title: Cross platform mobile methods +layout: default +--- + #### Cross platform mobile methods ##### Reset @@ -5,11 +10,13 @@ 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' ``` @@ -20,15 +27,16 @@ 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 -'mobile: pullFile', {path: '/Library/AddressBook/AddressBook.sqlitedb'} #=> /Library/AddressBook/AddressBook.sqlitedb +@driver.execute_script 'mobile: pullFile', {path: '/Library/AddressBook/AddressBook.sqlitedb'} #=> /Library/AddressBook/AddressBook.sqlitedb #iOS only -'mobile: pullFile, {path: '/UICatalog.app/logfile.log'} #=> /Applications/12323-452262-24241-23-124124/UICatalog.app/logfile.log +@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'}) ``` @@ -54,6 +62,7 @@ mobile :keyevent, keycode: 82 ``` Ruby without the gem + ```ruby @driver.execute_script 'mobile: keyevent', :keycode => 82 ``` @@ -68,4 +77,4 @@ Ruby + [appium_lib gem](https://github.com/appium/ruby_lib) ```ruby scroll_to 'Gallery' -``` +``` \ No newline at end of file diff --git a/docs/real-devices.md b/docs/en/real-devices.md similarity index 97% rename from docs/real-devices.md rename to docs/en/real-devices.md index f9eeb3833..169a43434 100644 --- a/docs/real-devices.md +++ b/docs/en/real-devices.md @@ -1,3 +1,8 @@ +--- +title: Appium on real devices +layout: default +--- + Appium on real iOS devices ====================== Appium has support for real device testing. diff --git a/docs/running-on-linux.md b/docs/en/running-on-linux.md similarity index 52% rename from docs/running-on-linux.md rename to docs/en/running-on-linux.md index 8e1ee73f0..7259a238e 100644 --- a/docs/running-on-linux.md +++ b/docs/en/running-on-linux.md @@ -1,17 +1,29 @@ +--- +title: Running Appium on Linux +layout: default +--- + Running Appium on Linux ======================= # Limitations -If you are running Appium on Linux, you cannot use the prebuilt '.app', which is built for OS X only. Additionally, you will not be able to test iOS apps because Appium relies on OS X-only libraries to support iOS testing. +If you are running Appium on Linux, you cannot use the prebuilt '.app', +which is built for OS X only. Additionally, you will not be able to test iOS +apps because Appium relies on OS X-only libraries to support iOS testing. # Setup -To get started, you'll need to install node.js (v.0.8 or greater). Just follow the [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager). +To get started, you'll need to install node.js (v.0.8 or greater). Just +follow the [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager). -Once you've got node.js installed, install the [Android SDK](http://developer.android.com/sdk/index.html). You will need to run the 'android' tool (included in the SDK) and make sure you have an API Level 17 or greater API installed. You will also need Ant to build the bootstrap jar that Appium uses for testing Android. +Once you've got node.js installed, install the [Android SDK](http://developer.android.com/sdk/index.html). +You will need to run the 'android' tool (included in the SDK) and make sure +you have an API Level 17 or greater API installed. You will also need Ant to +build the bootstrap jar that Appium uses for testing Android. -Finally, set `$ANDROID_HOME` to be your Android SDK path. If you unzipped the Android SDK to /usr/local/adt/, for example, you should add this to your shell startup: +Finally, set `$ANDROID_HOME` to be your Android SDK path. If you unzipped the +Android SDK to /usr/local/adt/, for example, you should add this to your shell startup: export ANDROID_HOME="/usr/local/adt/sdk" @@ -19,7 +31,8 @@ Now that you're setup to run Appium, run `./reset.sh --android` from your Appium # Running Appium -To run tests on Linux, you will need to have the Android Emulator booted and running an AVD with API Level 17 or greater. Then run Appium on the command line using node.js: +To run tests on Linux, you will need to have the Android Emulator booted and +running an AVD with API Level 17 or greater. Then run Appium on the command line using node.js: node . @@ -29,4 +42,4 @@ See the [server documentation](https://github.com/appium/appium/blob/master/docs * There exists a hardware accelerated emulator for android, it has it's own limitations. For more information you can check out this [page](https://github.com/appium/appium/blob/master/docs/android-hax-emulator.md). -* Make sure that `hw.battery=yes` in your AVD's `config.ini`. +* Make sure that `hw.battery=yes` in your AVD's `config.ini`. \ No newline at end of file diff --git a/docs/running-on-osx.md b/docs/en/running-on-osx.md similarity index 97% rename from docs/running-on-osx.md rename to docs/en/running-on-osx.md index 3dfcade94..a687c737e 100644 --- a/docs/running-on-osx.md +++ b/docs/en/running-on-osx.md @@ -1,4 +1,9 @@ -Running Appium on Mac OS X +--- +title: Running Appium on Mac OS X +layout: default +--- + +Running Appium on Mac OS X ======= Appium on OS X supports iOS and Android testing. diff --git a/docs/en/running-on-windows.md b/docs/en/running-on-windows.md new file mode 100644 index 000000000..e19e97b2c --- /dev/null +++ b/docs/en/running-on-windows.md @@ -0,0 +1,60 @@ +--- +title: Running Appium on Windows +layout: default +--- + +Running Appium on Windows +======================= + +# Limitations + +If you are running Appium on Windows, you cannot use the prebuilt '.app', +which is built for OS X only. Additionally, you will not be able to test iOS +apps because Appium relies on OS X-only libraries to support iOS testing. + +# Setup + +To get started: + +1. Install [node.js](http://nodejs.org/download/) (v.0.8 or greater). Use the + installer from nodejs.org. +1. Install the [Android SDK](http://developer.android.com/sdk/index.html). + You will need to run the 'android' tool (included in the SDK) and make sure + you have an API Level 17 or greater API installed. Set `ANDROID_HOME` to be + your Android SDK path and add the tools and platform-tools folders to your + PATH variable. +1. Install the Java JDK and set `JAVA_HOME` to your JDK folder. +1. Install [Apache Ant](http://ant.apache.org/bindownload.cgi) or use the one + that comes with the Android Windows SDK in the eclipse\plugins folder. Be + sure to add the folder containing ant to your PATH variable. +1. Install [Apache Maven](http://maven.apache.org/download.cgi) and set the + M2HOME and M2 environment variables. Set M2HOME to the directory maven is + installed in, and set M2 to %M2HOME\bin. Add the path you used for M2 to + your PATH. +1. Install [Git](http://git-scm.com/download/win) Be sure to install Git for + windows to run in the regular command prompt. +1. Instal [cURL](http://curl.haxx.se/download.html) + +Now that you've downloaded everything, run: + + reset.bat + +# Running Appium + +To run tests on Windows, you will need to have the Android Emulator booted or + an Android Device connected that is running an AVD with API Level 17 or + greater. Then run Appium on the command line using node.js: + + node . + +See the [server documentation](https://github.com/appium/appium/blob/master/docs/server-args.md) +for all the command line arguments. + +# Notes + +* you must supply the --no-reset and --full-reset flags currently for android + to work on Windows. +* There exists a hardware accelerated emulator for android, it has it's own + limitations. For more information you can check out this + [page](https://github.com/appium/appium/blob/master/docs/android-hax-emulator.md). +* Make sure that `hw.battery=yes` in your AVD's `config.ini`. diff --git a/docs/running-tests.md b/docs/en/running-tests.md similarity index 92% rename from docs/running-tests.md rename to docs/en/running-tests.md index 376bd690e..65ef6d95e 100644 --- a/docs/running-tests.md +++ b/docs/en/running-tests.md @@ -1,8 +1,14 @@ +--- +title: Running Tests +layout: default +--- + Running Tests ============= Preparing your app for test (iOS) ----- + Test apps run on the simulator have to be compiled specifically for the simulator, for example by executing the following command in the Xcode project: @@ -17,11 +23,13 @@ unpack it for you. Nice if you're not using Appium locally. Preparing your app for test (Android) ------ + Nothing in particular needs to be done to run your .apk using Appium. If you want to zip it up, you can. Running your test app with Appium (iOS) ------ + The best way to see what to do currently is to look at the example tests: [Node.js](https://github.com/appium/appium/tree/master/sample-code/examples/node) | [Python](https://github.com/appium/appium/tree/master/sample-code/examples/python) | [PHP](https://github.com/appium/appium/tree/master/sample-code/examples/php) | [Ruby](https://github.com/appium/appium/tree/master/sample-code/examples/ruby) | [Java](https://github.com/appium/appium/tree/master/sample-code/examples/java) @@ -53,6 +61,7 @@ all set now! Running your test app with Appium (Android) ----- + First, make sure you have one and only one Android emulator or device connected. If you run `adb devices`, for example, you should see one device connected. This is the device Appium will use for tests. Of course, to have @@ -106,13 +115,13 @@ all set now! Running your test app with Appium (Android devices < 4.2, and hybrid tests) ----- + Android devices before version 4.2 (API Level 17) do not have Google's -[UiAutomator -framework](developer.android.com/tools/help/uiautomator/index.html) installed. -This is what Appium uses to perform the -automation behaviors on the device. For earlier devices or tests of hybrid -(webview-based) apps, Appium comes bundled with another automation backend -called [Selendroid](http://selendroid.io/). +[UiAutomator framework](developer.android.com/tools/help/uiautomator/index.html) +installed. This is what Appium uses to perform the automation behaviors on +the device. For earlier devices or tests of hybrid (webview-based) apps, +Appium comes bundled with another automation backend called [Selendroid] +(http://selendroid.io/). To use Selendroid, all that is required is to slightly change the set of desired capabilities mentioned above, by replacing 'Android' with 'Selendroid': diff --git a/docs/server-args.md b/docs/en/server-args.md similarity index 98% rename from docs/server-args.md rename to docs/en/server-args.md index 7ecf7f325..074b15d26 100644 --- a/docs/server-args.md +++ b/docs/en/server-args.md @@ -1,3 +1,8 @@ +--- +title: Appium server arguments +layout: default +--- + Appium server arguments ========== @@ -66,4 +71,4 @@ All flags are optional, but some are required in conjunction with certain others |`--key-password`|android|(Android-only) Key password|| |`--show-config`|false|Show info about the appium server configuration and exit|| |`--command-timeout`|60|The default command timeout for the server to use for all sessions. Will still be overridden by newCommandTimeout cap|| -|`--keep-keychains`|false|(iOS) Whether to keep keychains (Library/Keychains) when reset app between sessions|| +|`--keep-keychains`|false|(iOS) Whether to keep keychains (Library/Keychains) when reset app between sessions|| \ No newline at end of file diff --git a/docs/style-guide.md b/docs/en/style-guide.md similarity index 78% rename from docs/style-guide.md rename to docs/en/style-guide.md index 89d5ae7e7..5d0c4ebb0 100644 --- a/docs/style-guide.md +++ b/docs/en/style-guide.md @@ -1,19 +1,36 @@ +--- +title: Style guide for contributors +layout: default +--- + Style guide for contributors ============================ -Thanks for your contribution to Appium! Here are the principles we use when writing javascript. Please conform to these so we can merge your pull request without going back and forth about style. The main principle is: *make your code look like the surrounding code*. +Thanks for your contribution to Appium! Here are the principles we use when +writing javascript. Please conform to these so we can merge your pull request + without going back and forth about style. The main principle is: *make your + code look like the surrounding code*. Rebasing -------- -Commits in a pull request should consist of [logical changes](https://github.com/appium/appium/pull/920#issuecomment-21588553). If there are multiple authors, make sure each author has their own commit. It's not a good idea to modify author information. -Merge commits should be rebased out of pull requests. +Commits in a pull request should consist of [logical changes](https://github.com/appium/appium/pull/920#issuecomment-21588553). +If there are multiple authors, make sure each author has their own commit. +It's not a good idea to modify author information. Merge commits should be +rebased out of pull requests. Linting ------- -All code (except for code in `bootstrap.js` which uses proprietary Apple methods) must pass JSLint. To check your code, you can simply run `grunt lint` from the Appium repo dir. If you've created a new .js file, please make sure it is covered by the wildcards in `grunt.js` or that it is added specifically. +All code (except for code in `bootstrap.js` which uses proprietary Apple +methods) must pass JSLint. To check your code, you can simply run `grunt +lint` from the Appium repo dir. If you've created a new .js file, +please make sure it is covered by the wildcards in `grunt.js` or that it is +added specifically. -It's easy to have your code linted as you type, which makes the whole process much smoother. We like [jshint](http://www.jshint.com), which has integrations with a lot of source code editors. The file `.jshintrc` is checked into the repo, and its contents are: +It's easy to have your code linted as you type, which makes the whole process +much smoother. We like [jshint](http://www.jshint.com), +which has integrations with a lot of source code editors. The file ` +.jshintrc` is checked into the repo, and its contents are: ```json { @@ -29,7 +46,10 @@ It's easy to have your code linted as you type, which makes the whole process mu } ``` -These defined what we want to see warnings about, etc..., while we're editing. See [this page](http://www.jshint.com/platforms/) for the list of editors and platforms and how to get your editor set up with automatic linting. +These defined what we want to see warnings about, etc..., +while we're editing. See [this page](http://www.jshint.com/platforms/) for +the list of editors and platforms and how to get your editor set up with +automatic linting. Style notes ------ @@ -228,4 +248,4 @@ h.driver .execute("'nan'--") .should.be.rejectedWith("status: 13") .nodeify(done); -``` +``` \ No newline at end of file diff --git a/docs/touch-actions.md b/docs/en/touch-actions.md similarity index 91% rename from docs/touch-actions.md rename to docs/en/touch-actions.md index 622b4593d..a8abb2682 100644 --- a/docs/touch-actions.md +++ b/docs/en/touch-actions.md @@ -1,5 +1,9 @@ -# Touch Actions +--- +title: Touch Actions +layout: default +--- +# 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: @@ -14,6 +18,7 @@ new TouchActions(driver).longPress(imageView).perform(); For Android Application: Java: + ```java WebElement element = wd.findElement(By.name("API Demo")); JavascriptExecutor js = (JavascriptExecutor) wd; @@ -23,6 +28,7 @@ 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 }) @@ -35,6 +41,4 @@ Currently Appium support some of the gestures in the Touch Actions API: * single tap Some other gestures are supported through the "Alternative access method" -explained in [Automating mobile gestures](gestures.md) - - +explained in [Automating mobile gestures](gestures.md) \ No newline at end of file diff --git a/docs/troubleshooting.md b/docs/en/troubleshooting.md similarity index 61% rename from docs/troubleshooting.md rename to docs/en/troubleshooting.md index 690f1f240..7efe6f871 100644 --- a/docs/troubleshooting.md +++ b/docs/en/troubleshooting.md @@ -1,12 +1,20 @@ +--- +title: Troubleshooting Appium +layout: default +--- + Troubleshooting Appium ====================== + Here's what to do if you're experiencing problems, before you submit a ticket to github or write to the appium-discuss mailing list. ## General * Make sure you've followed the getting started steps in the [README](https://github.com/appium/appium/blob/master/README.md) -* Make sure your system is set up appropriately (i.e., XCode is updated, Android SDK is installed and `ANDROID_HOME` is set: [setup instructions](https://github.com/appium/appium/blob/master/docs/running-on-osx.md)) +* Make sure your system is set up appropriately (i.e., XCode is updated, + Android SDK is installed and `ANDROID_HOME` is set: + [setup instructions](https://github.com/appium/appium/blob/master/docs/running-on-osx.md)) * Make sure the paths to your applications are correct ## If you're running Appium.app @@ -17,42 +25,58 @@ to github or write to the appium-discuss mailing list. ## If you're running Appium from source * `git pull` to make sure you're running the latest code -* Run the appropriate flavor of `reset.sh` based on what you're trying to automate: +* Run the appropriate flavor of `reset.sh` based on what you're trying to +automate: ./reset.sh # all ./reset.sh --ios # ios-only ./reset.sh --android # android-only ./reset.sh --selendroid # selendroid-only -* You might also want to run `reset.sh` with the `--dev` flag if you want the test apps downloaded and built as well. -* You can also use `appium-doctor` to automatically verify that all dependencies are met. If running from source, you -may have to use `bin/appium-doctor.js` or `node bin/appium-doctor.js`. +* You might also want to run `reset.sh` with the `--dev` flag if you want the + test apps downloaded and built as well. +* You can also use `appium-doctor` to automatically verify that all + dependencies are met. If running from source, you may have to use + `bin/appium-doctor.js` or `node bin/appium-doctor.js`. * If you get this error after upgrading to Android SDK 22: - `{ANDROID_HOME}/tools/ant/uibuild.xml:155: SDK does not have any Build Tools installed.` -In the Android SDK 22, the platform and build tools are split up into their own items in the SDK manager. Make sure you install the build-tools and platform-tools. + `{ANDROID_HOME}/tools/ant/uibuild.xml:155: SDK does not have any Build Tools installed.` +In the Android SDK 22, the platform and build tools are split up into their +own items in the SDK manager. Make sure you install the build-tools and platform-tools. ## Android * Make sure the Android emulator is up and running. -* It's sometimes useful to run `adb kill-server && adb devices`. This can reset the connection to the Android device. -* Make sure you know about the `app-package`, `app-activity`, and `app-wait-activity` desiredCapabilities (see [this doc](https://github.com/appium/appium/blob/master/docs/running-tests.md#run-android) for more information). +* It's sometimes useful to run `adb kill-server && adb devices`. This can + reset the connection to the Android device. +* Make sure you know about the `app-package`, `app-activity`, + and `app-wait-activity` desiredCapabilities (see [this doc](https://github.com/appium/appium/blob/master/docs/running-tests.md#run-android) + for more information). * Make sure you set ANDROID_HOME pointing to the Android SDK directory ## IOS * Make sure Instruments.app is not open -* If you're running the simulator, make sure your actual device is not plugged in +* If you're running the simulator, make sure your actual device is not + plugged in * Make sure the accessibility helper is turned off in your Settings app -* Make sure the app is compiled for the version of the simulator that's being run -* If you've ever run Appium with sudo, you might need to `sudo rm /tmp/instruments_sock` and try again as not-sudo. -* If this is the first time you've run Appium, make sure to authorize the use of Instruments. Usually a box will pop up that you enter your password into. If you're running Appium from source, you can simply run `sudo grunt authorize` from the main repo to avoid getting this popup. If you're running from npm, run `sudo authorize_ios` instead. -* If you see `iOS Simulator failed to install the application.` and the paths are correct, try restarting the computer. - +* Make sure the app is compiled for the version of the simulator that's being + run +* If you've ever run Appium with sudo, you might need to `sudo rm + /tmp/instruments_sock` and try again as not-sudo. +* If this is the first time you've run Appium, make sure to authorize the use + of Instruments. Usually a box will pop up that you enter your password into + . If you're running Appium from source, you can simply run `sudo grunt authorize` + from the main repo to avoid getting this popup. If you're running from npm, + run `sudo authorize_ios` instead. +* If you see `iOS Simulator failed to install the application.` and the + paths are correct, try restarting the computer. ## Webview/Hybrid/Safari app support * Make Sure you enable the 'Web Inspector' on the real device. -* Make Sure you enable the Safari - Advance Preferences- Developer menu for simulators. -* If you getting this error: select_port() failed, when trying to open the proxy, see this [discussion](https://groups.google.com/forum/#!topic/appium-discuss/tw2GaSN8WX0) +* Make Sure you enable the Safari - Advance Preferences- Developer menu for + simulators. +* If you getting this error: select_port() failed, when trying to open the + proxy, see this [discussion](https://groups.google.com/forum/#!topic/appium-discuss/tw2GaSN8WX0) ## FirefoxOS @@ -61,15 +85,22 @@ In the Android SDK 22, the platform and build tools are split up into their own ## Let the community know -Once you've tried the above steps and your issue still isn't resolved, here's what you can do: +Once you've tried the above steps and your issue still isn't resolved, +here's what you can do: -If you've found what you believe is a bug, go straight to the [issue tracker](https://github.com/appium/appium/issues) and submit an issue describing the bug and a repro case. +If you've found what you believe is a bug, go straight to the [issue tracker](https://github.com/appium/appium/issues) +and submit an issue describing the bug and a repro case. -If you're having trouble getting Appium working and the error messages Appium provides are not clear, join the [mailing list](https://groups.google.com/d/forum/appium-discuss) and send a message. Please include the following: +If you're having trouble getting Appium working and the error messages Appium +provides are not clear, join the [mailing list](https://groups.google.com/d/forum/appium-discuss) +and send a message. Please include the following: * How you're running Appium (Appium.app, npm, source) -* The client-side and server-side errors you're getting (i.e., "In Python this is the exception I get in my test script, and here's a link to a paste of the Appium server output) -* Per above, it's very important to include a paste of the Appium server output when it's run in verbose mode so that we can diagnose what's going on. +* The client-side and server-side errors you're getting (i.e., +"In Python this is the exception I get in my test script, +and here's a link to a paste of the Appium server output) +* Per above, it's very important to include a paste of the Appium server +output when it's run in verbose mode so that we can diagnose what's going on. ## Known Issues @@ -80,10 +111,13 @@ If you're having trouble getting Appium working and the error messages Appium pr found. This results in an error that looks like `(null) cannot be tapped`. Sometimes the only solution is to put the finding-and-acting code in a retry block. See also `mobile: findAndAct` on the [finding elements doc page](https://github.com/appium/appium/blob/master/docs/finding-elements.md) -* Appium may have difficulties finding the `node` executable if you've installed Node and npm via MacPorts. You must make sure that the MacPorts bin folder (`/opt/local/bin` by default) is added to `PATH` somewhere in your `~/.profile`, `~/.bash_profile` or `~/.bashrc`. +* Appium may have difficulties finding the `node` executable if you've +installed Node and npm via MacPorts. You must make sure that the MacPorts bin + folder (`/opt/local/bin` by default) is added to `PATH` somewhere in your + `~/.profile`, `~/.bash_profile` or `~/.bashrc`. ## Specific Errors |Action|Error|Resolution| |------|-----|----------| -|Running reset.sh|xcodebuild: error: SDK "iphonesimulator6.1" cannot be located|Install the iPhone 6.1 SDK _or_ build the test apps with a separate SDK, e.g., `grunt buildApp:UICatalog:iphonesimulator5.1`| +|Running reset.sh|xcodebuild: error: SDK "iphonesimulator6.1" cannot be located|Install the iPhone 6.1 SDK _or_ build the test apps with a separate SDK, e.g., `grunt buildApp:UICatalog:iphonesimulator5.1`| \ No newline at end of file diff --git a/docs/gestures.md b/docs/gestures.md deleted file mode 100644 index 4a0d350d5..000000000 --- a/docs/gestures.md +++ /dev/null @@ -1,330 +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 tapObject = new HashMap(); - 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 tapObject = new HashMap(); - 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 coords = new Dictionary(); - 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 flickObject = new HashMap(); - 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 swipeObject = new HashMap(); - 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 scrollObject = new HashMap(); - 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 scrollToObject = new HashMap(); - scrollToObject.put("element",((RemoteWebElement) element).getId()); - js.executeScript("mobile: scrollTo", scrollToObject); -``` - - -### longTap - - * **c#** - - ```c# - // long tap an element - // - Dictionary parameters = new Dictionary(); - parameters.Add("using", _attributeType); - parameters.Add("value", _attribute); - Response response = rm.executescript(DriverCommand.FindElement, parameters); - Dictionary elementDictionary = response.Value as Dictionary; - string id = null; - if (elementDictionary != null) - { - id = (string)elementDictionary["ELEMENT"]; - } - IJavaScriptExecutor js = (IJavaScriptExecutor)remoteDriver; - Dictionary longTapObject = new Dictionary(); - longTapObject.Add("element", id); - js.ExecuteScript("mobile: longClick", longTapObject); - ``` diff --git a/docs/running-on-windows.md b/docs/running-on-windows.md deleted file mode 100644 index 47e0d4ce8..000000000 --- a/docs/running-on-windows.md +++ /dev/null @@ -1,37 +0,0 @@ -Running Appium on Windows -======================= - -# Limitations - -If you are running Appium on Windows, you cannot use the prebuilt '.app', which is built for OS X only. Additionally, you will not be able to test iOS apps because Appium relies on OS X-only libraries to support iOS testing. - -# Setup - -To get started: - -1. Install [node.js](http://nodejs.org/download/) (v.0.8 or greater). Use the installer from nodejs.org. -2. Install the [Android SDK](http://developer.android.com/sdk/index.html). You will need to run the 'android' tool (included in the SDK) and make sure you have an API Level 17 or greater API installed. Set `ANDROID_HOME` to be your Android SDK path and add the tools and platform-tools folders to your PATH variable. -3. Install the Java JDK and set `JAVA_HOME` to your JDK folder. -4. Install [Apache Ant](http://ant.apache.org/bindownload.cgi) or use the one that comes with the Android Windows SDK in the eclipse\plugins folder. Be sure to add the folder containing ant to your PATH variable. -5. Install [Apache Maven](http://maven.apache.org/download.cgi) and set the M2HOME and M2 environment variables. Set M2HOME to the directory maven is installed in, and set M2 to %M2HOME\bin. Add the path you used for M2 to your PATH. -6. Install [Git](http://git-scm.com/download/win) Be sure to install Git for windows to run in the regular command prompt. -7. Instal [cURL](http://curl.haxx.se/download.html) - -Now that you've downloaded everything, run: - - reset.bat - -# Running Appium - -To run tests on Windows, you will need to have the Android Emulator booted or an Android Device connected that is running an AVD with API Level 17 or greater. Then run Appium on the command line using node.js: - - node . - -See the [server documentation](https://github.com/appium/appium/blob/master/docs/server-args.md) for all the command line arguments. - -# Notes -* you must supply the --no-reset and --full-reset flags currently for android to work on Windows. -* There exists a hardware accelerated emulator for android, it has it's own - limitations. For more information you can check out this - [page](https://github.com/appium/appium/blob/master/docs/android-hax-emulator.md). -* Make sure that `hw.battery=yes` in your AVD's `config.ini`.