mirror of
https://github.com/appium/appium.git
synced 2026-11-10 03:44:40 +08:00
Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8150b4f3a6 | ||
|
|
691c2f66c0 | ||
|
|
b590d9b9d5 | ||
|
|
0da1891ac9 | ||
|
|
2cadaa284e | ||
|
|
c78847855b | ||
|
|
4970643d96 | ||
|
|
e05f93eb28 | ||
|
|
66184e132d | ||
|
|
02b4abe465 | ||
|
|
4034d16d2d | ||
|
|
19cb2d6f99 | ||
|
|
001327b894 | ||
|
|
51bfe25c51 | ||
|
|
d7027c09ea | ||
|
|
ed98432390 | ||
|
|
0d9b4a812a | ||
|
|
aa8d0e70aa | ||
|
|
dc4901a87a | ||
|
|
8313c6026b | ||
|
|
547d308382 | ||
|
|
3e931207b7 | ||
|
|
563670ecde | ||
|
|
bf0458ba9b | ||
|
|
74fa4504f8 |
@@ -19,3 +19,12 @@ Describe in more detail the problem you have been experiencing, if necessary.
|
||||
## Link to Appium logs
|
||||
|
||||
Create a [gist](https://gist.github.com) which is a paste of your _full_ Appium logs, and link them here. Do _not_ paste your full Appium logs here, as it will make this issue very long and hard to read! If you are reporting a bug, _always_ include Appium logs!
|
||||
|
||||
|
||||
## Code To Reproduce Issue [ Good To Have ]
|
||||
|
||||
Please remember that, with sample code; it's easier to reproduce bug and much faster to fix it.
|
||||
|
||||
Please git clone https://github.com/appium/sample-code and use one of your favourite languages and sample apps to reproduce issue.
|
||||
|
||||
In case a similar scenario is missing in sample-code, please submit a PR with one of the sample apps provided.
|
||||
@@ -30,3 +30,4 @@ build/
|
||||
*DerivedData
|
||||
__pycache__
|
||||
old
|
||||
.tern-project
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
[submodule "submodules/instruments-without-delay"]
|
||||
path = submodules/instruments-without-delay
|
||||
url = https://github.com/facebook/instruments-without-delay.git
|
||||
[submodule "submodules/ApiDemos"]
|
||||
path = submodules/ApiDemos
|
||||
url = https://github.com/appium/android-apidemos.git
|
||||
[submodule "submodules/appium.io"]
|
||||
path = submodules/appium.io
|
||||
url = https://github.com/appium/appium.io.git
|
||||
[submodule "submodules/selendroid"]
|
||||
path = submodules/selendroid
|
||||
url = https://github.com/selendroid/selendroid.git
|
||||
[submodule "submodules/io.appium.gappium.sampleapp"]
|
||||
path = submodules/io.appium.gappium.sampleapp
|
||||
url = https://github.com/appium/io.appium.gappium.sampleapp.git
|
||||
[submodule "submodules/unlock_apk"]
|
||||
path = submodules/unlock_apk
|
||||
url = https://github.com/appium/unlock_apk.git
|
||||
[submodule "submodules/libimobiledevice-macosx"]
|
||||
path = submodules/libimobiledevice-macosx
|
||||
url = https://github.com/benvium/libimobiledevice-macosx.git
|
||||
[submodule "submodules/ForceQuitUnresponsiveApps"]
|
||||
path = submodules/ForceQuitUnresponsiveApps
|
||||
url = https://github.com/appium/ForceQuitUnresponsiveApps.git
|
||||
[submodule "submodules/appium-atoms"]
|
||||
path = submodules/appium-atoms
|
||||
url = https://github.com/appium/appium-atoms.git
|
||||
branch = published
|
||||
[submodule "submodules/appium-instruments"]
|
||||
path = submodules/appium-instruments
|
||||
url = https://github.com/appium/appium-instruments.git
|
||||
branch = published
|
||||
[submodule "submodules/appium-uiauto"]
|
||||
path = submodules/appium-uiauto
|
||||
url = https://github.com/appium/appium-uiauto.git
|
||||
branch = published
|
||||
[submodule "submodules/appium-adb"]
|
||||
path = submodules/appium-adb
|
||||
url = https://github.com/appium/appium-adb.git
|
||||
[submodule "submodules/io.appium.android.ime"]
|
||||
path = submodules/io.appium.android.ime
|
||||
url = https://github.com/appium/io.appium.android.ime.git
|
||||
[submodule "submodules/io.appium.settings"]
|
||||
path = submodules/io.appium.settings
|
||||
url = https://github.com/appium/io.appium.settings.git
|
||||
[submodule "submodules/sample-code"]
|
||||
path = submodules/sample-code
|
||||
url = https://github.com/appium/sample-code
|
||||
[submodule "submodules/deviceconsole"]
|
||||
path = submodules/deviceconsole
|
||||
url = https://github.com/rpetrich/deviceconsole.git
|
||||
[submodule "submodules/appium-ci-gulper"]
|
||||
path = submodules/appium-ci-gulper
|
||||
url = https://github.com/appium/appium-ci-gulper.git
|
||||
branch = master
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "5"
|
||||
- "stable"
|
||||
- "4"
|
||||
- "0.12"
|
||||
after_success:
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
CHANGES IN VERSION 1.5.1 (from 1.5)
|
||||
===================================
|
||||
|
||||
*NOTE*: Appium 1.5.1 is a bug-fix release.
|
||||
|
||||
#### General
|
||||
- allow `platformName` to be any case
|
||||
- Windows process handling is cleaned up
|
||||
- Desired capabilities `language` and `locale` added
|
||||
|
||||
#### iOS
|
||||
- iOS 9.3 (Xcode 7.3) support
|
||||
- Fix handling of return values from `executeScript` in Safari
|
||||
- Don't stop if Instruments doesn't shut down in a timely manner
|
||||
- Escape single quotes in all methods that set the value on an element
|
||||
- Allow custom device names
|
||||
- Make full use of process arguments to Instruments
|
||||
- Pass `launchTimeout` to Instruments when checking devices
|
||||
|
||||
#### Android
|
||||
- Make use of `--bootstrap-port` server argument
|
||||
- Fix `keystorePassword` capability to allow a string
|
||||
- Fix handling of localization in Android 6
|
||||
- Use Appium's unlock logic for Chrome sessions
|
||||
- Make sure reset works
|
||||
- Make unlock more reliable for later versions of Android
|
||||
- Allow Xpath searching from the context of another element
|
||||
- Make full use of process arguments to adb
|
||||
- Better error messages when ChromeDriver fails to start
|
||||
|
||||
CHANGES IN VERSION 1.5 (from 1.4.16)
|
||||
======================================
|
||||
|
||||
@@ -22,9 +52,11 @@ tests.
|
||||
amount of complexity to the startup flow and Appium shouldn't be responsible
|
||||
for this kind of use case
|
||||
- Remove long-deprecated `name` locator strategy
|
||||
- Remove long-deprecated `mobile: xxx` gesture commands, except scroll
|
||||
|
||||
#### iOS
|
||||
- add Tapster support for some more touch methods
|
||||
- fix moveTo: treat coordinates as relative, instead of absolute
|
||||
- iPhone 6 + 6S support
|
||||
- iOS 9.3 support
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ See the [platform support doc](/docs/en/appium-setup/platform-support.md) for mo
|
||||
|
||||
1. You don't have to recompile your app or modify it in any way, due
|
||||
to use of standard automation APIs on all platforms.
|
||||
2. You can write tests with your favorite dev tools using any [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol)-compatible
|
||||
2. You can write tests with your favorite dev tools using any [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html)-compatible
|
||||
language such as Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
JavaScript with Node.js (in [promise, callback](https://github.com/admc/wd) or [generator](https://github.com/jlipps/yiewd) flavors),
|
||||
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, or Perl
|
||||
with the Selenium WebDriver API and language-specific client libraries.
|
||||
3. You can use any testing framework.
|
||||
|
||||
Investing in the [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) protocol means you are betting on a single, free and open protocol for testing that has become a defacto standard. Don't lock yourself into a proprietary stack.
|
||||
Investing in the [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) protocol means you are betting on a single, free and open protocol for testing that has become a defacto standard. Don't lock yourself into a proprietary stack.
|
||||
|
||||
If you use Apple's UIAutomation library without Appium you can only write tests
|
||||
using JavaScript and you can only run tests through the Instruments application.
|
||||
@@ -83,7 +83,7 @@ You also need to download the Appium client for your language so you can write t
|
||||
|
||||
### Quick Start
|
||||
|
||||
Kick up an Appium server, and then run a test written in your favorite [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol)-compatible language!
|
||||
Kick up an Appium server, and then run a test written in your favorite [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html)-compatible language!
|
||||
You can run an Appium server using node.js or using the application, see below.
|
||||
|
||||
#### Using Node.js
|
||||
@@ -102,7 +102,7 @@ $ appium
|
||||
|
||||
The main guide for getting started writing and running tests is [the running tests](/docs/en/writing-running-appium/running-tests.md) doc, which includes explanations for iOS, Android, and Android older devices. If you're interested in testing on physical hardware, you might be interested in our [real devices guide](/docs/en/appium-setup/real-devices.md).
|
||||
|
||||
Essentially, we support a subset of the [Selenium WebDriver JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol), and extend it so that you can specify mobile-targeted [desired capabilities](/docs/en/writing-running-appium/caps.md) to run your test through Appium.
|
||||
Essentially, we support a subset of the [Selenium WebDriver JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html), and extend it so that you can specify mobile-targeted [desired capabilities](/docs/en/writing-running-appium/caps.md) to run your test through Appium.
|
||||
|
||||
You find elements by using a subset of WebDriver's element-finding strategies.
|
||||
See [finding elements](/docs/en/writing-running-appium/finding-elements.md) for detailed information. We also have several extensions to the JSON Wire Protocol for [automating mobile gestures](/docs/en/writing-running-appium/touch-actions.md) like tap, flick, and swipe.
|
||||
@@ -116,7 +116,7 @@ For the full list of Appium doc pages, visit [this directory](/docs/en/).
|
||||
### How It Works
|
||||
|
||||
Appium drives various native automation frameworks and provides an API based on
|
||||
Selenium's [WebDriver JSON wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol).
|
||||
Selenium's [WebDriver JSON wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html).
|
||||
|
||||
Appium drives Apple's UIAutomation library for iOS support, which is based on
|
||||
[Dan Cuellar's](http://github.com/penguinho) work on iOS Auto.
|
||||
|
||||
+5
-5
@@ -23,14 +23,14 @@ Appium 是一个开源的,跨平台的自动化测试工具。
|
||||
|
||||
1. 因为 Appium 在所有平台上都使用了标准的自动化接口,
|
||||
所以你不需要以重新编译或者修改你的 app。
|
||||
2. 你可以用你喜欢的开发工具,使用任何 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 兼容的语言来编写测试用例。比如
|
||||
2. 你可以用你喜欢的开发工具,使用任何 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言来编写测试用例。比如
|
||||
Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
JavaScript with Node.js (in both [callback](https://github.com/admc/wd) and [yield-based](https://github.com/jlipps/yiewd) flavours),
|
||||
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, 或者 Perl。
|
||||
可以使用标准的Selenium WebDriver API和特定语言的客户端库。
|
||||
3. 你可以使用任何测试框架。
|
||||
|
||||
投资 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 意味着你可以押宝在一个已经成为标准的独立,自由和开放的协议。你不会被任何专利限制。
|
||||
投资 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 意味着你可以押宝在一个已经成为标准的独立,自由和开放的协议。你不会被任何专利限制。
|
||||
|
||||
|
||||
如果没有 Appium,你就只能用 Javascript 来写 Apple 的 UIAutomation 脚本,并且只能通过Instruments 应用来运行你的测试。同样的,在 Google 的UiAutomator体系下,你只能用 Java 写你的测试案例。Appium 最终开启了跨平台原生移动自动化的可能。
|
||||
@@ -69,7 +69,7 @@ Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
|
||||
|
||||
### 快速开始
|
||||
启动 Appium server,并运行用你喜欢的 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 兼容的语言编写的测试用例。
|
||||
启动 Appium server,并运行用你喜欢的 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言编写的测试用例。
|
||||
你可以用 node.js 或者下面的应用程序来运行 Appium
|
||||
|
||||
#### 使用 Node.js
|
||||
@@ -92,7 +92,7 @@ Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
我们支持 [Selenium WebDriver JSON Wire Protocol](https://github.com/appium/appium/wiki/JSON-Wire-Protocol:-Supported-Methods) 的一个子集,而且在此之上扩展了移动平台相关的特性。所以你可以
|
||||
指定特定移动平台[desired capabilities](writing-running-appium/caps.cn.md) 来运行你的测试。
|
||||
|
||||
你可以通过 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 元素定位策略的子集来定位元素。更多信息请参考 [finding elements](writing-running-appium/finding-elements.cn.md)
|
||||
你可以通过 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 元素定位策略的子集来定位元素。更多信息请参考 [finding elements](writing-running-appium/finding-elements.cn.md)
|
||||
为了支持移动手势[automating mobile gestures](writing-running-appium/touch-actions.cn.md),比如
|
||||
tap,flick 和 swipe,我们扩展了JSON Wire Protocolor。
|
||||
|
||||
@@ -102,7 +102,7 @@ Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
|
||||
### 工作原理
|
||||
|
||||
Appium 可以驱动多种原生自动化框架,同时也提供基于 Selenium 的 [WebDriver JSON wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol) api。
|
||||
Appium 可以驱动多种原生自动化框架,同时也提供基于 Selenium 的 [WebDriver JSON wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html) api。
|
||||
|
||||
基于[Dan Cuellar's](http://github.com/penguinho) 在 iOS 自动化上的成果,Appium 通过驱动 Apple 的 UIAutomation 库来提供 iOS 支持。
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
## 客户端类库列表及Appium服务端支持
|
||||
|
||||
这些类库封装了标准Selenium客户端类库,为用户提供所有常见的[JSON](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 格式selenium命令以及额外的移动设备控制相关的命令,如多点**触控手势**和**屏幕朝向**。
|
||||
这些类库封装了标准Selenium客户端类库,为用户提供所有常见的[JSON](https://w3c.github.io/webdriver/webdriver-spec.html) 格式selenium命令以及额外的移动设备控制相关的命令,如多点**触控手势**和**屏幕朝向**。
|
||||
|
||||
Appium客户端类库实现了[Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)(一个标准协议的官方扩展草稿)和[W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html)(一个传输不可预知的自动化协议,该协议定义了MultiAction 接口)的元素。
|
||||
Appium客户端类库实现了[Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)(一个标准协议的官方扩展草稿)和[W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html)(一个传输不可预知的自动化协议,该协议定义了MultiAction 接口)的元素。
|
||||
|
||||
Appium 服务端定义了官方协议的扩展,为Appium 用户提供了方便的接口来执行各种设备动作,例如在测试过程中安装/卸载app。这就是为什么我们需要Appium 特定的客户端,而不是通用的Selenium 客户端。当然,Appium 客户端类库只是增加了一些功能,而实际上这些功能就是简单的扩展了Selenium 客户端,所以他们仍然可以用来运行通用的selenium会话。
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平
|
||||
* Android 2.3+: Google's [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). (Instrumentation由单独的项目[Selendroid](http://selendroid.io)提供支持 )
|
||||
|
||||
为了满足第二点,我们把这些第三方框架封装成一套 API,[WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.WebDriver(也就是 "Selenium WebDriver") 指定了客户端到服务端的协议。
|
||||
(参见 [JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol))。使用这种客户端-服务端的架构,我们可以使用任何语言来编写客户端,向服务端发送恰当的 HTTP 请求。
|
||||
(参见 [JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html))。使用这种客户端-服务端的架构,我们可以使用任何语言来编写客户端,向服务端发送恰当的 HTTP 请求。
|
||||
目前已经实现了大多数流行语言版本的客户端,这意味着你可以使用任何测试套件或者测试框架。客户端库就是简单的HTTP 客户,可以以任何你喜欢的方式潜入你的代码。换句话说,Appium 和 WebDriver 客户端不是技术意义上的“测试框架”,而是“自动化库”。你可以在你的测试环境中随意使用这些自动化库!
|
||||
|
||||
事实上 WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html)。我们又何必为移动做一个完全不同的呢?所以我们扩充了[WebDriver 的协议](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile),在原有的基础上添加移动自动化相关的 API 方法,这也满足了第三条理念。
|
||||
事实上 WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html)。我们又何必为移动做一个完全不同的呢?所以我们扩充了[WebDriver 的协议](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md),在原有的基础上添加移动自动化相关的 API 方法,这也满足了第三条理念。
|
||||
|
||||
第四条就不用说了,[Appium 是开源的](https://github.com/appium/appium)。
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Appium支持webdriver定位策略的子集
|
||||
* 根据"class"定位(例如, UI组件类型)
|
||||
* 根据"xpath"定位 (例如,具有一定约束的路径抽象标示, 基于XPath方式)
|
||||
|
||||
另外, Appium 还支持部分 [Mobile JSON 连接协议](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) 的定位策略
|
||||
另外, Appium 还支持部分 [Mobile JSON 连接协议](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) 的定位策略
|
||||
|
||||
* `ios uiautomation`: 一个递归地、对应使用 [UIAutomation library](ios_predicate.cn.md) 搜索元素的字符串(iOS-only)
|
||||
* `android uiautomator`: 一个递归地、对应使用 [UiAutomator Api](uiautomator_uiselector.cn.md)搜索元素的字符串 (Android-only)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## 调整网络设置
|
||||
|
||||
Selenium 的 [Mobile JSON Wire Protocol Specification](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) 支持一个获取和设置设备网络连接的 [API](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile#104) 。这个 API 通过位掩码(bitmask)工作,把所有可能的状态用一个整型数据表示:
|
||||
Selenium 的 [Mobile JSON Wire Protocol Specification](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) 支持一个获取和设置设备网络连接的 [API](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md#104) 。这个 API 通过位掩码(bitmask)工作,把所有可能的状态用一个整型数据表示:
|
||||
|
||||
| 值 (别名) | 数据连接 | Wifi 连接 | 飞行模式 |
|
||||
| ------------------ | ---- | ---- | ------------- |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
## List of client libraries with Appium server support
|
||||
|
||||
These libraries wrap standard Selenium client libraries to provide all the regular selenium commands dictated by the [JSON Wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol), and add extra commands related to controlling mobile devices, such as **multi-touch gestures** and **screen orientation**.
|
||||
These libraries wrap standard Selenium client libraries to provide all the regular selenium commands dictated by the [JSON Wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html), and add extra commands related to controlling mobile devices, such as **multi-touch gestures** and **screen orientation**.
|
||||
|
||||
Appium client libraries implement the [Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) (an official draft extension to the standard protocol), and elements of the [W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html) (a transport-agnostic automation spec; this is where the MultiAction API is defined).
|
||||
Appium client libraries implement the [Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) (an official draft extension to the standard protocol), and elements of the [W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html) (a transport-agnostic automation spec; this is where the MultiAction API is defined).
|
||||
|
||||
The Appium server itself defines custom extensions to the official protocols, giving Appium users helpful access to various device behaviors (such as installing/uninstalling apps during the course of a test session). This is why we need Appium-specific clients, not just the 'vanilla' Selenium clients. Of course, Appium client libraries only **add** functionality (in fact, they simply extend the standard Selenium clients), so they can still be used to run regular Selenium sessions.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ third-party code or frameworks to your app. This means **you're testing the same
|
||||
We meet requirement #2 by wrapping the vendor-provided frameworks in one API,
|
||||
the [WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.
|
||||
WebDriver (aka "Selenium WebDriver") specifies a client-server protocol
|
||||
(known as the [JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol)).
|
||||
(known as the [JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html)).
|
||||
Given this client-server architecture, a client written in any language can
|
||||
be used to send the appropriate HTTP requests to the server. There are
|
||||
already [clients written in every popular programming language](http://appium.io/downloads). This also
|
||||
@@ -50,7 +50,7 @@ manage your test environment any way you like!
|
||||
|
||||
We meet requirement #3 in the same way: WebDriver has become the de facto
|
||||
standard for automating web browsers, and is a [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html).
|
||||
Why do something totally different for mobile? Instead we have [extended the protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
|
||||
Why do something totally different for mobile? Instead we have [extended the protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
with extra API methods useful for mobile automation.
|
||||
|
||||
It should be obvious that requirement #4 is a given -- you're reading this
|
||||
|
||||
@@ -12,9 +12,9 @@ WebDriver protocol for everything.
|
||||
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/contexts](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
|
||||
1. Call [GET session/:sessionId/contexts](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
1. This returns a list of contexts we can access, like 'NATIVE_APP' or 'WEBVIEW_1'
|
||||
1. Call [POST session/:sessionId/context](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
|
||||
1. Call [POST session/:sessionId/context](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
with the id of the context 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,
|
||||
|
||||
@@ -5,11 +5,11 @@ the command line (appium does this under the hood for xcode < 7). See [iwd](http
|
||||
|
||||
For enabling iwd for xcode >= 7,
|
||||
- Checkout [appium-instruments](https://github.com/appium/appium-instruments)
|
||||
- Run `xcode_iwd.sh` present in `<appium-instruments>/bin/`
|
||||
- Run `xcode-iwd.sh` present in `<appium-instruments>/bin/`
|
||||
|
||||
```
|
||||
sh <appium-instruments>/bin/xcode_iwd.sh <path to xcode> <path to appium-instruments>
|
||||
sh <appium-instruments>/bin/xcode-iwd.sh <path to xcode> <path to appium-instruments>
|
||||
```
|
||||
eg. `sh ./bin/xcode_iwd.sh /Applications/Xcode.app /Users/xyz/appium-instruments/`
|
||||
eg. `sh ./bin/xcode-iwd.sh /Applications/Xcode.app /Users/xyz/appium-instruments/`
|
||||
|
||||
Note: iwd with xcode7 will only work for iOS >= 9.0, you can switch to older xcode for iOS < 9.0
|
||||
|
||||
@@ -23,6 +23,8 @@ cd appium
|
||||
npm install
|
||||
gulp transpile # requires gulp, see below
|
||||
sudo node_modules/.bin/authorize-ios.js # for ios only
|
||||
# alternatively
|
||||
sudo $(npm bin)/authorize-ios
|
||||
node .
|
||||
```
|
||||
|
||||
@@ -81,7 +83,10 @@ have to modify your `/etc/authorization` file in one of two ways:
|
||||
|
||||
```center
|
||||
sudo node_modules/.bin/authorize-ios.js
|
||||
```
|
||||
|
||||
# alternatively
|
||||
sudo $(npm bin)/authorize-ios
|
||||
```
|
||||
|
||||
At this point, run:
|
||||
|
||||
|
||||
@@ -825,7 +825,7 @@ swipe start_x: 75, start_y: 500, end_x: 75, end_y: 0, duration: 0.8
|
||||
|
||||
```python
|
||||
# python
|
||||
driver.swipe(start=75, starty=500, endx=75, endy=0, duration=800)
|
||||
driver.swipe(start_x=75, start_y=500, end_x=75, end_y=0, duration=800)
|
||||
```
|
||||
|
||||
```java
|
||||
@@ -987,27 +987,28 @@ Scroll to an element.
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
element = find_element :name, 'Element Name'
|
||||
execute_script "mobile: scrollTo", :element => element.ref
|
||||
element = find_element :name, "Element Name"
|
||||
execute_script "mobile: scroll", direction: "down", element: element.ref
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
driver.execute_script("mobile: scrollTo", {"element": element.id})
|
||||
driver.execute_script("mobile: scroll", {"direction": "down", element: element.id})
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
WebElement element = driver.findElement(By.name("Element Name"));
|
||||
HashMap<String, String> arguments = new HashMap<String, String>();
|
||||
arguments.put("element", element.getId());
|
||||
(JavascriptExecutor)driver.executeScript("mobile: scrollTo", arguments);
|
||||
JavascriptExecutor js = (JavascriptExecutor) driver;
|
||||
HashMap<String, String> scrollObject = new HashMap<String, String>();
|
||||
scrollObject.put("direction", "down");
|
||||
scrollObject.put("element", ((RemoteWebElement) element).getId());
|
||||
js.executeScript("mobile: scroll", scrollObject);
|
||||
```
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
return driver.elementByName().then(function (el) {
|
||||
return driver.execute('mobile: scrollTo', {element: el.value});
|
||||
driver.execute("mobile: scroll", [{direction: "down", element: el.value}]);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1019,7 +1020,10 @@ $this->scroll($els[count($els) - 1], $els[0]);
|
||||
|
||||
```csharp
|
||||
// c#
|
||||
todo: csharp
|
||||
Dictionary<string, string> scrollObject = new Dictionary<string, string>();
|
||||
scrollObject.Add("direction", "down");
|
||||
scrollObject.Add("element", <element_id>);
|
||||
((IJavaScriptExecutor)driver).ExecuteScript("mobile: scroll", scrollObject));
|
||||
```
|
||||
|
||||
### Pull file
|
||||
|
||||
@@ -6,7 +6,7 @@ Appium supports a subset of the WebDriver locator strategies:
|
||||
* 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
|
||||
Appium additionally supports some of the [Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) locator strategies
|
||||
|
||||
* `-ios uiautomation`: a string corresponding to a recursive element search
|
||||
using the [UIAutomation library](ios_predicate.md) (iOS-only)
|
||||
|
||||
@@ -176,7 +176,7 @@ class ContextTests extends PHPUnit_Extensions_AppiumTestCase
|
||||
Pre-requisites:
|
||||
|
||||
* Make sure Chrome (an app with the package `com.android.chrome`) is installed on your device or emulator. Getting Chrome for the x86 version of the emulator is not currently possible without building Chromium, so you may want to run an ARM emulator and then copy a Chrome APK from a real device to get Chrome on an emulator.
|
||||
* If downloaded from [NPM](https://www.npmjs.org/package/appium), or running from the [.app](https://github.com/appium/appium-dot-app), nothing needs to be done. If running from source, `npm install` will download ChromeDriver and put it in `node_modules/appium-android-driver/node_modules/appium-chromedriver/chromedriver`. A particular version can be specified by passing the `--chromedriver_version` config property (e.g., `npm install appium --chromedriver_version="2.16"`), otherwise the most recent one will be retrieved.
|
||||
* If downloaded from [NPM](https://www.npmjs.org/package/appium), or running from the [.app](https://github.com/appium/appium-dot-app), nothing needs to be done. If running from source, `npm install` will download ChromeDriver and put it in `node_modules/appium-chromedriver/chromedriver/<OS name>/` for users having npm v3+ and for npm v2 it will be in `node_modules/appium-android-driver/node_modules/appium-chromedriver/chromedriver/<OS name>/`. A particular version can be specified by passing the `--chromedriver_version` config property (e.g., `npm install appium --chromedriver_version="2.16"`), otherwise the most recent one will be retrieved.
|
||||
|
||||
Then, use desired capabilities like these to run your test in Chrome:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Adjusting Network Connection
|
||||
|
||||
The Selenium [Mobile JSON Wire Protocol Specification](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) supports an [API](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile#104) for getting and setting the network connection for a device. The API works through a bitmask, assigning an integer to each possible state:
|
||||
The Selenium [Mobile JSON Wire Protocol Specification](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) supports an [API](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md#104) for getting and setting the network connection for a device. The API works through a bitmask, assigning an integer to each possible state:
|
||||
|
||||
| Value (Alias) | Data | Wifi | Airplane Mode |
|
||||
| ------------------ | ---- | ---- | ------------- |
|
||||
|
||||
@@ -44,10 +44,18 @@ to another position, and removing their finger from the screen.
|
||||
Appium performs the events in sequence. You can add a `wait` event to control
|
||||
the timing of the gesture.
|
||||
|
||||
`moveTo` coordinates are *relative* to the current position. For example, dragging from
|
||||
100,100 to 200,200 can be achieved by:
|
||||
```
|
||||
.press(100,100) // Start at 100,00
|
||||
.moveTo(100,100) // Increase X & Y by 100 each, ending up at 200,200
|
||||
|
||||
```
|
||||
|
||||
The appium client libraries have different ways of implementing this, for example:
|
||||
you can pass in coordinates or an element to a `moveTo` event. Passing both
|
||||
coordinates _and_ an element will treat the coordinates as relative to the
|
||||
elements position, rather than absolute.
|
||||
element's position, rather than relative to the current position.
|
||||
|
||||
Calling the `perform` event sends the entire sequence of events to appium,
|
||||
and the touch gesture is run on your device.
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
## 为什么选择appium ?
|
||||
|
||||
1. 你不需要以任何方式重新编译或者修改你的app,就可以在所有的平台上使用标准的自动化APIs
|
||||
2. 你可以用你喜欢的开发工具使用任何 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 兼容的语言来编写测试用例.比如
|
||||
2. 你可以用你喜欢的开发工具使用任何 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言来编写测试用例.比如
|
||||
Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
JavaScript with Node.js (in both [callback](https://github.com/admc/wd) and [yield-based](https://github.com/jlipps/yiewd) flavours),
|
||||
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, 或者 Perl
|
||||
可以使用标准的Selenium WebDriver API和特定语言的客户端库.
|
||||
3. 你可以使用任何测试框架.
|
||||
|
||||
依托 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 意味着你可以押宝在一个已经成为事实上标准的独立,自由和开放的协议.而不会被限制在任何的专利中
|
||||
依托 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 意味着你可以押宝在一个已经成为事实上标准的独立,自由和开放的协议.而不会被限制在任何的专利中
|
||||
|
||||
|
||||
如果在没有使用Appium的情况,你使用了Apple的UIAutomation库就只能通过Javascript,并且只能通过Instruments application插桩应用来运行你的测试.
|
||||
@@ -54,7 +54,7 @@ Appium最终开启了跨平台原生移动自动化的可能.
|
||||
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
|
||||
|
||||
## 快速开始
|
||||
启动Appium server,并运行用你喜欢的 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 兼容的语言编写的测试用例.
|
||||
启动Appium server,并运行用你喜欢的 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言编写的测试用例.
|
||||
你可以用node.js或者下面的应用程序来运行Appium
|
||||
|
||||
### 使用Node.js
|
||||
@@ -72,7 +72,7 @@ Appium最终开启了跨平台原生移动自动化的可能.
|
||||
我们支持 [Selenium WebDriver JSON Wire Protocol](https://github.com/appium/appium/wiki/JSON-Wire-Protocol:-Supported-Methods) 的一个子集
|
||||
首先还需要指定特定移动平台相关的 [desired capabilities](caps.cn.md) 来通过appium运行你的测试
|
||||
|
||||
你可以通过 [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 的元素定位策略的一个子集来定位元素
|
||||
你可以通过 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 的元素定位策略的一个子集来定位元素
|
||||
更多信息请参考 [finding elements](finding-elements.cn.md)
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ Appium最终开启了跨平台原生移动自动化的可能.
|
||||
|
||||
## 工作原理
|
||||
|
||||
Appium通过多种原生自动化框架来提供基于Selenium的 [WebDriver JSON wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol) api
|
||||
Appium通过多种原生自动化框架来提供基于Selenium的 [WebDriver JSON wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html) api
|
||||
|
||||
Appium驱动Apple的UIAutomation库提供IOS支持. UIAutomation基于[Dan Cuellar's](http://github.com/penguinho)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平
|
||||
|
||||
为了满足第二点,我们把这些第三方框架封装成一套 API, [WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.
|
||||
WebDriver (也就是 "Selenium WebDriver") 指定了客户端到服务端的协议。
|
||||
(参见 [JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol))。
|
||||
(参见 [JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html))。
|
||||
使用这种客户端-服务端的架构,我们可以使用任何语言来编写客户端,向服务端发送恰当的 HTTP 请求。
|
||||
而且目前已经有大多数流行语言版本的客户端实现了。这也意味着你可以使用任何测试套件或者测试框架。客户端库就是简单的
|
||||
HTTP 客户,可以以任何你喜欢的方式潜入你的代码。换句话说,Appium 和 WebDriver 客户端不是技术意义上的“测试框架”,
|
||||
@@ -41,7 +41,7 @@ HTTP 客户,可以以任何你喜欢的方式潜入你的代码。换句话说
|
||||
|
||||
事实上 WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html)。
|
||||
我们又何必为移动做一个完全不同的呢?
|
||||
所以我们扩充了[WebDriver 的协议](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile),
|
||||
所以我们扩充了[WebDriver 的协议](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md),
|
||||
在原有的基础上添加移动自动化相关的 API 方法,这也也满足了第三条理念。
|
||||
|
||||
第四条就不用说了,[Appium 是开源的](https://github.com/appium/appium)。
|
||||
|
||||
+4
-5
@@ -1,7 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import log from './logger';
|
||||
import { getAppiumConfig } from './config';
|
||||
import { fixCaps } from './helpers';
|
||||
import { BaseDriver } from 'appium-base-driver';
|
||||
import { FakeDriver } from 'appium-fake-driver';
|
||||
import { AndroidDriver } from 'appium-android-driver';
|
||||
@@ -26,7 +25,7 @@ class AppiumDriver extends BaseDriver {
|
||||
}
|
||||
|
||||
sessionExists (sessionId) {
|
||||
return _.contains(_.keys(this.sessions), sessionId) &&
|
||||
return _.includes(_.keys(this.sessions), sessionId) &&
|
||||
this.sessions[sessionId].sessionId !== null;
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ class AppiumDriver extends BaseDriver {
|
||||
|
||||
async getSessions () {
|
||||
let sessions = [];
|
||||
for (let [id, driver] of _.pairs(this.sessions)) {
|
||||
for (let [id, driver] of _.toPairs(this.sessions)) {
|
||||
sessions.push({id: id, capabilities: driver.caps});
|
||||
}
|
||||
return sessions;
|
||||
@@ -94,7 +93,7 @@ class AppiumDriver extends BaseDriver {
|
||||
log.info(`Creating new ${InnerDriver.name} session`);
|
||||
log.info('Capabilities:');
|
||||
util.inspect(caps);
|
||||
for (let [cap, value] of _.pairs(caps)) {
|
||||
for (let [cap, value] of _.toPairs(caps)) {
|
||||
log.info(` ${cap}: ${util.inspect(value)}`);
|
||||
}
|
||||
try {
|
||||
@@ -103,7 +102,7 @@ class AppiumDriver extends BaseDriver {
|
||||
throw new errors.SessionNotCreatedError(e.message);
|
||||
}
|
||||
let d = new InnerDriver(this.args);
|
||||
let [innerSessionId, dCaps] = await d.createSession(fixCaps(caps), reqCaps, curSessions);
|
||||
let [innerSessionId, dCaps] = await d.createSession(caps, reqCaps, curSessions);
|
||||
this.sessions[innerSessionId] = d;
|
||||
|
||||
// Remove the session on unexpected shutdown, so that we are in a position
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ function validateServerArgs (parser, args) {
|
||||
|
||||
const nonDefaultArgs = getNonDefaultArgs(parser, args);
|
||||
|
||||
for (let [arg, validator] of _.pairs(validations)) {
|
||||
for (let [arg, validator] of _.toPairs(validations)) {
|
||||
if (_.has(nonDefaultArgs, arg)) {
|
||||
if (!validator(args[arg], arg)) {
|
||||
throw new Error(`Invalid argument for param ${arg}: ${args[arg]}`);
|
||||
|
||||
@@ -109,9 +109,13 @@ async function isAlreadyRegistered (jsonObject) {
|
||||
throw new Error(`Request failed`);
|
||||
}
|
||||
let responseData = JSON.parse(response.body);
|
||||
if (responseData.success !== true) {
|
||||
// if register fail, print the debug msg
|
||||
logger.debug(`Grid registration error: ${responseData.msg}`);
|
||||
}
|
||||
return responseData.success;
|
||||
} catch (err) {
|
||||
logger.debug("Hub down or not responding: ${err.message}");
|
||||
logger.debug(`Hub down or not responding: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import log from './logger';
|
||||
|
||||
|
||||
function fixCaps (originalCaps) {
|
||||
let caps = _.clone(originalCaps);
|
||||
// boolean capabilities can be passed in as strings 'false' and 'true'
|
||||
// which we want to translate into boolean values
|
||||
for (let [cap, value] of _.pairs(caps)) {
|
||||
if (_.isString(value)) {
|
||||
value = value.toLowerCase();
|
||||
if (value === 'true' || value === 'false') {
|
||||
log.debug(`Capability '${cap}' changed from string to boolean. This may cause unexpected behavior`);
|
||||
caps[cap] = (value === 'true');
|
||||
}
|
||||
}
|
||||
}
|
||||
return caps;
|
||||
}
|
||||
|
||||
|
||||
export { fixCaps };
|
||||
+20
-10
@@ -3,6 +3,7 @@ import { patchLogger } from 'appium-logger';
|
||||
import winston from 'winston';
|
||||
import { fs } from 'appium-support';
|
||||
import 'date-utils';
|
||||
import _ from 'lodash';
|
||||
|
||||
|
||||
// set up distributed logging before everything else
|
||||
@@ -12,10 +13,10 @@ global._global_npmlog = npmlog;
|
||||
// npmlog is used only for emitting, we use winston for output
|
||||
npmlog.level = "silent";
|
||||
const levels = {
|
||||
debug: 1,
|
||||
info: 2,
|
||||
warn: 3,
|
||||
error: 4,
|
||||
debug: 4,
|
||||
info: 3,
|
||||
warn: 2,
|
||||
error: 1,
|
||||
};
|
||||
|
||||
const colors = {
|
||||
@@ -99,7 +100,7 @@ function _createFileTransport (args, logLvl) {
|
||||
return transport;
|
||||
}
|
||||
|
||||
function _createWebhookTransport (args, logLvl) {
|
||||
function _createHttpTransport (args, logLvl) {
|
||||
let host = null,
|
||||
port = null;
|
||||
|
||||
@@ -109,8 +110,8 @@ function _createWebhookTransport (args, logLvl) {
|
||||
port = parseInt(hostAndPort[1], 10);
|
||||
}
|
||||
|
||||
let transport = new (winston.transports.Webhook)({
|
||||
name: "webhook",
|
||||
let transport = new (winston.transports.Http)({
|
||||
name: "http",
|
||||
host: host || '127.0.0.1',
|
||||
port: port || 9003,
|
||||
path: '/',
|
||||
@@ -157,9 +158,9 @@ async function _createTransports (args) {
|
||||
|
||||
if (args.webhook) {
|
||||
try {
|
||||
transports.push(_createWebhookTransport(args, fileLogLevel));
|
||||
transports.push(_createHttpTransport(args, fileLogLevel));
|
||||
} catch (e) {
|
||||
console.log(`Tried to attach logging to webhook at ${args.webhook} but ` +
|
||||
console.log(`Tried to attach logging to Http at ${args.webhook} but ` +
|
||||
`an error occurred: ${e.message}`);
|
||||
}
|
||||
}
|
||||
@@ -204,6 +205,15 @@ async function init (args) {
|
||||
}
|
||||
}
|
||||
|
||||
function clear () {
|
||||
if (logger) {
|
||||
for (let transport of _.keys(logger.transports)) {
|
||||
logger.remove(transport);
|
||||
}
|
||||
}
|
||||
npmlog.removeAllListeners('log');
|
||||
}
|
||||
|
||||
export { init };
|
||||
|
||||
export { init, clear };
|
||||
export default init;
|
||||
|
||||
+3
-3
@@ -38,14 +38,14 @@ async function preflightChecks (parser, args) {
|
||||
|
||||
function logDeprecationWarning (deprecatedArgs) {
|
||||
logger.warn('Deprecated server args:');
|
||||
for (let [arg, realArg] of _.pairs(deprecatedArgs)) {
|
||||
for (let [arg, realArg] of _.toPairs(deprecatedArgs)) {
|
||||
logger.warn(` ${arg.red} => ${realArg}`);
|
||||
}
|
||||
}
|
||||
|
||||
function logNonDefaultArgsWarning (args) {
|
||||
logger.info('Non-default server args:');
|
||||
for (let [arg, value] of _.pairs(args)) {
|
||||
for (let [arg, value] of _.toPairs(args)) {
|
||||
logger.info(` ${arg}: ${util.inspect(value)}`);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ function logDefaultCapabilitiesWarning (caps) {
|
||||
logger.info('Default capabilities, which will be added to each request ' +
|
||||
'unless overridden by desired capabilities:');
|
||||
util.inspect(caps);
|
||||
for (let [cap, value] of _.pairs(caps)) {
|
||||
for (let [cap, value] of _.toPairs(caps)) {
|
||||
logger.info(` ${cap}: ${util.inspect(value)}`);
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+5504
-1890
File diff suppressed because it is too large
Load Diff
+29
-27
@@ -11,7 +11,7 @@
|
||||
"firefoxos",
|
||||
"testing"
|
||||
],
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.1",
|
||||
"author": "https://github.com/appium",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
@@ -21,9 +21,10 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/appium/appium/issues"
|
||||
},
|
||||
"engines": [
|
||||
"node"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=0.12",
|
||||
"iojs": ">=1.0.0"
|
||||
},
|
||||
"main": "./build/lib/main.js",
|
||||
"bin": {
|
||||
"appium": "./build/lib/main.js",
|
||||
@@ -34,27 +35,28 @@
|
||||
"doc": "./docs"
|
||||
},
|
||||
"dependencies": {
|
||||
"appium-android-driver": "^1.6.11",
|
||||
"appium-base-driver": "^1.3.0",
|
||||
"appium-express": "^1.2.0",
|
||||
"appium-android-driver": "^1.8.0",
|
||||
"appium-base-driver": "^1.4.1",
|
||||
"appium-express": "^1.2.2",
|
||||
"appium-fake-driver": "^0.1.9",
|
||||
"appium-ios-driver": "^1.8.7",
|
||||
"appium-ios-driver": "^1.10.0",
|
||||
"appium-logger": "^2.1.0",
|
||||
"appium-selendroid-driver": "^1.2.2",
|
||||
"appium-support": "^2.0.9",
|
||||
"argparse": "^1.0.2",
|
||||
"appium-selendroid-driver": "^1.3.0",
|
||||
"appium-support": "^2.1.0",
|
||||
"argparse": "^1.0.7",
|
||||
"asyncbox": "^2.3.1",
|
||||
"authorize-ios": "^1.0.4",
|
||||
"babel-runtime": "=5.8.24",
|
||||
"bluebird": "^2.9.25",
|
||||
"date-utils": "^1.2.18",
|
||||
"lodash": "^3.9.1",
|
||||
"mobile-json-wire-protocol": "^1.3.2",
|
||||
"npmlog": "^2.0.1",
|
||||
"bluebird": "^2.10.2",
|
||||
"continuation-local-storage": "^3.1.6",
|
||||
"date-utils": "^1.2.19",
|
||||
"lodash": "^4.6.1",
|
||||
"mobile-json-wire-protocol": "^1.3.3",
|
||||
"npmlog": "^2.0.3",
|
||||
"request-promise": "^1.0.2",
|
||||
"source-map-support": "^0.3.2",
|
||||
"teen_process": "^1.5.1",
|
||||
"winston": "^1.0.0"
|
||||
"source-map-support": "^0.4.0",
|
||||
"teen_process": "^1.5.2",
|
||||
"winston": "^2.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "gulp prepublish",
|
||||
@@ -62,15 +64,15 @@
|
||||
"watch": "gulp"
|
||||
},
|
||||
"devDependencies": {
|
||||
"appium-gulp-plugins": "^1.3.12",
|
||||
"chai": "^3.2.0",
|
||||
"chai-as-promised": "^5.0.0",
|
||||
"gulp": "^3.8.11",
|
||||
"mocha": "^2.2.5",
|
||||
"sinon": "^1.14.1",
|
||||
"wd": "~0.3.11"
|
||||
"appium-gulp-plugins": "^1.4.3",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^5.2.0",
|
||||
"gulp": "^3.9.1",
|
||||
"mocha": "^2.4.5",
|
||||
"sinon": "^1.17.3",
|
||||
"wd": "~0.4.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^1.0.6"
|
||||
"fsevents": "^1.0.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ describe('Config', () => {
|
||||
// but also to have access to process methods
|
||||
// so copy them over to a writable object
|
||||
let tempProcess = {};
|
||||
for (let [prop, value] of _.pairs(process)) {
|
||||
for (let [prop, value] of _.toPairs(process)) {
|
||||
tempProcess[prop] = value;
|
||||
}
|
||||
process = tempProcess;
|
||||
|
||||
@@ -71,15 +71,6 @@ describe('AppiumDriver', () => {
|
||||
await appium.createSession(BASE_CAPS);
|
||||
mockFakeDriver.verify();
|
||||
});
|
||||
it('should call inner driver\'s createSession with desired capabilities with string booleans transformed to booleans', async () => {
|
||||
let sentCaps = _.extend({autoAcceptAlerts: 'false', autoDismissAlerts: 'true'}, BASE_CAPS);
|
||||
let expectedCaps = _.extend({autoAcceptAlerts: false, autoDismissAlerts: true}, BASE_CAPS);
|
||||
mockFakeDriver.expects("createSession")
|
||||
.once().withExactArgs(expectedCaps, undefined, [])
|
||||
.returns([1, expectedCaps]);
|
||||
await appium.createSession(sentCaps);
|
||||
mockFakeDriver.verify();
|
||||
});
|
||||
});
|
||||
describe('deleteSession', () => {
|
||||
let appium
|
||||
|
||||
+65
-7
@@ -1,14 +1,72 @@
|
||||
// transpile:mocha
|
||||
|
||||
import { init as logsinkInit } from '../lib/logsink';
|
||||
import logger from '../lib/logger';
|
||||
import { init as logsinkInit, clear as logsinkClear } from '../lib/logsink';
|
||||
import sinon from 'sinon';
|
||||
import { getLogger } from 'appium-logger';
|
||||
|
||||
|
||||
// temporarily turn on logging to stdio, so we can catch and query
|
||||
let forceLogs = process.env._FORCE_LOGS;
|
||||
process.env._FORCE_LOGS = 1;
|
||||
let logger = getLogger('Appium');
|
||||
|
||||
describe('Logger', () => {
|
||||
before(() => {
|
||||
logsinkInit({});
|
||||
let stderrSpy;
|
||||
let stdoutSpy;
|
||||
beforeEach(() => {
|
||||
stderrSpy = sinon.spy(process.stderr, 'write');
|
||||
stdoutSpy = sinon.spy(process.stdout, 'write');
|
||||
logsinkClear();
|
||||
});
|
||||
it('should work', () => {
|
||||
logger.warn('something');
|
||||
logger.debug('something');
|
||||
afterEach(() => {
|
||||
stderrSpy.restore();
|
||||
stdoutSpy.restore();
|
||||
});
|
||||
after(() => {
|
||||
process.env._FORCE_LOGS = forceLogs;
|
||||
});
|
||||
|
||||
const errorMsg = 'some error';
|
||||
const warnMsg = 'some warning';
|
||||
const debugMsg = 'some debug';
|
||||
|
||||
function doLogging () {
|
||||
logger.error(errorMsg);
|
||||
logger.warn(warnMsg);
|
||||
logger.debug(debugMsg);
|
||||
}
|
||||
|
||||
it('should send error, info and debug when loglevel is debug', async () => {
|
||||
await logsinkInit({loglevel: 'debug'});
|
||||
|
||||
doLogging();
|
||||
|
||||
stderrSpy.callCount.should.equal(1);
|
||||
stderrSpy.args[0][0].should.include(errorMsg);
|
||||
|
||||
stdoutSpy.callCount.should.equal(2);
|
||||
stdoutSpy.args[0][0].should.include(warnMsg);
|
||||
stdoutSpy.args[1][0].should.include(debugMsg);
|
||||
});
|
||||
it('should send error and info when loglevel is info', async () => {
|
||||
await logsinkInit({loglevel: 'info'});
|
||||
|
||||
doLogging();
|
||||
|
||||
stderrSpy.callCount.should.equal(1);
|
||||
stderrSpy.args[0][0].should.include(errorMsg);
|
||||
|
||||
stdoutSpy.callCount.should.equal(1);
|
||||
stdoutSpy.args[0][0].should.include(warnMsg);
|
||||
});
|
||||
it('should send error when loglevel is error', async () => {
|
||||
await logsinkInit({loglevel: 'error'});
|
||||
|
||||
doLogging();
|
||||
|
||||
stderrSpy.callCount.should.equal(1);
|
||||
stderrSpy.args[0][0].should.include(errorMsg);
|
||||
|
||||
stdoutSpy.callCount.should.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user