Compare commits

...
Author SHA1 Message Date
Jonathan Lipps a8375b291b bump to 1.6.4 beta 2 2017-03-28 16:32:43 -07:00
Mykola Mokhnach 01d6d1cf9a Add documentation for gestures available under “mobile: *” interface for XCTest-based driver (#8048)
* Add documentation for gestures available under “mobile: *” interface for XCTest-based driver

* Improve the description of pinch arguments

* Add more details about scroll/swipe

* Capitalize header
2017-03-28 16:31:37 -07:00
Dan Cuellar 92bce718ab Add MacDriver (#8046)
* Add MacDriver

* Add MacDriver to version map

* Add some notes about Mac

* Update README.md

* Add section about mac apps.

* Move information to running on OS X page
2017-03-16 16:30:04 -07:00
Dan Graham c237de1e4b Document 'startIWDP' capability (#8024) 2017-03-16 16:30:00 -07:00
Jonathan Lipps d4a4c865c1 update roadmap 2017-03-16 16:29:57 -07:00
Jonathan Lipps b03f3a045e clean up packweb a bit, correct owners 2017-03-16 16:29:54 -07:00
vikramvi 9dc9505c00 updated issue template with clear instructions to provide appium logs in gist format only 2017-03-16 16:29:49 -07:00
Isaac Murchie a6079ff9d2 Add documentation for SafariLauncher 2017-03-16 16:29:44 -07:00
Dan Graham 1263d5755c Documentation for new desired cap: calendarAccessAuthorized (#8001) 2017-03-16 16:29:39 -07:00
Nozomi Ito 7770f8b927 Fix wrong python sample code 2017-03-16 16:29:35 -07:00
Dan Graham 61149c9c0a Fixed broken link in real-devices-ios.md 2017-03-16 16:29:32 -07:00
Isaac Murchie ed6e6b2505 Clean up real device setup docs 2017-03-16 16:29:25 -07:00
Isaac Murchie 74d87250da Move to logger from appium-support 2017-03-02 07:41:36 -05:00
William Candillon fe5f2179fe Update running-tests.md 2017-03-02 07:41:26 -05:00
Bas Broek 1b1d1024cc XCUITest now supports swipe gestures 2017-03-02 07:41:11 -05:00
Bas Broek 2413974517 Fix file url and add language comments 2017-02-21 15:20:02 -05:00
Isaac Murchie c0ed34cad9 Fix formatting of default capabilities 2017-02-21 15:19:54 -05:00
Dan Graham 51549ccf16 Don't allow undefined process.argv[1] in parser
argParse breaks if process.argv[1], which is a problem if Appium is being run as a binary. Added check so that if process.argv[1] is undefined, set the prog name to 'Appium'
2017-02-21 15:19:41 -05:00
Jonathan Lipps e2f8d2e13f add google summer of code ideas doc 2017-02-21 15:19:32 -05:00
Isaac Murchie 3585978c36 Fix CLA link in PR template 2017-02-21 15:19:23 -05:00
Bas Broek 405afe065b Remove unnecessary punctuation 2017-02-21 15:19:13 -05:00
Bas Broek 62c66c32ea Fix typos in Issue Template 2017-02-21 15:19:05 -05:00
Brian Heim fc024bd2cb fix typo in running-on-osx.md 2017-02-21 15:18:56 -05:00
Isaac Murchie 53f283f03d Bump version for 1.6.4-beta 2017-02-01 12:46:30 -05:00
Isaac Murchie 2da45d2154 Update ChangeLog for 1.6.4 beta release 2017-02-01 10:02:20 -05:00
Dan Graham e4bfd7c9cf Add swiping documentations
I kept it simple and just instructed the reader to replace 'mobile: scroll' with 'mobile: swipe'. Since the two have the exact same API, no sense in maintaining both sets of instructions.
2017-02-01 09:50:29 -05:00
Isaac Murchie f3c4817bfa Add version string to driver announcement 2017-02-01 09:50:20 -05:00
Jonathan Lipps fb3ef327a0 make the auto-scrolling API difference more prominent in migration doc 2017-02-01 09:50:10 -05:00
h3dkandi 3991ba3f79 Update troubleshooting.md
Make people check if their keychain is unlocked.
[Link](https://github.com/appium/appium/issues/7705) to issue inspiring this change.
2017-02-01 09:50:01 -05:00
Jonathan Lipps e2a5546be1 make a note about building PickerWheels appropriately 2017-02-01 09:49:44 -05:00
Jonathan Lipps 16af4f49f4 update roadmap 2017-02-01 09:19:44 -05:00
Jonathan Stoneman 88685dcb69 Replace IOSDriver with WindowsDriver 2017-02-01 09:16:38 -05:00
Isaac Murchie 5a5748cb16 Once catch signals once 2017-02-01 09:16:28 -05:00
Isaac Murchie cdabc1cea7 Update XCUITest caps 2017-02-01 09:16:16 -05:00
Jonathan Lipps deaf7c4835 add note about swipe 2017-02-01 09:16:06 -05:00
Jonathan Lipps b3f3b2132b add note about tapping outside the frame in xcuitest migration doc 2017-02-01 09:15:57 -05:00
Isaac Murchie 47166af12c Add note about autoAcceptAlerts and autoDismissAlerts for XCUITest 2017-02-01 09:15:02 -05:00
Jonathan Lipps 74e6419ab7 remove npm-shrinkwrap post 1.6.3 publish 2016-12-13 08:04:20 -08:00
Jonathan Lipps f95eb6c4f5 re-add shrinkwrap for publish 2016-12-12 10:16:23 -08:00
Jonathan Lipps 00aab07e2c update changelog 2016-12-12 09:30:02 -08:00
Jonathan Lipps d8fcc7d850 re-add shrinkwrap for publish 2016-12-09 16:39:04 -08:00
Jonathan Lipps d027f64700 update changelog 2016-12-09 16:23:02 -08:00
Jonathan Lipps ce479a577d add autoGrantPermissions capability in docs 2016-12-09 14:16:30 -08:00
Jonathan Lipps 2ddb1208f4 add webDriverAgentUrl capability in docs 2016-12-09 10:40:41 -08:00
Jonathan Lipps df2a2a3da0 refactor unexpected shutdown, and fix lint so we can use upgraded appium eslint 2016-12-07 15:24:18 -08:00
Jonathan Lipps e10bb290ea ensure esling-plugin-promise is available 2016-12-07 15:24:14 -08:00
Jonathan Lipps f0f71faa15 bump version for 1.6.3 2016-12-07 15:24:09 -08:00
Jonathan Lipps 964a511be9 add changelog for 1.6.3 2016-12-07 15:24:02 -08:00
Jonathan Lipps 8e9252f12e change semver refs in package.json to be more transparent 2016-12-07 15:23:17 -08:00
shoma c57d17541e Remove duplicate trailing in jshintrc for test 2016-12-06 17:07:46 -08:00
Kazuaki Matsuo 757c20e486 fix back quote 2016-12-06 17:07:41 -08:00
Jonathan Lipps 696e4dea3f bump version for 1.6.2 2016-12-01 15:39:52 -08:00
Jonathan Lipps 2c52e4661c update changelog for 1.6.2 2016-12-01 13:20:05 -06:00
Alexander Sorokin 11f5a0f5c0 Fixed the "Windows App Testing" link in the docs 2016-12-01 13:20:05 -06:00
Mykola Mokhnach ea4e55ad20 Add documentation for the newly added xcuitest capability 2016-12-01 13:20:05 -06:00
Julia 215c649545 Update appium-bindings.md 2016-12-01 13:20:05 -06:00
Jonathan Lipps c05fd69088 set version to 1.6.1 2016-11-24 14:44:40 -08:00
Jonathan Lipps 369946f5c8 update 1.6.1 changelog 2016-11-24 12:34:09 -08:00
Dan Graham 3f273bd5f7 Dan certificate documentation (#7289)
document customSSLCert capability
2016-11-24 10:26:00 -08:00
h3dkandi b1a39ec8f0 spelling mistake of JSON key 2016-11-24 10:26:00 -08:00
Isaac Murchie 5486055fd3 Add note about pinch in xcuitest 2016-11-24 10:26:00 -08:00
rkavalap 0fd38c8ab1 Updating NodeJS versions in travis 2016-11-24 10:18:19 -08:00
Isaac Murchie 65d8f4a606 Add note about lock, shake, location in xcuitest 2016-11-24 10:18:19 -08:00
Mykola Mokhnach c0f3d7a311 Add scaleFactor capability description 2016-11-24 10:18:19 -08:00
Anton Kuznetsov aaad6acaa9 Direction value should be string for mobile scroll 2016-11-24 10:18:19 -08:00
Anton Kuznetsov 30629133ec Update touch-actions.md 2016-11-24 10:18:19 -08:00
Dan Graham f1f821c44d Document '-ios predicate string' locator strategy (#7164)
* Document '-ios predicate string' locator strategy

Includes a Java example showing how to use predicate string in appium; documents the iOS version support
2016-11-24 10:17:58 -08:00
Isaac Murchie 5817d3125a v1.6.1-beta 2016-11-04 11:28:18 -07:00
Isaac Murchie 41a4c33fdc Remove shrinkwrap for beta release 2016-11-04 11:23:51 -07:00
Isaac Murchie d7f9dba9a1 1.6.1 beta changelog 2016-11-04 11:21:48 -07:00
Dan Graham a66e159cc2 Document '-ios predicate string' locator strategy (#7164)
* Document '-ios predicate string' locator strategy

Includes a Java example showing how to use predicate string in appium; documents the iOS version support
2016-11-04 10:52:54 -07:00
Jonathan Lipps 74dfda9a8d update roadmap with priorities and links to epics 2016-11-04 10:52:46 -07:00
Jonathan Lipps 84377d91fe mention that we use zenhub for project management 2016-11-04 10:52:38 -07:00
Jonathan Lipps 60c7d73c39 update license and add note about appium agile process 2016-11-04 10:52:29 -07:00
Mykola Mokhnach 939fff4c91 Format one more example 2016-11-04 10:52:16 -07:00
Mykola Mokhnach 19fd7646a4 Cut underscores 2016-11-04 10:52:08 -07:00
Mykola Mokhnach aa295a481e Better formatting for examples 2016-11-04 10:51:59 -07:00
Mykola Mokhnach faabdc1942 Add recommendations for using xpath locators in XCUITest mode 2016-11-04 10:51:49 -07:00
Jonathan Lipps 0a80b7f5ac basic refresh of docs, just small edits for accuracy and completeness 2016-11-04 10:51:37 -07:00
Rubén González Alonso 2e9181db93 Fix grid register with Selenium 3 hubs 2016-11-04 10:51:28 -07:00
Rubén González Alonso 657a83bdcb Allow to connect an Appium node to Selenium Grid 3 2016-11-04 10:51:20 -07:00
Chris Kruger e5ca5b55fc graceful handling of SIGTERM and SIGINT such that return codes are more in line Unix process exit codes 2016-11-04 10:51:06 -07:00
Alex Lau 6624802ece Fix --suppress-adb-kill-server command line argument 2016-11-04 10:49:58 -07:00
Isaac Murchie 790d9e8df0 Add shrinkwrap for publish 2016-10-10 15:05:02 -04:00
Isaac Murchie ec3e0bc7b3 1.6.0 2016-10-07 16:54:27 -04:00
71 changed files with 1418 additions and 632 deletions
+7 -5
View File
@@ -14,17 +14,19 @@ Briefly describe the issue you are experiencing (or the feature you want to see
## Details
Describe in more detail the problem you have been experiencing, if necessary.
If necessary, describe the problem you have been experiencing in more detail.
## 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!
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 remember that with sample code it's easier to reproduce the bug and it's 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.
Please git clone https://github.com/appium/sample-code and use one of your favourite languages and sample apps to reproduce the issue.
In case a similar scenario is missing in sample-code, please submit a PR with one of the sample apps provided.
In case a similar scenario is missing in sample-code, please submit a PR with one of the sample apps provided.
+1 -1
View File
@@ -16,7 +16,7 @@ _Put an `x` in the boxes that apply_
_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._
- [ ] I have read the [CONTRIBUTING](/CONTRIBUTING.md) doc
- [ ] I have signed the [CLA](https://docs.google.com/forms/d/1lOfXRw_0VCk7gYzjj4WLetGu7yelDVo5LWh0z7pGftE/viewform)
- [ ] I have signed the [CLA](https://cla.js.foundation/appium/appium)
- [ ] Lint and unit tests pass locally with my changes
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] I have added necessary documentation (if appropriate)
+2 -1
View File
@@ -1,7 +1,8 @@
language: node_js
sudo: false
node_js:
- "stable"
- "7"
- "6"
- "4"
script:
- npm run lint
+210
View File
@@ -1,3 +1,213 @@
CHANGES IN VERSION 1.6.4 Beta (from 1.6.3)
===================================
**Note:** This is a **_BETA_** release. Please direct any issues to the [Appium
issue tracker](https://github.com/appium/appium/issues) and provide as much
information as possible.
#### General
* Fixed `UnhandledPromiseRejection` errors when running Appium with Node version
7
* Better indicate missing necessary programs to users
* Fix session creation logging
* Fix server shutdown on `SIGINT` and `SIGTERM` signals
* Ensure that all requests have `application/json` content-type
#### iOS
* Fix issues with error handling in Safari/Webview handling
* Increase simulator launch timeout for iOS 10+
* Better handling of page selection in Safari
* Fix memory usage issues when device logs get large
#### iOS - XCUITest
* Changed the way the Appium checks that WebDriverAgent is running on the device,
so that rather than searching the logs, the device is pinged until it is
ready.
- Removed `realDeviceLogger` capability, since we no longer check the logs
* Add `useNewWDA` capability, which forces uninstall of the WDA app from the
device before each session
* Add `wdaLaunchTimeout` capability, which specified the time, in `ms`, to wait
for WDA to be loaded and launched on the device
* Allow for the auto-generation of the Xcode config file used to configurable
WDA before launch. This includes _two_ new desired capabilities
- `xcodeOrgId` - the Apple developer team identifier string
- `xcodeSigningId` - a string representing a signing certificate, defaulting to
"iPhone Developer"
* Allow for automatic changing of bundle id for WDA in cases where a
provisioning profile cannot be made for default bundle
- add `updatedWDABundleId` capability to specify bundle id for which there is
a valid provisioning profile
* Speed up setting the value of text fields
* Add `wdaConnectionTimeout` to control how long the server waits for WDA to
allow connections
* Fix handling of local port on real devices
* Speed up Safari interactions
* Fix session deletion to ensure that clean up happens
* Add `mobile: swipe` execute method
* Ensure that scrolling through `mobile: scroll` works in web context
#### Android
* Default installation to ChromeDriver 2.26
* Add device manufacturer, model, and screen size to session details
* Fix bug in checking avd status on some systems
* Allow wildcards in `appWaitActivity` capability
#### Android - Selendroid
* Fix handling of host binary configuration for more precise installation options
CHANGES IN VERSION 1.6.3 (from 1.6.2)
===================================
_This is another emergency release due to an issue with the NPM shrinkwrap_
#### iOS
* Fix issue where we might try and uninstall an ssl cert from a real device
where this isn't sensible
* Fix another issue with acceptSslCerts where it might potentially miss the
correct sim UDID
#### iOS - XCUITest
* Upgrade version of WebDriverAgent used. Includes following updates:
* Improve xpath query performance
* Verify predicates
* Fix crash for some xpath selectors
* Decorate proxied getSession response with Appium's capabilities (fixes
issues with clients that call getSession to determine server capabilities
and are confused by WDA's non-standard response) ([#7480](https://github.com/appium/appium/issues/7480))
* Fix issue with starting XCUITests on a real device, due to changes in WDA
that invalidated our startup detection logic. ([#7313](https://github.com/appium/appium/issues/7313))
* Allow connecting to an already-running WebDriverAgent through the
`webDriverAgentUrl` capability, rather than starting our own
#### Android
* Fix bug where we would attempt to get target SDK version from manifests
even when they might not include it. ([#7353](https://github.com/appium/appium/issues/7353))
* Actually pass the `acceptSslCerts` capability to the underlying automation
so that it can have an effect ([#7326](https://github.com/appium/appium/issues/7326))
* Updated permission granting logic to speed up permission granting by doing
it in bulk rather than one at a time ([#7493](https://github.com/appium/appium/issues/7493))
* Hide the new permission granting logic behind an `autoGrantPermissions`
capability which doesn't attempt to grant permissions unless it's `true`
([#7497](https://github.com/appium/appium/issues/7497))
#### Android - Uiautomator2
* Add ability to verify TOAST messages (these can't be interacted with, only
text retrieval allowed)
#### Windows
* _Actually_ upgrade WinAppDriver to 0.7 ([#7445](https://github.com/appium/appium/issues/7445)). Includes following updates:
* Click on arbitrary elements
* Support for sendKeys modifiers
* Various bugfixes
* Added `GET /orientation`
* Added support for WPF apps
CHANGES IN VERSION 1.6.2 (from 1.6.1)
===================================
_This is a small, mostly-emergency release because we realized we omitted
XCUITest upgrades via WebDriverAgent that we had mistakenly presumed were part
of 1.6.1._
#### iOS - XCUITest
* Upgrade version of WebDriverAgent used. Includes following updates:
* Support for setting values on sliders
* Fix tapping in various orientations
* Allow tapping on arbitrary coordinates
* Support for pinch gestures
* Make `clear` faster
* Improve xpath query performance
* Add `preventWDAAttachments` capability to help with XCUITest speed and disk usage
#### Android - UiAutomator2
* Code refactoring to pave the way for some UiAutomator2 wifi automation work
* Find an unused system port automatically to avoid port clashes
#### Windows
* Upgrade WinAppDriver to 0.7. Includes following updates:
* Click on arbitrary elements
* Support for sendKeys modifiers
* Various bugfixes
* Added `GET /orientation`
* Added support for WPF apps
CHANGES IN VERSION 1.6.1 (from 1.6.0)
===================================
Appium 1.6.1 is the first release since bringing Appium into the [JS Foundation](https://js.foundation/)
(see [press release](https://js.foundation/announcements/2016/10/17/Linux-Foundation-Unites-JavaScript-Community-Open-Web-Development/)).
Much of the development energy has been spent on fixing issues that have come up
from the newly-integrated XCUITest and UI Automator 2 vendor-provided test
backends.
#### General
* Add `clearSystemFiles` desired capability, to specify whether to delete any generated
files at the end of a session (see iOS and Android entries for particulars)
* Better handle signals for stopping server
* Fix operation of Selenium 3 Grid
* Log more of the proxied requests and responses, for better debugging
* Better handle source mapping for IDE support
* Move `appium-doctor` into globally-installed utility, not bundled with server
* Move `appium-logger` into `appium-base-driver`
* Better handle downloading of zip files which may not have a `.zip` extension (like `.apk`)
##### iOS
* Add support for iOS 10.1
* Add support for iOS 10.2 Beta 1
* Add `clearSystemFiles` desired capability to specify whether to Core Simulator
files, and Instruments (for iOS Driver) or XCUITest (for XCUITest Driver) generated files
* Ensure correct files are tested when checking for Simulator newness
* Map `iPad Simulator` `deviceName` to iPad Retina instead of discontinued iPad 2
* Gracefully return when Webkit Remote Debugger doesn't return on a real device
* Better log errors from xcode handling
* Add `customSSLCert` capability to pre-authorize a specific SSL cert in the iOS trust store
* During reset, don't try to uninstall an app from a real device if it's not installed
##### iOS - XCUITest specific
* clean up logging to remove confusing "Waiting..." lines
* Fix issue in which switching to NATIVE_APP would still proxy find commands to Remote debugger
* Fix handling of Selenium Grids
* Correctly handle long press so duration is respected
* Add `tapWithShortPressDuration` desired capability to specify a length for tapping,
if the regular tap is too long for the app under test
* Add support for scrolling through Touch Actions
* Make sure keyboard is available when keys are sent to Text Fields
* Add support for Zoom via Touch Action API (Pinch still not supported by Apple)
* Fix implementation of double tap
* Improvements in startup flow for real devices
* Allow gestures on coordinates, not just elements
* Add `scaleFactor` capability to direct Appium to set the simulator scale
##### Android
* Use ChromeDriver version 2.25
* Correctly handle `--suppress-adb-kill-server` command line argument
* Pass actual failure back when session fail and deleting the session also fails
* Add `clearSystemFiles` desired capability to specify whether to delete temporary
copies of the application under test at the end of the session
* Fix issue where finding UI Automator process id would throw an error
* Add `chromeAndroidPackage` capability which will be passed to `chromeOptions`
* Add APIs for gathering various kinds of performance data
* Ensure we don't try to stop app if `dontStopAppOnReset` is in force
* Fix issue where we tried to determine the bounds of a non-existent element
##### Android - UiAutomator2
* Fix handling of element attributes
* Better handle element finding
* Toast message verification support
* Ensure that there is a <hierarchy> root tag for xml/xpath source
* Implement /rotation endpoint (supports 4 rotations)
CHANGES IN VERSION 1.6.0 (from 1.5.3)
===================================
+16
View File
@@ -0,0 +1,16 @@
Google Summer of Code Ideas
=====
Appium is excited to participate as a [Google Summer of Code](https://summerofcode.withgoogle.com/) sponsor project. Here's a fun list of ideas that a Summer of Code student participant can use as a foundation for thinking about what to contribute to Appium!
|Idea|Description|
|----|-----------|
|Apple tvOS Support|Our users have been asking for an Appium driver for Apple tvOS apps. Is this possible? We're not entirely sure! Why not be awesome and build it?|
|Test App revamp|Appium uses a number of poorly-designed mobile applications in its own testing. We have to use a variety of apps because we need to test that Appium can automate all the various controls and platform features that mobile vendors provide. Really what we need is one cross-platform app (or one app per platform) that exhibit all and only the features we need to test. This would be a fun project to build some mobile apps used for testing and also demoing Appium at events and in training videos, etc...|
|Tooling and Performance|We haven't instrumented Appium with very many performance metrics, and don't really know if we're missing some low-hanging fruit in terms of performance. Maybe you can help us do that?|
|Babel|We have a lot of repos, and they're all on a really old version of Babel. They all need to stay in sync. How can we make this situation better, and upgrade to the latest and greatest?|
|Unity3d Driver|Historically, Appium hasn't been great at automating games. We don't have any particular support for the frameworks used to create games. Unity is a popular one, for example. What if we could write an Appium driver that talked to an embedded process in a test version of a Unity game, that allowed us to find and interact with 3d elements? It would be amazing! You can also be amazing and lead Appium into this new world.|
|Testing the Internet of Things|Appium's architecture makes it dead simple to integrate drivers for automating new technologies. What about _really_ new technologies like IoT devices? Help to redefine the semantics of the WebDriver protocol for use with IoT, and build a driver for an IoT device to prove it out.|
|Driver for X|Have an idea of something else Appium could automate that it doesn't already? Build a driver for it! This would involve some awesome Node.js code, plus whatever else is needed to integrate with the platform you have in mind.|
Hopefully this gives you some ideas of fun projects that would be substantial and long-lasting contributions to the Appium community.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2012-2016 Sauce Labs, Inc.
Copyright 2012-2016 JS Foundation and other contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+23 -15
View File
@@ -10,7 +10,7 @@
[![Build Status](https://team-appium.ci.cloudbees.com/job/Appium/badge/icon)](https://team-appium.ci.cloudbees.com/job/Appium/)
Appium is an open source, cross-platform test automation tool for native, hybrid and mobile web apps, tested on simulators (iOS, FirefoxOS), emulators (Android), and real devices (iOS, Android, Windows, FirefoxOS).
Appium is an open source, cross-platform test automation tool for native, hybrid and mobile web and desktop apps, tested on simulators (iOS), emulators (Android), and real devices (iOS, Android, Windows, Mac).
### Supported Platforms
@@ -18,7 +18,7 @@ Appium is an open source, cross-platform test automation tool for native, hybrid
* iOS
* Android
* Windows
* FirefoxOS
* Mac
See the [platform support doc](/docs/en/appium-setup/platform-support.md) for more detailed information.
@@ -77,15 +77,16 @@ You also need to download the Appium client for your language so you can write t
* [linux](/docs/en/appium-setup/running-on-linux.md)
* [osx](/docs/en/appium-setup/running-on-osx.md)
* [windows](/docs/en/appium-setup/running-on-windows.md)
#### Windows Requirements
* Windows 10
* [Documentation](/docs/en/appium-setup/running-on-windows.md)
#### FirefoxOS Requirements
#### Mac Requirements
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
* Mac OS X 10.7 +
* [Documentation](https://github.com/penguinho/appium/blob/mac-driver/docs/en/appium-setup/running-on-osx.md#testing-mac-apps)
### Quick Start
@@ -99,7 +100,14 @@ $ npm install -g appium
$ appium
```
#### Using the App
As we said above, you may want to run `appium-doctor` to ensure your system is set up properly:
```
$ npm install -g appium-doctor
$ appium-doctor
```
#### Using the Appium Desktop App
* [Download the Appium app](https://bitbucket.org/appium/appium.app/downloads/)
* Run it!
@@ -108,6 +116,8 @@ $ 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).
(*Note*: If you're automating iOS 10+, be sure to check out our [XCUITest Migration Guide](/docs/en/advanced-concepts/migrating-to-xcuitest.md) since Apple's automation support has changed significantly since iOS 10, with corresponding changes in 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.
@@ -124,18 +134,15 @@ For the full list of Appium doc pages, visit [this directory](/docs/en/).
Appium drives various native automation frameworks and provides an API based on
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.
For new iOS versions (9.3 and up), Appium drives Apple's XCUITest library. Our support for XCUITest utilizes Facebook's [WebDriverAgent](https://github.com/facebook/webdriveragent) project.
For older iOS versions (9.3 and below), Appium drives Apple's UIAutomation library, using a strategy which is based on [Dan Cuellar's](http://github.com/penguinho) work on iOS Auto.
Android support uses the UiAutomator framework for newer platforms and
[Selendroid](http://github.com/DominikDary/selendroid) for older Android platforms.
Windows support uses Microsoft's [WinAppDriver](https://github.com/Microsoft/WinAppDriver)
FirefoxOS support leverages [Marionette](https://developer.mozilla.org/en-US/docs/Marionette),
an automation driver that is compatible with WebDriver and is used to automate
Gecko-based platforms.
### Contributing
Please take a look at our [contribution documentation](CONTRIBUTING.md)
@@ -145,11 +152,12 @@ for instructions on how to build, test and run Appium from source.
Interested in where Appium is heading in the future? Check out the [Roadmap](ROADMAP.md)
### Project Credits & Inspiration
### Project History, Credits & Inspiration
[Credits](/docs/en/contributing-to-appium/credits.md)
* [History](http://appium.io/history)
* [Credits](/docs/en/contributing-to-appium/credits.md)
### Mailing List
### User Forums
Announcements and debates often take place on the [Discussion Group](https://discuss.appium.io), be sure to sign up!
+20 -10
View File
@@ -17,31 +17,41 @@ exists to outline large-scale future plans for Appium.
| Project | Description | ETD | Projected Appium Release |
|---------|-------------|-----|--------------------------|
|[Architecture Overhaul](https://github.com/appium/appium/issues/5169)|Appium's architecture has grown unwieldy enough that adding new features and preventing regressions has become difficult. A rearchitecture is in order to solve these issues as well as migrate the codebase to a form of JS much easier to work in and understand.|1/2016|1.5|
|XCUITest backend integration|Instruments + UIAutomation has been working well for many Appium users, but requires crazy workarounds to deal with bugs which remain unfixed on the Apple side. We should explore Apple's newer technology, XCUITest, in order to see if the overall experience is more stable. This new backend would exist alongside the UIAutomation backend.|3/2016?|Beta in 1.6?|
|UiAutomator2 backend integration|Google has released [UiAutomator 2](http://developer.android.com/reference/android/support/test/uiautomator/package-summary.html), and it promises to fix some issues and limitations with the previous UiAutomator support. We will build this inside of Selendroid since it requires an instrumentation context.|3/2016?|TBD|
|iOS 9.3 support|Appium should support iOS 9.3 / Xcode 7.3|2/2016|1.6?||
|[Appium CI + Metrics Improvements](https://github.com/appium/appium/issues/7168)|We have CI servers running via Cloudbees that we don't understand and which break. Let's document and own them so they work reliably. Also, let's implement gathering various metrics about driver performance so we can track this over time and ensure we're not releasing a driver which has decreased in performance or reliability.|Q2 2017|N/A|
## Upcoming Projects (in rough order of priority)
| Project | Description |
|---------|-------------|
|Apple Watch support|Appium should support Apple Watch apps via the Watch simulator|
|Onboarding Overhaul|The current Appium docs leave a lot to be desired. The format is confusing (it would be better for API docs), the content is outdated, and many things are still undocumented. This project would go back to the drawing board in all of these areas and put together something genuinely helpful for the community, which hopefully reduces the kind of support issues we're currently flooded by.|
|New Appium GUIs|The current Appium GUIs (Appium.app and Appium.exe) have a number of issues. They aren't maintained by the core Appium team. They're written in Objective-C and C# respectively: two languages, and specifically, two languages other than Appium's core language. Because of this they lag behind the Appium server and are often broken. However, users love them primarily because of the Inspector feature (the thing that lets them graphically navigate their app), so we have to field a ton of complaints about these projects. There's an opportunity to start over. With [Electron](http://electron.atom.io/), we'd be able to take the new version of Appium we're working on and embed it directly inside a Node-based GUI app written using the languages and technologies the core team is experienced with. We'd have one codebase and could distribute the app on Mac, Windows, and Linux. The GUIs would become an official part of Appium's release cycle so they wouldn't be broken.|
|Unity3d backend POC|This is a research project to determine whether we can add some kind of support for 3d game automation, probably based on the Unity3d game development platform.|
|Dynamic Test App|Our current test applications (the ones used to test Appium's iOS and Android support) are not ideal. We use too many of them and the ones we use have a random hodgepodge of app SDK features, sometimes not enough to sufficiently test automation support. Using [Titanium](https://github.com/appcelerator/titanium_mobile), we can develop an app that allows us to inject whatever native code we need, as we need it. The app thus changes itself test-by-test to have whatever UI features we need for that particular test. It gives us much more fine-grained control over what we're testing. The app code would also be cross-platform and written in JS, which would make it easier for the core team to write and maintain.|
|[Onboarding Overhaul](https://github.com/appium/appium/issues/7169)|The current Appium docs leave a lot to be desired. The format is confusing (it would be better for API docs), the content is outdated, and many things are still undocumented. This project would go back to the drawing board in all of these areas and put together something genuinely helpful for the community, which hopefully reduces the kind of support issues we're currently flooded by.|
|[Appium Client Library Updates](https://github.com/appium/appium/issues/7170)|It's been too long since we ensured that Appium's client libraries were up to date with the server|
|[Sample Code Overhaul](https://github.com/appium/appium/issues/7171)|Our sample code repo has grown tangled and broken. Let's make a new one with minimal examples which are the same across every language, and actually maintain the repo so as not to let it become overgrown.|
|[Test App Overhaul](https://github.com/appium/appium/issues/7172)|Our current test applications (the ones used to test Appium's iOS and Android support) are not ideal. We use too many of them and the ones we use have a random hodgepodge of app SDK features, sometimes not enough to sufficiently test automation support. It'd be great to find a way to ensure our test app(s) have all the features we need to test, and keep in sync with our requirements.|
|[iOS Test Startup Time Improvement](https://github.com/appium/appium/issues/7173)|iOS startup times have gotten progressively longer with each iOS release. In part this is Apple's fault and there's not anything we can do about it. But we should investigate and see if we can be more efficient in how we start, especially given that we can now focus on XCUITest and leave Instruments behind|
|[Appium Dearchitecture](https://github.com/appium/appium/issues/7174)|OK, we went a bit overboard in Appium 1.5 by exploding Appium into 40+ repos and NPM packages. Let's think a little more critically about it and consolidate into the minimal number of repos/packages that make sense for our code and community patterns.|
|[Appium 2.0](https://github.com/appium/appium/issues/7175)|Appium, rather than bundling all the separate drivers by default, becomes a driver management interface (in addition to continuing to play the role of automation frontend server). Appium gets a set of CLI tools for users to pick and choose which drivers and versions of drivers they want to use via Appium|
## Projects Under Consideration (unprioritized)
## Projects Under Consideration (unplanned and unprioritized)
| Project | Description |
|---------|-------------|
|Windows Phone Support|There has been some work done on automating Windows Phone apps. We could take this all the way to integration with Appium in the form of a WindowsDriver.|
|Apple Watch support|Appium should support Apple Watch apps via the Watch simulator|
|Unity3d backend POC|This is a research project to determine whether we can add some kind of support for 3d game automation, probably based on the Unity3d game development platform.|
## Completed Roadmap Projects
| Project | Description | Completed | Appium Release | Notes |
|---------|-------------|-----------|----------------|-------|
|[New Appium GUIs](https://github.com/appium/appium/issues/7167)|The current Appium GUIs (Appium.app and Appium.exe) have a number of issues. They aren't maintained by the core Appium team. They're written in Objective-C and C# respectively: two languages, and specifically, two languages other than Appium's core language. Because of this they lag behind the Appium server and are often broken. However, users love them primarily because of the Inspector feature (the thing that lets them graphically navigate their app), so we have to field a ton of complaints about these projects. There's an opportunity to start over. With [Electron](http://electron.atom.io/), we'd be able to take the new version of Appium we're working on and embed it directly inside a Node-based GUI app written using the languages and technologies the core team is experienced with. We'd have one codebase and could distribute the app on Mac, Windows, and Linux. The GUIs would become an official part of Appium's release cycle so they wouldn't be broken.|3/2017|N/A|[Appium Desktop website](https://github.com/appium/appium-desktop)|
|[Android 7.1.1 Support](https://github.com/appium/appium/issues/7165)|Google has released Android 7.1.1 (API Level 25). Ensure it works with UiAutomator 1/2|2/2017|1.6.4||
|[Android 7.0 Support](https://github.com/appium/appium/issues/7156)|Support Android 7 (Nougat)|11/2016|1.6.3||
|[iOS 10.2 Support](https://github.com/appium/appium/issues/7166)|Support iOS 10.2|11/2016|1.6.1||
|[iOS 10.1 Support](https://github.com/appium/appium/issues/7105)|Support iOS 10.1|11/2016|1.6.1||
|UiAutomator2 integration|Google has released [UiAutomator 2](http://developer.android.com/reference/android/support/test/uiautomator/package-summary.html), and it promises to fix some issues and limitations with the previous UiAutomator support. We will build this inside of Selendroid since it requires an instrumentation context.|10/2016?|1.6.0|
|XCUITest integration / iOS 10 support|Instruments + UIAutomation has been working well for many Appium users, but requires crazy workarounds to deal with bugs which remain unfixed on the Apple side. Also, UIAutomation has been removed in favor of XCUITest for iOS 10+. This new backend would exist alongside the UIAutomation backend.|10/2016|1.6.0||
|iOS 9.3 support|Appium should support iOS 9.3 / Xcode 7.3|3/2016|1.5.1||
|[Architecture Overhaul](https://github.com/appium/appium/issues/5169)|Appium's architecture has grown unwieldy enough that adding new features and preventing regressions has become difficult. A rearchitecture is in order to solve these issues as well as migrate the codebase to a form of JS much easier to work in and understand.|2/2015|1.5.0||
|iOS 9.2 support|Appium should support iOS 9.2 / Xcode 7.2|11/2015|1.4.14||
|iOS 9.1 support|Appium should support iOS 9.1 / Xcode 7.1|10/2015|1.4.12||
|iOS 9.0 support|Appium should support iOS 9.0 / Xcode 7.0|10/2015|1.4.11||
+4 -10
View File
@@ -1,13 +1,6 @@
## Introduction to Appium
Appium is an open-source tool for automating native,
mobile web, and hybrid applications on iOS and Android platforms.
**Native apps** are those written using the iOS, Android, or Windows SDKs. **Mobile web apps** are web apps accessed using a mobile browser (Appium supports
Safari on iOS and Chrome or the built-in 'Browser' app on Android). **Hybrid apps** have a
wrapper around a "webview" -- a native control that enables interaction with
web content. Projects like [Phonegap](http://phonegap.com/),
make it easy to build apps using web technologies that are then bundled into
a native wrapper, creating a hybrid app.
Appium is an open-source tool for automating native, mobile web, and hybrid applications on iOS mobile, Android mobile, and Windows desktop platforms. **Native apps** are those written using the iOS, Android, or Windows SDKs. **Mobile web apps** are web apps accessed using a mobile browser (Appium supports Safari on iOS and Chrome or the built-in 'Browser' app on Android). **Hybrid apps** have a wrapper around a "webview" -- a native control that enables interaction with web content. Projects like [Phonegap](http://phonegap.com/), make it easy to build apps using web technologies that are then bundled into a native wrapper, creating a hybrid app.
Importantly, Appium is "cross-platform": it allows you to write tests against
multiple platforms (iOS, Android, Windows), using the same API. This enables code reuse between iOS, Android, and Windows testsuites.
@@ -31,10 +24,11 @@ meet requirement #1 by using vendor-provided automation frameworks under the
hood. That way, we don't need to compile in any Appium-specific or
third-party code or frameworks to your app. This means **you're testing the same app you're shipping**. The vendor-provided frameworks we use are:
* iOS: Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)
* iOS 9.3 and above: Apple's [XCUITest](https://developer.apple.com/reference/xctest)
* iOS 9.3 and lower: Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)
* Android 4.2+: Google's [UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)
* Android 2.3+: Google's [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). (Instrumentation support is provided by bundling a separate project, [Selendroid](http://selendroid.io))
* Windows: Microsoft's [WinAppDriver](http://github.com/microsoft/winappdriver)
* Windows: Microsoft's [WinAppDriver](http://github.com/microsoft/winappdriver)
We meet requirement #2 by wrapping the vendor-provided frameworks in one API,
the [WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.
+25 -25
View File
@@ -31,18 +31,18 @@ Here are the steps required to talk to a web view in your Appium test:
// javascript
// assuming we have an initialized `driver` object for an app
driver
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
return driver.context(contexts[1]); // choose the webview context
})
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
return driver.context(contexts[1]); // choose the webview context
})
// do some web testing
.elementsByCss('.green_button').click()
// do some web testing
.elementsByCss('.green_button').click()
.context('NATIVE_APP') // leave webview context
.context('NATIVE_APP') // leave webview context
// do more native stuff here if we want
// do more native stuff here if we want
.quit() // stop webdrivage
.quit() // stop webdrivage
```
```java
@@ -52,7 +52,7 @@ driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities)
Set<String> contextNames = driver.getContextHandles();
for (String contextName : contextNames) {
System.out.println(contextNames); //prints out something like NATIVE_APP \n WEBVIEW_1
System.out.println(contextNames); //prints out something like NATIVE_APP \n WEBVIEW_1
}
driver.context(contextNames.toArray()[1]); // set context to WEBVIEW_1
@@ -76,18 +76,18 @@ driver.quit();
# Then switch to it using @driver.switch_to.context("WEBVIEW_6")
Given(/^I switch to webview$/) do
webview = @driver.contexts.last
@driver.switch_to.context(webview)
webview = @driver.contexts.last
@driver.switch_to.context(webview)
end
Given(/^I switch out of webview$/) do
@driver.switch_to.context(@driver.contexts.first)
@driver.switch_to.context(@driver.contexts.first)
end
# Now you can use CSS to select an element inside your webview
And(/^I click a webview button $/) do
@driver.find_element(:css, ".green_button").click
@driver.find_element(:css, ".green_button").click
end
```
@@ -116,23 +116,23 @@ driver.quit()
public function testThings()
{
$expected_contexts = array(
0 => 'NATIVE_APP',
1 => 'WEBVIEW_1'
);
$expected_contexts = array(
0 => 'NATIVE_APP',
1 => 'WEBVIEW_1'
);
$contexts = $this->contexts();
$this->assertEquals($expected_contexts, $contexts);
$contexts = $this->contexts();
$this->assertEquals($expected_contexts, $contexts);
$this->context($contexts[1]);
$context = $this->context();
$this->assertEquals('WEBVIEW_1', $context);
$this->context($contexts[1]);
$context = $this->context();
$this->assertEquals('WEBVIEW_1', $context);
// do webby stuff
// do webby stuff
$this->context('NATIVE_APP');
$this->context('NATIVE_APP');
// do mobile stuff
// do mobile stuff
}
```
@@ -50,12 +50,27 @@ Once installed you can start the proxy with the following command:
> ios_webkit_debug_proxy -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
```
You may also use the ios-webkit-debug-proxy-launcher to launch the
You can also set the desired capability called 'startIWDP' to true (https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md). This will run the above command as a subprocess from within Appium and will set the udid, so you don't have to run ios_webkit_debug_proxy yourself anymore. It monitors the proxy for crashes and relaunches when needed.
``` center
// example desired capabilities
{
"browserName": "Safari",
"platformName": "iOS",
"deviceName": "iPhone 7",
"automationName": "XCUITest",
"startIWDP": true,
"udid": "auto"
}
```
You may also use `ios-webkit-debug-proxy-launcher`, a small script included with the Appium codebase, to launch the
proxy. It monitors the proxy log for errors, and relaunch the proxy
where needed. This is also optional and may help with recent devices:
``` center
# change the udid
# note, this is run from an Appium repository
> ./bin/ios-webkit-debug-proxy-launcher.js -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
```
+4 -5
View File
@@ -1,15 +1,14 @@
## Setting up instruments without delay (iwd) for xcode 7 and iOS >= 9.0
For iOS >= 9.0 instruments without delay (iwd) does not work by passing binaries through
the command line (appium does this under the hood for xcode < 7). See [iwd](https://github.com/lawrencelomax/instruments-without-delay/tree/xcode7-quirks#xcode-7--ios-9-support)
For iOS >= 9.0 instruments without delay (iwd) does not work by passing binaries through the command line (appium does this under the hood for xcode < 7). See [iwd](https://github.com/lawrencelomax/instruments-without-delay/tree/xcode7-quirks#xcode-7--ios-9-support)
For enabling iwd for xcode >= 7,
- Checkout [appium-instruments](https://github.com/appium/appium-instruments)
- Run `xcode-iwd.sh` present in `<appium-instruments>/bin/`
- Check out [appium-instruments](https://github.com/appium/appium-instruments)
- Run `xcode-iwd.sh` present in `<appium-instruments>/bin/`, with arguments as indicated below:
```
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/`
Note: iwd with xcode7 will only work for iOS >= 9.0, you can switch to older xcode for iOS < 9.0
Note: iwd with Xcode 7 will only work for iOS >= 9.0, you can switch to an older version of Xcode for iOS < 9.0
@@ -1,3 +1,5 @@
*This document is old, and only of interest for those migrating to Appium 1.x from an earlier version*
## Migrating your tests from Appium 0.18.x to Appium 1.x
Appium 1.0 has removed a number of deprecated features from the previous versions. This guide will help you know what needs to change in your test suite to take advantage of Appium 1.0.
@@ -1,4 +1,4 @@
## Migrating your iOS tests from UIAutomation (iOS 9.2 and below) to XCUITest (iOS 9.3 and up)
## Migrating your iOS tests from UIAutomation (iOS 9.3 and below) to XCUITest (iOS 9.3 and up)
For iOS automation, Appium relies on system frameworks provided by Apple. For iOS 9.2 and below, Apple's only automation technology was called UIAutomation, and it ran in the context of a process called "Instruments". As of iOS 10, Apple has completely removed the UIAutomation instrument, thus making it impossible for Appium to allow testing in the way it used to. Fortunately, Apple introduced a new automation technology, called XCUITest, beginning with iOS 9.3. For iOS 10 and up, this will be the only supported automation framework from Apple.
@@ -21,6 +21,61 @@ As mentioned just above, if you rely on the app source XML from the `page source
This locator strategy was specifically built on UIAutomation, so it is not included in the XCUITest automation backend. We will be working on a similar "native"-type locator strategy in coming releases.
### `xpath` locator strategy
1. Try not to use XPath locators unless there is absolutely no other alternatives. In general, xpath locators might be times slower, than other types of locators like accessibility id, class name and predicate (up to 100 times slower in some special cases). They are so slow, because xpath location is not natively supported by Apple's XCTest framework.
2. Use
```
driver.findElement(x)
```
call instead of
```
driver.findElements(x)[0]
```
to lookup single element by xpath. The more possible UI elements are matched by your locator the slower it is.
3. Be very specific when locating elements by xpath. Such locators like
```
//*
```
may take minutes to complete depending on how many UI elements your application has (e. g.
```
driver.findElement(By.xpath("//XCUIElementTypeButton[@value='blabla']"))
```
is faster than
```
driver.findElement(By.xpath("//*[@value='blabla']"))
```
or
```
driver.findElement(By.xpath("//XCUIElementTypeButton")))
```
4. In most cases it would be faster to perform multiple nested findElement calls than to perform a single call by xpath (e.g.
```
driver.findElement(x).findElement(y)
```
is usually faster than
```
driver.findElement(z)
```
where x and y are non-xpath locators and z is a xpath locator).
### System dependencies
In addition to the many gotchas that might come with upgrading any XCode installation (unrelated to Appium), Appium's XCUITest support requires a new system dependency: [Carthage](https://github.com/Carthage/Carthage). Appium Doctor has now been updated to ensure that the `carthage` binary is on your path.
@@ -35,10 +90,21 @@ Unfortunately, the XCUITest API and the UIAutomation API are not equivalent. In
We will endeavor to add these features back in future releases of Appium.
#### Scrolling and clicking
In the previous UIAutomation-based driver, if you tried to click on an element that wasn't in view, UIAutomation would scroll to the element automatically and then tap it. With XCUITest, this is no longer the case. You are now responsible for ensuring your element is in view before interacting with it (the same way a user would be responsible for the same).
### Other known issues
Finally, a list of known issues with the initial 1.6 release:
Finally, a list of known issues with the initial 1.6 release (we'll strike through issues which have been resolved):
* [Problems with processArguments](https://github.com/appium/appium/issues/6888)
* ~~Unable to interact with elements on devices in Landscape mode (https://github.com/appium/appium/issues/6994)~~
* `shake` is not implemented due to lack of support from Apple
* `lock` is not implemented due to lack of support from Apple
* Setting geo-location not supported due to lack of support from Apple
* Through the TouchAction/MultiAction API, `zoom` gestures work but `pinch` gestures do not, due to an Apple issue.
* ~~Through the TouchAction/MultiAction API, `swipe` gestures are currently not supported, though they should be soon (https://github.com/appium/appium/issues/7573)~~
* The capabilities `autoAcceptAlerts` and `autoDismissAlerts` do not currently work, and there is continued debate about whether we will be able to implement them in the future.
* There is an issue with the iOS SDK such that PickerWheels built using certain API methods are not automatable by XCUITest. See https://github.com/appium/appium/issues/6962 for the workaround, to ensure your PickerWheels are built properly.
As far as possible, we will add the missing features and fix other known issues in the [1.6.1 Milestone](https://github.com/appium/appium/milestone/27), so following that may be of interest to you.
As far as possible, we will add the missing features and fix other known issues in future versions of Appium.
+5 -3
View File
@@ -21,8 +21,8 @@ Settings are implemented via the following API endpoints:
```
{
settings: {
ignoreUnimportantViews : true
}
ignoreUnimportantViews : true
}
}
```
@@ -31,10 +31,12 @@ Settings are implemented via the following API endpoints:
>Returns a JSON hash of all the currently specified settings.
```
{
ignoreUnimportantViews : true
ignoreUnimportantViews : true
}
```
Note that the actual commands you would use in your test script differ based on the language; see the specific Appium client documention for more information.
### Supported Settings
**"ignoreUnimportantViews"** - Boolean which sets whether Android devices should use `setCompressedLayoutHeirarchy()` which ignores all views which are marked IMPORTANT_FOR_ACCESSIBILITY_NO or IMPORTANT_FOR_ACCESSIBILITY_AUTO (and have been deemed not important by the system), in an attempt to make things less confusing or faster.
+9 -10
View File
@@ -1,12 +1,12 @@
## Android Setup
To get started, you'll need to install node.js (v4 or greater). Just
To get started, you'll need to install Node.js (v4 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, under the 'tools' directory).
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, under the 'tools' directory).
Run the 'android' tool and use it to install an API Level 17 or greater.
Run the `android` tool and use it to install an API Level 17 or greater.
(If you want to run Appium from source, you will also need [Apache Ant](http://ant.apache.org/) to build the bootstrap jar that Appium uses for running against Android simulators/devices.)
@@ -16,13 +16,12 @@ shell startup:
export ANDROID_HOME="/usr/local/adt/sdk"
Now you're set up to run Appium! If you're running Appium from source, run
`npm install` from your Appium checkout to install all the
dependencies.
Now you're set up to run Appium! (If you're running Appium from source, make sure to run `npm install` from your Appium checkout to install all the
dependencies.)
### Additional Setup for Older Versions of Android
Appium uses, and comes prepackaged with, Selendroid for running Android
Appium uses, and comes prepackaged with, a project called [Selendroid](https://selendroid.io) for running Android
versions 2.3 to 4.1. Appium switches to using Selendroid automatically when it
detects older versions, but there is some additional setup required if you're
running from source.
@@ -44,7 +43,7 @@ See the [server documentation](/docs/en/writing-running-appium/server-args.md) f
limitations. For more information you can check out this
[page](/docs/en/appium-setup/android-hax-emulator.md).
* Make sure that `hw.battery=yes` in your AVD's `config.ini`, if you want to
run any of the Appium tests, or use any of the power commands.
* Selendroid requires the following permission for your app:
run any of the Appium tests, or use any of the power commands. As of Android 5.0, this is the default.
* Selendroid requires the following permission for instrumenting your app:
`<uses-permission android:name="android.**permission.INTERNET"/>`,
please make sure your app has internet permission set when you are using selendroid or older versions of Android i.e. 2.3 to 4.1
+3 -3
View File
@@ -1,6 +1,6 @@
## Parallel Android Tests
Appium provides a way for users to automate multiple Android sessions on a single machine. All it involves is starting multiple Appium servers with different flags.
Appium provides a way for users to automate multiple Android sessions on a single machine. All it involves is starting multiple Appium servers with different flags.
The important flags for automating multiple Android sessions are:
@@ -18,13 +18,13 @@ If we had two devices with the ID's 43364 and 32456, we would start two differen
`node . -p 4491 -bp 2252 -U 43364`
As long as your Appium and Appium bootstrap ports are between 0 and 65536, all they have to be is different so that two Appium servers aren't trying to listen on the same port. Be sure that your -u flag corresponds with the correct device ID. This is how Appium knows which device to communicate with, so it must be accurate.
As long as your Appium and Appium bootstrap ports are between 0 and 65536, all they have to be is different so that two Appium servers aren't trying to listen on the same port. Be sure that your -u flag corresponds with the correct device ID. This is how Appium knows which device to communicate with, so it must be accurate.
If you are using chromedriver or selendroid, set a different port for each server.
### Parallel iOS Tests
Unfortunately, running local parallel iOS tests aren't possible. Unlike Android, only one version of the iOS simulator can be launched at a time, making it run multiple tests at once.
Unfortunately, running local parallel iOS tests isn't currently possible. Unlike Android, only one version of the iOS simulator can be launched at a time, making it run multiple tests at once.
If you do want to run parallel iOS tests, you need to use Sauce. Simply upload your Appium test to Sauce, and it can run as many parallel iOS or Android tests as your account allows. See more about running your tests on Sauce [here](https://docs.saucelabs.com/tutorials/appium/).
+8 -7
View File
@@ -9,21 +9,21 @@ make explicit the level of support and requirements for each of these.
See [Running on OS X: iOS](running-on-osx.md) for iOS requirements and setup
instructions.
* Versions: 7.1, 8.0, 8.1, 8.2, 8.3, 8.4, 9.0, 9.1 and 9.2
* Versions: 7.1 and up
* Devices: iPhone Simulator, iPad Simulator, and real iPhones and iPads
* Native app support: Yes, with debug version of .app (simulator),
or correctly-signed .ipa (real devices). Underlying support is provided by
Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)
Apple's [XCUITest](https://developer.apple.com/reference/xctest) (or [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/) for older versions)
framework.
* Mobile web support: Yes, via automation of mobile Safari. For real devices,
ios-webkit-remote-debugger is required, and automation of native aspects of
`ios-webkit-remote-debugger` is required, and automation of native aspects of
the Safari interface is not possible. See the [mobile web doc](/docs/en/writing-running-appium/mobile-web.md) for instructions.
* Hybrid support: Yes. For real devices, ios-webkit-remote-debugger is
required. See the [hybrid doc](/docs/en/advanced-concepts/hybrid.md) for instructions.
* Support for automating multiple apps in one session: No
* Support for automating multiple devices simultaneously: No
* Support for automating vendor-provided or third-party apps: Only
vendor-provided apps (Preferences, Maps, etc...), and only on the simulator
vendor-provided apps (Preferences, Maps, etc...), and only on the simulator. For iOS 10+, you can automate the home screen as well.
* Support for automating custom, non-standard UI controls: Minimal. You need to
set accessibility information on the control which enables some basic
automation.
@@ -62,8 +62,9 @@ instructions.
when using the Selendroid backend)
* Support for automating custom, non-standard UI controls: No
### Windows Support
### Windows Desktop Support
See [running on Windows](running-on-windows.md) for details
See these docs for details:
* [Windows App Testing](windows-app-testing.md)
* [Running on Windows](running-on-windows.md)
* [Windows App Testing](/docs/en/writing-running-appium/windows-app-testing.md)
@@ -0,0 +1,12 @@
## Appium on Android Real Devices
Hooray! There is nothing extra to know about testing real Android devices: it
works exactly the same as testing on emulators. Make sure that your device
can connect to ADB and has Developer Mode enabled (the process for this differs
for different vendors, so check their documentation). For testing Chrome on a real
device, you are responsible for ensuring that Chrome of an appropriate version
is installed.
Also, you will want to make sure that "Verify Apps" in settings is
disabled/unchecked, otherwise it can prevent some of Appium's helper apps from
launching and doing their job correctly.
Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

+280
View File
@@ -0,0 +1,280 @@
## Appium on iOS Real Devices
Appium has support for iOS real device testing.
### Running your tests with Appium
Once your device and app are configured, you can run tests on that device by
passing the `udid` desired capability, and the bundle ID (via the `bundleId`
capability, if the app is installed on the device) or the path to the `.ipa` or
`.app` file via the `app` desired capability.
### Desired Capabilities
You can launch the app on a device by including the following desired
capabilities in your tests:
* `app` or `bundleId` - specifies the application, or, if it is already installed,
simply the bundle identifier of the app so that Appium can launch it
* `udid` - the specific id of the device to test on. This can also be set to
`auto` if there is only a single device, in which case Appium will determine
the device id and use it
Refer to the [Appium server capabilities](/docs/en/writing-running-appium/caps.md) page for more detail on
the capabilities that you can use.
### Required Software
Appium iOS real device support depends on a central third-party software suite,
[libimobiledevice](http://www.libimobiledevice.org/), which is easily installable
with [Homebrew](http://brew.sh/))
```
brew install libimobiledevice
```
## Configuring iOS Real Device Tests: Xcode 7 and iOS 9.3 or below
Automating real devices with iOS 9.3 or below, using Xcode 7.3 or below (i.e.,
_Instruments_-based testing) requires a relatively small amount of configuration.
The central requirement is to have a build of your app signed with a development
provisioning profile. Unfortunately Apple has removed all of its documentation
on using older versions of Xcode, but a good overview of the process can be
found [here](https://medium.com/ios-os-x-development/ios-code-signing-provisioning-in-a-nutshell-d5b247760bef#.5hirl92tn)
and [here](https://engineering.nodesagency.com/articles/iOS/Understanding-code-signing-for-iOS-apps/).
In a little more detail, to get started on a real device, you will need the following:
* An [Apple Developer ID](https://developer.apple.com/programs/ios/) and a valid
Developer Account with a configured development certificate and provisioning
profile.
* A valid iOS Development Certificate and Provisioning Profile are necessary to
test on a real device. Your app will also need to be signed. You can find
information about this in the [Apple documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html).
* An iPad or iPhone. Make sure this has been set up for development in Xcode.
* A signed `.app` or `.ipa` file of your app, or the source code to build one.
* A Mac with [Xcode](https://developer.apple.com/xcode/) and the Xcode Command
Line Developer Tools.
Appium handles installing the application to the device, using `ideviceinstaller`
(part of `libimobiledevice`), but it is sometimes easier to pre-install your app
using Xcode to ensure there are no problems (see the [iOS deploy](ios-deploy.md)
document for more information).
### Troubleshooting ideas
0. Make sure UDID is correct by checking it in Xcode Organizer or iTunes. It
is a long string (20+ chars).
0. Make sure that you can run your tests against the Simulator.
0. Double check that you can invoke your automation from Instruments.
0. Make sure Instruments is not already running.
0. Make sure UI Automation is enabled on your device. Settings -> Developer -> Enable UI Automation
## Configuring iOS Real Device Tests: Xcode 8 and iOS 9.3 and above
In addition to the dependency on `libimobiledevice`, Appium support for real
devices running iOS 9.3 and above using Xcode 8+ also depends on `ios-deploy`,
which is easily available through [npm](https://www.npmjs.com/package/ios-deploy)
```
npm install -g ios-deploy
```
Unfortunately, Apple changed the way it makes testing available, and the new
way requires the installation of a helper application onto the device, through
which the application under test is automated. While this is simple in theory,
the hoops of code signing and provisioning applications for development and
testing can make this a bit of a headache.
The application that Appium installs is called `WebDriverAgent-Runner` (found
[here](https://github.com/facebook/WebDriverAgent/)), and to do the install
Appium needs to be able to configure its build.
### Basic (automatic) configuration
The easiest way to get up-and-running with Appium's XCUITest support on iOS
real devices is to use the automatic configuration strategy. There are two ways
to do this:
* Use the `xcodeOrgId` and `xcodeSigningId` desired capabilities:
```json
{
"xcodeOrgId": "<Team ID>",
"xcodeSigningId": "iPhone Developer"
}
```
* Create a `.xcconfig` file somewhere on your file system and add the following to it:
```
DEVELOPMENT_TEAM = <Team ID>
CODE_SIGN_IDENTITY = iPhone Developer
```
In either case, the Team ID is a unique 10-character string generated by Apple
that is assigned to your team. You can find your Team ID using your developer
account. Sign in to [developer.apple.com/account](http://developer.apple.com/account),
and click Membership in the sidebar. Your Team ID appears in the Membership
Information section under the team name. You can also find your team ID listed
under the "Organizational Unit" field in your iPhone Developer certificate in
your keychain.
Note that these are mutually exclusive strategies; use _either_ the
`xcodeConfigFile` capability or the combination of `xcodeOrgId` and `xcodeSigningId`.
Once this configuration is done, it should just be a matter of starting your test
specifying a real device in your `udid` desired capability.
If this has not worked it will usually manifest itself in the Appium server logs
as some error followed by `info XCUITest xcodebuild exited with code '65' and
signal 'null'`. This usually means that the necessary code signing is not set up
correctly. Go on to the [Basic (manual) configuration](https://github.com/imurchie/appium-xcuitest-driver/blob/isaac-rs/docs/real-device-config.md#basic-manual-configuration)
to fix.
If the `WebDriverAgentRunner` is successfully installed on the device, but in the
Appium logs there is an error message something like:
```
2017-01-24 09:02:18.358 xcodebuild[30385:339674] Error Domain=com.apple.platform.iphoneos Code=-12 "Unable to launch com.apple.test.WebDriverAgentRunner-Runner" UserInfo={NSLocalizedDescription=Unable to launch com.apple.test.WebDriverAgentRunner-Runner, NSUnderlyingError=0x7fa839cadc60 {Error Domain=DTXMessage Code=1 "(null)" UserInfo={DTXExceptionKey=The operation couldn’t be completed. Unable to launch com.apple.test.WebDriverAgentRunner-Runner because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user. : Failed to launch process with bundle identifier 'com.apple.test.WebDriverAgentRunner-Runner'}}}
2017-01-24 09:02:18.358 xcodebuild[30385:339674] Error Domain=IDETestOperationsObserverErrorDomain Code=5 "Early unexpected exit, operation never finished bootstrapping - no restart will be attempted" UserInfo={NSLocalizedDescription=Early unexpected exit, operation never finished bootstrapping - no restart will be attempted}
Testing failed:
Test target WebDriverAgentRunner encountered an error (Early unexpected exit, operation never finished bootstrapping - no restart will be attempted)
```
The problem is that the developer is not trusted on the device. If you manually
try to run the `WebDriverAgentRunner` app on the device, you will see a popup
message:
![Untrusted developer](real-devices-img/untrusted-dev.png)
You can go to Settings => General => Device Management on the device to trust
the developer and allow the `WebDriverAgentRunner` app to be run (see [Apple
documentation for more information](https://support.apple.com/en-us/HT204460)).
### Basic (manual) configuration
There are many cases in which the basic automatic configuration is not enough. This
usually has to do with code signing and the configuration of the project to be
able to be run on the real device under test. Often this happens when the
development account being used is a "Free" one, in which case it is not possible
to create a wildcard provisioning profile, and will often not create one for the
default application bundle.
This will manifest as something like an error that Xcode **failed to create
provisioning profile**:
![No provisioning profile](real-devices-img/no-prov-prof.png)
The easiest way around this is to create a provisioning profile by opening
[Xcode](https://developer.apple.com/xcode/) and creating a new project:
![Create new project](real-devices-img/create-new-project.png)
The type does not matter, other than it being "iOS". "Single View Application"
is the easiest:
![Create single page](real-devices-img/create-single-page.png)
The important part is to use a unique "Product Name" and "Organization Name". Also,
at this point, specify your "Team".
![Setup bundle](real-devices-img/set-up-bundle.png)
You can confirm that the provisioning profile was created by looking at the "Project"
tab:
![Project pane](real-devices-img/project-prov-prof.png)
Or by going into your account preferences and seeing the provisioning profile:
![Check provisioning profile](real-devices-img/check-prov-prof.png)
At this point you have a valid provisioning profile. Make note of the bundle id
you associated with it, and add that in the `updatedWDABundleId` desired
capability for your tests. Then follow the [initial instructions for automatic
configuration](#basic-automatic-configuration).
### Full manual configuration
Alternatively, the provisioning profile can be manually associated with the
project (keep in mind that this will have to be done each time the WebDriverAgent
is updated, and is _not_ recommended):
* Find out where your Appium installation is:
```
$ which appium
/path/where/installed/bin/appium
```
* Given this installation location, `/path/where/installed/bin/appium`, `WebDriverAgent`
will be found in `/path/where/installed/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent`.
Open a terminal and go to that location, then run the following in order to
set the project up:
```
mkdir -p Resources/WebDriverAgent.bundle
./Scripts/bootstrap.sh -d
```
* Open `WebDriverAgent.xcodeproj` in Xcode. For **both** the `WebDriverAgentLib`
and `WebDriverAgentRunner` targets, select "Automatically manage signing"
in the "General" tab, and then select your `Development Team`. This
should also auto select `Signing Ceritificate`. The outcome should look as
shown below:
![WebDriverAgent in Xcode project](real-devices-img/xcode-config.png)
* Xcode may fail to create a provisioning profile for the `WebDriverAgentRunner`
target:
![Xcode provisioning fail](real-devices-img/xcode-facebook-fail.png)
* This necessitates manually changing the bundle id for the target by going
into the "Build Settings" tab, and changing the "Product Bundle Identifier"
from `com.facebook.WebDriverAgentRunner` to something that Xcode will accept:
![Xcode bundle id](real-devices-img/xcode-bundle-id.png)
* Going back to the "General" tab for the `WebDriverAgentRunner` target, you
should now see that it has created a provisioning profile and all is well:
![Xcode provisioning profile](real-devices-img/xcode-facebook-succeed.png)
* Finally, you can verify that everything works. Build the project:
```
xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=<udid>' test
```
If this was successful, the output should end with something like:
```
Test Suite 'All tests' started at 2017-01-23 15:49:12.585
Test Suite 'WebDriverAgentRunner.xctest' started at 2017-01-23 15:49:12.586
Test Suite 'UITestingUITests' started at 2017-01-23 15:49:12.587
Test Case '-[UITestingUITests testRunner]' started.
t = 0.00s Start Test at 2017-01-23 15:49:12.588
t = 0.00s Set Up
```
* To completely verify, you can try accessing the WebDriverAgent server status
(**note:** you _must_ be on the same network as the device, and know its IP
address, from Settings => Wi-Fi => Current Network):
```
export DEVICE_URL='http://<device IP>:8100'
export JSON_HEADER='-H "Content-Type: application/json;charset=UTF-8, accept: application/json"'
curl -X GET $JSON_HEADER $DEVICE_URL/status
```
You ought to get back output something like this:
```
{
"value" : {
"state" : "success",
"os" : {
"name" : "iOS",
"version" : "10.2"
},
"ios" : {
"simulatorVersion" : "10.2",
"ip" : "192.168.0.7"
},
"build" : {
"time" : "Jan 23 2017 14:59:57"
}
},
"sessionId" : "8951A6DD-F3AD-410E-A5DB-D042F42F68A7",
"status" : 0
}
```
+3 -88
View File
@@ -1,91 +1,6 @@
## Appium on real iOS devices
## Appium Support for Real Device Testing
Appium has support for real device testing.
To get started on a real device, you will need the following:
* An [Apple Developer ID](https://developer.apple.com/programs/ios/)
and a valid Developer Account with a configured distribution certificate and
provisioning profile.
* An iPad or iPhone. Make sure this has been set up for development in Xcode. See [this article](https://developer.apple.com/library/ios/recipes/xcode_help-devices_organizer/articles/provision_device_for_development-generic.html) for more information.
* A signed `.ipa` file of your app, or the source code to build one.
* A Mac with [Xcode](https://itunes.apple.com/en/app/xcode/id497799835?mt=12)
and the Xcode Command Line Developer Tools.
### Provisioning Profile
A valid iOS Development Distribution Certificate and Provisioning Profile are
necessary to test on a real device. Your app will also need to be signed. You
can find information about this in the [Apple documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html).
Appium will attempt to install your app using Fruitstrap, but it is often easier
to pre-install your app using Xcode to ensure there are no problems (see the [iOS deploy](ios-deploy.md) doc for more information).
### Testing using Xcode 8 (including iOS 10) with XCUITest
This functionality currently depends on logging based on `idevicesyslog`, and
port forwarding based on `iProxy`, both of which are part of `libimobiledevice`.
Install it with [Homebrew](http://brew.sh/),
```
brew install libimobiledevice
```
Alternatively, logging can be done using `deviceconsole`, which is available
[here](https://github.com/rpetrich/deviceconsole). To choose between them, use
the desired capability `realDeviceLogger`, passing in the path to the logging
program.
### Running your tests with Appium
Once your device and app are configured, you can run tests on that device by
passing the `-U` or `--udid` flag to the server or the `udid` desired capability,
and the bundle ID (if the app is installed on the device) or the path to the
`.ipa` or `.apk` file via the `--app` flag or the `app` desired capability.
### Server Arguments
For example, if you are prelaunching your app and wish for Appium to force use
a specific UDID, then you may use the below command:
```center
appium -U <udid> --app <path or bundle>
```
This will start Appium and have Appium use the device to test the app.
Refer to the [Appium server arguments](/docs/en/writing-running-appium/server-args.md) page for more detail on
the arguments that you can use.
### Desired Capabilities
You can launch the app on a device by including the following desired
capabilities in your tests:
* `app`
* `udid`
Refer to the [Appium server capabilities](/docs/en/writing-running-appium/caps.md) page for more detail on
the capabilities that you can use.
### Troubleshooting ideas
0. Make sure UDID is correct by checking it in Xcode Organizer or iTunes. It
is a long string (20+ chars).
0. Make sure that you can run your tests against the Simulator.
0. Double check that you can invoke your automation from Instruments.
0. Make sure Instruments is not already running.
0. Make sure UI Automation is enabled on your device. Settings -> Developer -> Enable UI Automation
### Appium on real Android devices
Hooray! There's nothing extra to know about testing real Android devices: it
works exactly the same as testing on emulators. Make sure that your device
can connect to ADB and has Developer Mode enabled. For testing Chrome on a real
device, you're responsible for ensuring that Chrome of an appropriate version
is installed.
Also, you'll want to make sure that "Verify Apps" in settings is
disabled/unchecked, otherwise it can prevent some of Appium's helper apps from
launching and doing their job correctly.
* For **Android** testing, see [android real device documentation](real-devices-android.md)
* For **iOS** testing, see [iOS real device documentation](real-devices-ios.md)
+13 -6
View File
@@ -4,14 +4,14 @@ Appium on OS X supports iOS and Android testing.
### System setup (iOS)
* Appium requires Mac OS X 10.7 or greater. We recommend OS X 10.10.
* Appium requires Mac OS X 10.10 or greater.
* Make sure you have Xcode and the iOS SDK(s) installed. Xcode version 7.1 is
recommended as earlier versions of Xcode are limited in which versions of iOS
they can test against. See the next section for more detail.
* You need to authorize use of the iOS Simulator. See [below](#authorizing-ios-on-the-computer).
* If you're on Xcode 7.x, Instruments Without Delay (IWD) does not work. You can
enable IWD (which will significantly speed up your tests) using
[this method](/docs/en/advanced-concepts/iwd_xcode7.md)
* If you're on Xcode 7.x and up, Instruments Without Delay (IWD) does not work.
You can enable IWD (which will significantly speed up your tests) using [this
method](/docs/en/advanced-concepts/iwd_xcode7.md)
* If you're on Xcode 6, you need to launch each simulator you intend to use
with appium in advance, and change the default to actually show the soft
keyboard if you want sendKeys to work. You can do this by clicking on any
@@ -23,9 +23,9 @@ Appium on OS X supports iOS and Android testing.
a platformVersion cap of "8.0", you need to make sure that there is exactly
one device with the name "iPhone 5s" and the 8.0 sdk in your devices list.
Otherwise, Appium won't know which one to use.
* In iOS8, devices each have their own setting which enables or disables
* In iOS 8, devices each have their own setting which enables or disables
UIAutomation. It lives in a "Developer" view in the Settings app. You need to
verify that UIAutomaion is enabled in this view before the simulator or
verify that UIAutomation is enabled in this view before the simulator or
device can be automated.
### Authorizing iOS on the computer
@@ -66,8 +66,15 @@ manager:
brew install carthage
```
### Testing Mac apps
Currently, the Mac app driver for appium does not ship with the AppiumForMac binary, which means, in order to automate Mac apps you must manually install the AppiumForMac application and grant it the appropriate OS X Accessibility permissions.
To Install Appium for Mac:
1. [Download a release](https://github.com/appium/appium-for-mac/releases/tag/0.2.0) and unzip the application into your `/Applications` folder
2. Follow the [brief supplemental installation instructions](https://github.com/appium/appium-for-mac#installation) to enable appium to have access to OS X's Accessibility APIs
For more information on using Appium for mac, checkout the [docs](https://github.com/appium/appium-for-mac#appium-for-mac).
### System setup (Android)
+1 -5
View File
@@ -60,6 +60,7 @@ own items in the SDK manager. Make sure you install the build-tools and platform
* If Instruments is crashing when running against a physical device ("exited with code 253"), ensure Xcode has downloaded device symbols. Go to Window -> Devices, and it should start automatically. This is needed after iOS version upgrades.
* If you see `iOS Simulator failed to install the application.` and the
paths are correct, try restarting the computer.
* Make sure your macOS keychain that holds the certificate(s) needed for building your app and the WebDriverAgent is unlocked. Especialy if you are using ssh. General symptom to look for is `codesign` failure.
* If you have custom elements in your app, they will not be automatable by
UIAutomation (and therefore Appium) by default. You need to set the
accessibility status to 'enabled' on them. The way to do this in code is:
@@ -139,11 +140,6 @@ own items in the SDK manager. Make sure you install the build-tools and platform
* In a Safari session, if the logs indicate that the initial url cannot be entered, make sure that
you have the software keyboard enabled. See this [discussion](https://github.com/appium/appium/issues/6440).
### FirefoxOS
* Make sure the Boot-to-Gecko simulator is up and running.
* Make sure the simulator screen is alive and unlocked (might require restarting B2G).
### Let the community know
Once you've tried the above steps and your issue still isn't resolved,
@@ -81,10 +81,8 @@ have to modify your `/etc/authorization` file in one of two ways:
`/etc/authorization` file for you:
```center
sudo node_modules/.bin/authorize-ios.js
# alternatively
sudo $(npm bin)/authorize-ios
npm install -g authorize-ios
sudo authorize-ios
```
At this point, run:
@@ -9,7 +9,7 @@
- contains all available and supported CLI arguments
- check for deprecation and mutual exclusion
- put logging together
- mixture out of npmlog, winston and appium-logger
- mixture out of npmlog, winston and a custom logger
- initiates AppiumDriver (extends Basedriver)
- assigns iOS/Android/Selendroid/Fake driver to session
- creates/deletes Appium session
@@ -14,3 +14,4 @@
* [instruments-without-delay](https://github.com/facebook/instruments-without-delay)
* [deviceconsole](https://github.com/rpetrich/deviceconsole)
* [WinAppDriver](http://github.com/Microsoft/WinAppDriver)
* [WebDriverAgent](https://github.com/facebook/webdriveragent)
@@ -30,6 +30,37 @@ _development_ questions, not _usage_ questions or bug reports. Usage questions
belong on [discuss.appium.io](https://discuss.appium.io). The GitHub issue
tracker is for bug reports and feature requests only.
### Agile Development Workflow
The Appium team runs development according to a very lightweight version of
SCRUM. Every two weeks we begin a new "sprint", or a period of time in which we
have decided what we want to accomplish. Anyone familiar with the Appium
codebase is welcome to attend our sprint planning and participate as a SCRUM
team member for that sprint. No long-term commitments required! During the
sprint, we update each other with daily progress in the `#standup` room in our
[Appium Slack Group](https://appium.slack.com) (there are no real-time daily
standups). At the end of the sprint, to celebrate our accomplishments and
reflect on how things went, we hold a "retrospective", which might result in
a list of things we can try differently or do better next time around.
Ultimately, the goal is to time an Appium release at the end of each sprint, so
every two weeks. We're not quite there, but hopefully we will be soon.
Current meeting times:
* Sprint Planning: every other Monday from 10:00 AM - 10:45 AM (Pacific Time)
* Sprint Retrospective: every other _other_ Friday from 1:00 PM - 1:30 PM (Pacific Time)
We hold meetings using [Zoom](https://zoom.us) video chat.
For project management, we use the [ZenHub](http://zenhub.com) browser plugin,
which adds various features like Kanban boards and Epics to the GitHub
interface. To fully participate in Appium SCRUM, you'll need to have this
browser plugin installed.
If you are interested in participating a sprint, ping `@jlipps` or `@isaac` in
the Appium Slack Group, or DM `@jlipps` on Twitter, and we'll share how to join
the video chat for the next sprint.
### Architecture
Appium is primarily a collection of [node.js](http://nodejs.org) packages that
+1 -1
View File
@@ -1,6 +1,6 @@
## Appium gulp commands
[Gulp](http://gulpjs.com) is like make for Node.js! We use it to automate all
[Gulp](http://gulpjs.com) is like `make` for Node.js! We use it to automate all
kinds of appium dev tasks. Here's what you can do:
|Task|Description|
@@ -210,7 +210,7 @@ driver.open_notifications()
```ruby
# ruby
openNotifications
open_notifications
```
```csharp
@@ -434,7 +434,7 @@ autoLaunch=false.
```ruby
# ruby
launch
launch_app
```
```python
@@ -473,7 +473,7 @@ Reset the app.
```ruby
# ruby
reset
driver.reset
```
```python
@@ -630,7 +630,7 @@ Get the app's strings.
```ruby
# ruby
strings = app_strings
app_strings
```
```python
@@ -993,7 +993,7 @@ execute_script "mobile: scroll", direction: "down", element: element.ref
```python
# python
driver.execute_script("mobile: scroll", {"direction": "down", element: element.id})
driver.execute_script("mobile: scroll", {"direction": "down", "element": element.id})
```
```java
@@ -1107,19 +1107,22 @@ driver.PushFile("/data/local/tmp/file.txt", "some data for the file");
Here you will find sample code for getting/setting appium serverSetting.
For more information on how they work, and which settings are supported, see
[the settings docs][/docs/en/advanced-concepts/settings.md]
[the settings docs](/docs/en/advanced-concepts/settings.md).
```ruby
# ruby
current_settings = get_settings
update_settings someSetting: true
```
```python
# python
current_settings = driver.get_settings()
driver.update_settings({"someSetting": true})
```
```java
// java
JsonObject settings = driver.getSettings()
// java-client doesn't support setting arbitrary settings, just settings which are already provided by appium.
// So for the 'ignoreUnimportantViews' setting, the following method exists:
@@ -1127,16 +1130,19 @@ driver.ignoreUnimportantViews(true);
```
```javascript
// javascript
var settings = driver.settings();
browser.updateSettings({'someSetting': true});
```
```php
// php
$settings = $this->getSettings();
$this->updateSettings(array('cyberdelia' => "open"));
```
```csharp
// c#
Dictionary<String, Object>settings = driver.GetSettings();
// dotnet-driver doesn't support setting arbitrary settings, just settings which are already provided by appium.
// So for the 'ignoreUnimportantViews' setting, the following method exists:
@@ -1,245 +0,0 @@
# Apple XCUITest
Xcode 7 introduces [new UI testing features](https://developer.apple.com/videos/play/wwdc2015/406/). Moving forward, [Appium iOS Driver](https://github.com/appium/appium-ios-driver) will leverage this framework, replacing UI Automation. While there are no official docs, @joemasilotti has created [some handy unofficial docs](http://masilotti.com/xctest-documentation/index.html) by pulling out comments from the header files.
## Launching the App (XCUIApplication)
- ##### – launch
Launches the application. This call is synchronous and when it returns the application is launched
and ready to handle user events. Any failure in the launch sequence is reported as a test failure
and halts the test at this point. If the application is already running, this call will first
terminate the existing instance to ensure clean state of the launched instance.
- ##### – terminate
Terminates any running instance of the application. If the application has an existing debug session
via Xcode, the termination is implemented as a halt via that debug connection. Otherwise, a SIGKILL
is sent to the process.
- #####   launchArguments
The arguments that will be passed to the application on launch. If not modified, these are the
arguments that Xcode will pass on launch. Those arguments can be changed, added to, or removed.
Unlike NSTask, it is legal to modify these arguments after the application has been launched. These
changes will not affect the current launch session, but will take effect the next time the application
is launched.
- #####   launchEnvironment
The environment that will be passed to the application on launch. If not modified, this is the
environment that Xcode will pass on launch. Those variables can be changed, added to, or removed.
Unlike NSTask, it is legal to modify the environment after the application has been launched. These
changes will not affect the current launch session, but will take effect the next time the application
is launched.
## Accessing the Device (XCUIDevice)
- ##### + sharedDevice
The current device.
- #####   orientation
The orientation of the device.
- ##### – pressButton:
Simulates the user pressing a physical button.
## Querying for Elements (XCUIElementQuery)
- #####   element
Returns an element that will use the query for resolution.
- #####   count
Evaluates the query at the time it is called and returns the number of matches found.
- ##### – elementAtIndex:
Returns an element that will resolve to the index into the query’s result set.
- ##### – elementBoundByIndex:
Returns an element that will use the index into the query’s results to determine which underlying accessibility element it is matched with.
- ##### – elementMatchingPredicate:
Returns an element that matches the predicate. The predicate will be evaluated against objects of type idXCUIElementAttributes.
- ##### – elementMatchingType:identifier:
Returns an element that matches the type and identifier.
- ##### – objectForKeyedSubscript:
Keyed subscripting is implemented as a shortcut for matching an identifier only. For example, app.descendants[“Foo”] -> XCUIElement.
- #####   allElementsBoundByAccessibilityElement
Immediately evaluates the query and returns an array of elements bound to the resulting accessibility elements.
- #####   allElementsBoundByIndex
Immediately evaluates the query and returns an array of elements bound by the index of each result.
- ##### – descendantsMatchingType:
Returns a new query that finds the descendants of all the elements found by the receiver.
- ##### – childrenMatchingType:
Returns a new query that finds the direct children of all the elements found by the receiver.
- ##### – matchingPredicate:
Returns a new query that applies the specified attributes or predicate to the receiver. The predicate will be evaluated against objects of type idXCUIElementAttributes.
- ##### – matchingType:identifier:
- ##### – matchingIdentifier:
- ##### – containingPredicate:
Returns a new query for finding elements that contain a descendant matching the specification. The predicate will be evaluated against objects of type idXCUIElementAttributes.
- ##### – containingType:identifier:
- #####   debugDescription
@discussion
Provides debugging information about the query. The data in the string will vary based on the time
at which it is captured, but it may include any of the following as well as additional data:
• A description of each step of the query.
• Information about the inputs and matched outputs of each step of the query.
This data should be used for debugging only - depending on any of the data as part of a test is unsupported.
## Interacting with Elements (XCUIElement)
### XCUIElementEventSynthesis Methods
- ##### – typeText:
Types a string into the element. The element or a descendant must have keyboard focus; otherwise an
error is raised.
- ##### – tap
Sends a tap event to a hittable point computed for the element.
- ##### – doubleTap
Sends a double tap event to a hittable point computed for the element.
- ##### – twoFingerTap
Sends a two finger tap event to a hittable point computed for the element.
- ##### – tapWithNumberOfTaps:numberOfTouches:
Sends one or more taps with one of more touch points.
- ##### – pressForDuration:
Sends a long press gesture to a hittable point computed for the element, holding for the specified duration.
- ##### – pressForDuration:thenDragToElement:
Initiates a press-and-hold gesture that then drags to another element, suitable for table cell reordering and similar operations.
@param duration
Duration of the initial press-and-hold.
@param otherElement
The element to finish the drag gesture over. In the example of table cell reordering, this would be the reorder element of the destination row.
- ##### – swipeUp
Sends a swipe-up gesture.
- ##### – swipeDown
Sends a swipe-down gesture.
- ##### – swipeLeft
Sends a swipe-left gesture.
- ##### – swipeRight
Sends a swipe-right gesture.
- ##### – pinchWithScale:velocity:
Sends a pinching gesture with two touches.
- ##### – rotate:withVelocity:
Sends a rotation gesture with two touches.
### XCUIElementTypeSlider Methods
- ##### – adjustToNormalizedSliderPosition:
Manipulates the UI to change the displayed value of the slider to one based on a normalized position. 0 corresponds to the minimum value of the slider, 1 corresponds to its maximum value. The adjustment is a “best effort” to move the indicator to the desired position; absolute fidelity is not guaranteed.
- #####   normalizedSliderPosition
Returns the position of the slider’s indicator as a normalized value where 0 corresponds to the minimum value of the slider and 1 corresponds to its maximum value.
### XCUIElementTypePickerWheel Methods
- ##### – adjustToPickerWheelValue:
Changes the displayed value for the picker wheel. Will generate a test failure if the specified value is not available.
### Other Methods
- #####   exists
Test to determine if the element exists.
- #####   hittable
Whether or not a hit point can be computed for the element for the purpose of synthesizing events.
- ##### – descendantsMatchingType:
Returns a query for all descendants of the element matching the specified type.
- ##### – childrenMatchingType:
Returns a query for direct children of the element matching the specified type.
- ##### – coordinateWithNormalizedOffset:
Creates and returns a new coordinate that will compute its screen point by adding the offset multiplied by the size of the element’s frame to the origin of the element’s frame.
- #####   debugDescription
@discussion
Provides debugging information about the element. The data in the string will vary based on the
time at which it is captured, but it may include any of the following as well as additional data:
• Values for the elements attributes.
• The entire tree of descendants rooted at the element.
• The element’s query.
This data should be used for debugging only - depending on any of the data as part of a test is unsupported.
## Using Coordinates (XCUICoordinate)
- ##### – init
Coordinates are never instantiated directly. Instead, they are created by elements or by other coordinates.
- #####   referencedElement
The element that the coordinate is based on, either directly or via the coordinate from which it was derived.
- #####   screenPoint
The dynamically computed value of the coordinate’s location on screen. Note that this value is dependent on the current frame of the referenced element; if the element’s frame changes, so will the value returned by this property. If the referenced element does exist when this is called, it will fail the test; check the referenced element’s exists property if the element may not be present.
- ##### – coordinateWithOffset:
Creates a new coordinate with an absolute offset in points from the original coordinate.
- ##### – tap
- ##### – doubleTap
- ##### – pressForDuration:
- ##### – pressForDuration:thenDragToCoordinate:
- ##### – hover
+12 -3
View File
@@ -62,6 +62,7 @@
|`recreateChromeDriverSessions`| Kill ChromeDriver session when moving to a non-ChromeDriver webview. Defaults to `false` | `true` or `false`|
|`nativeWebScreenshot`| In a web context, use native (adb) method for taking a screenshot, rather than proxying to ChromeDriver. Defaults to `false` | `true` or `false`|
|`androidScreenshotPath`| The name of the directory on the device in which the screenshot will be put. Defaults to `/data/local/tmp` |e.g. `/sdcard/screenshots/`|
|`autoGrantPermissions`|Have Appium automatically determine which permissions your app requires and grant them to the app on install. Defaults to `false`|`true` or `false`|
### iOS Only
@@ -75,8 +76,8 @@
|`launchTimeout`| Amount of time in ms to wait for instruments before assuming it hung and failing the session|e.g. `20000`|
|`locationServicesEnabled`| (Sim-only) Force location services to be either on or off. Default is to keep current sim setting.|`true` or `false`|
|`locationServicesAuthorized`| (Sim-only) Set location services to be authorized or not authorized for app via plist, so that location services alert doesn't pop up. Default is to keep current sim setting. Note that if you use this setting you MUST also use the `bundleId` capability to send in your app's bundle ID.|`true` or `false`|
|`autoAcceptAlerts`| Accept all iOS alerts automatically if they pop up. This includes privacy access permission alerts (e.g., location, contacts, photos). Default is false.|`true` or `false`|
|`autoDismissAlerts`| Dismiss all iOS alerts automatically if they pop up. This includes privacy access permission alerts (e.g., location, contacts, photos). Default is false.|`true` or `false`|
|`autoAcceptAlerts`| Accept all iOS alerts automatically if they pop up. This includes privacy access permission alerts (e.g., location, contacts, photos). Default is false. Does not work on `XCUITest`-based tests.|`true` or `false`|
|`autoDismissAlerts`| Dismiss all iOS alerts automatically if they pop up. This includes privacy access permission alerts (e.g., location, contacts, photos). Default is false. Does not work on `XCUITest`-based tests.|`true` or `false`|
|`nativeInstrumentsLib`| Use native intruments lib (ie disable instruments-without-delay).|`true` or `false`|
|`nativeWebTap`| (Sim-only) Enable "real", non-javascript-based web taps in Safari. Default: `false`. Warning: depending on viewport size/ratio this might not accurately tap an element|`true` or `false`|
|`safariInitialUrl`| (Sim-only) (>= 8.1) Initial safari url, default is a local welcome page | e.g. `https://www.github.com` |
@@ -93,6 +94,8 @@
|`waitForAppScript`| The ios automation script used to determined if the app has been launched, by default the system wait for the page source not to be empty. The result must be a boolean |e.g. `true;`, `target.elements().length > 0;`, `$.delay(5000); true;` |
|`webviewConnectRetries`| Number of times to send connection message to remote debugger, to get webview. Default: `8` |e.g., `12`|
|`appName`| The display name of the application under test. Used to automate backgrounding the app in iOS 9+.|e.g., `UICatalog`|
|`customSSLCert`|(Sim/Emu-only) Add an SSL certificate to simulator. | e.g. <br/>`-----BEGIN CERTIFICATE-----MIIFWjCCBEKg...`<br/>`-----END CERTIFICATE-----`|
### iOS Only, using XCUITest
@@ -103,11 +106,17 @@
|`processArguments`|Process arguments and environment which will be sent to the WebDriverAgent server.|`{ args: ["a", "b", "c"] , env: { "a": "b", "c": "d" } }` or `'{"args": ["a", "b", "c"], "env": { "a": "b", "c": "d" }}'`|
|`wdaLocalPort`|This value if specified, will be used to forward traffic from Mac host to real ios devices over USB. Default value is same as port number used by WDA on device.|e.g., `8100`|
|`showXcodeLog`|Whether to display the output of the Xcode command used to run the tests. If this is `true`, there will be **lots** of extra logging at startup. Defaults to `false`|e.g., `true`|
|`realDeviceLogger`|Device logger for real devices. It could be path to `deviceconsole` (installed with `npm install deviceconsole`, a compiled binary named `deviceconsole` will be added to `./node_modules/deviceconsole/`) or `idevicesyslog` (comes with libimobiledevice). Defaults to `idevicesyslog`|`idevicesyslog`, `/abs/path/to/deviceconsole`|
|`iosInstallPause`|Time in milliseconds to pause between installing the application and starting WebDriverAgent on the device. Used particularly for larger applications. Defaults to `0`|e.g., `8000`|
|`xcodeConfigFile`|Full path to an optional Xcode configuration file that specifies the code signing identity and team for running the WebDriverAgent on the real device.|e.g., `/path/to/myconfig.xcconfig`|
|`keychainPath`|Full path to the private development key exported from the system keychain. Used in conjunction with `keychainPassword` when testing on real devices.|e.g., `/path/to/MyPrivateKey.p12`|
|`keychainPassword`|Password for unlocking keychain specified in `keychainPath`.|e.g., `super awesome password`|
|`scaleFactor`|Simulator scale factor. This is useful to have if the default resolution of simulated device is greater than the actual display resolution. So you can scale the simulator to see the whole device screen without scrolling. |Acceptable values are: `'1.0', '0.75', '0.5', '0.33' and '0.25'`. The value should be a string.|
|`preventWDAAttachments`|Sets read only permissons to Attachments subfolder of WebDriverAgent root inside Xcode's DerivedData. This is necessary to prevent XCTest framework from creating tons of unnecessary screenshots and logs, which are impossible to shutdown using programming interfaces provided by Apple.|Setting the capability to `true` will set Posix permissions of the folder to `555` and `false` will reset them back to `755`|
|`webDriverAgentUrl`|If provided, Appium will connect to an existing WebDriverAgent instance at this URL instead of starting a new one.|e.g., `http://localhost:8100`|
|`useNewWDA`|If `true`, forces uninstall of any existing WebDriverAgent app on device. This can provide stability in some situations. Defaults to `false`.|e.g., `true`|
|`wdaLaunchTimeout`|Time, in ms, to wait for WebDriverAgewnt to be pingable. Defaults to 60000ms.|e.g., `30000`|
|`calendarAccessAuthorized`|If truthy, enables calendar access on IOS Simulator with given bundleId. If `false`, disables
calendar access on IOS Simulator with given bundleId. Otherwise, the calendar authorizationStatus remains unchanged.||
### You.i Engine Only
@@ -1,6 +1,6 @@
## The --default-capabilities flag
Appium 1.5 does away with most CLI flags; the remainder can be converted into JSON and made part of the `--default-capabilities` flag. For example:
Appium 1.5 does away with most CLI flags that existed previously; the remainder can be converted into JSON and made part of the `--default-capabilities` flag. For example:
```
# raw JSON as an argument
@@ -28,13 +28,13 @@ Appium 1.5 does away with most CLI flags; the remainder can be converted into JS
| --udid | udid |
| --orientation | orientation |
| --no-reset | noReset |
| --full-reset | rullReset |
| --full-reset | fullReset |
| --app-pkg | appPackage |
| --app-activity | appActivity |
| --app-wait-package | appWaitPackage |
| --app-wait-activity | appWaitActivity |
| --device-ready-timeout | deviceReadyTimeout |
| --android-coverage | androidCoverage |
| --android-coverage | androidCoverage |
| --avd | avd |
| --avd-args | avdArgs |
| --use-keystore | useKeystore |
@@ -9,7 +9,7 @@ with certain constraints)
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)
using the [UIAutomation library](ios_predicate.md) (iOS 9.3 and below only)
* `-android uiautomator`: a string corresponding to a recursive element
search using the [UiAutomator Api](uiautomator_uiselector.md) (Android-only)
* `accessibility id`: a string corresponding to a recursive element search
@@ -0,0 +1,193 @@
## Automating Mobile Gestures For iOS With WebDriverAgent/XCTest Backend
Unfortunately Apple's XCTest framework does not natively support W3C standards for
TouchAction interface implementation. Although, it provides rich set of gestures,
inluding these, that are unique for iOS platform. It is possible to directly invoke these
gestures in Appium starting from version 1.6.4-beta.
It is important to rememeber that XCTest and WDA are being constantly changed.
This means all "mobile: *" commands can be also subject of change in Appium
without any preliminary notice.
### mobile: swipe
This gesture performs a simple "swipe" gesture on the particular screen element or
on the application element, which is usually the whole screen. This method does not
accept coordnates and siply emulates single swipe with one finger. It might be
useful for such cases like album pagination, switching views, etc. More advanced
cases may require to call "mobile: dragFromToForDuration", where one can supply
coordinates and duration.
#### Supported arguments
* _direction_: Either 'up', 'down', 'left' or 'right'. The parameter is mandatory
* _element_: Element id to swipe on. Application element will be used instead if this
parameter is not provided
#### Usage examples
```java
// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("direction", "down");
scrollObject.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: swipe", scrollObject);
```
### mobile: scroll
Scrolls the element or the whole screen. Different scrolling strategies are supported.
Arguments define the choosen strategy: either 'name', 'direction', 'predicateString' or
'toVisible' in that order. All strategies are exclusive and only one strategy
can be applied at a single moment of time. Use "mobile: scroll" to emulate precise
scrolling in tables or collection views, where it is already known to which element
the scrolling should be performed. Although, there is one known limitation there: in case
it is necessary to perform too many scroll gestures on parent container to reach the
necessary child element (tens of them) then the method call may fail.
#### Supported arguments
* _element_: Element id to scroll. Application element will be used if this argument is not set
* _name_: the accessibility id of the child element, to which scrolling is performed.
The same result can be achieved by setting _predicateString_ argument to
'name == accessibilityId'. Has no effect if _element_ is not a container
* _direction_: Either 'up', 'down', 'left' or 'right'. The main difference from
_swipe_ call with the same argument is that _scroll_ will try to move the current viewport
exactly to the next/previous page (the term "page" means the content, which fits into
a single device screen)
* _predicateString_: the NSPredicate locator of the child element, to which
the scrolling should be performed. Has no effect if _element_ is not a container
* _toVisible_: Boolean parameter. If set to _true_ then asks to scroll to
the first visible _element_ in the parent container. Has no effect if _element_ is
not set
#### Usage examples
```python
# Python
driver.execute_script('mobile: scroll', {'direction': 'down'});
```
### mobile: pinch
Performs pinch gesture on the given element or on the application element.
#### Supported arguments
* _element_: Element id to pinch on. Application element will be used instead if this
parameter is not provided
* _scale_: Pinch scale of type float. Use a scale between 0 and 1 to "pinch close" or
zoom out and a scale greater than 1 to "pinch open" or zoom in. Mandatory parameter
* _velocity_: The velocity of the pinch in scale factor per second (float value). Mandatory parameter
#### Usage examples
```ruby
# Ruby
execute_script 'mobile: pinch', scale: 0.5, velocity: 1.1
```
### mobile: doubleTap
Performs double tap gesture on the given element or on the screen.
#### Supported arguments
* _element_: Element id to double tap on
* _x_: Screen x tap coordinate of type float. Mandatory parameter only if _element_ is not set
* _y_: Screen y tap coordinate of type float. Mandatory parameter only if _element_ is not set
#### Usage examples
```javascript
// javascript
driver.execute('mobile: doubleTap', {element: element.value.ELEMENT});
```
### mobile: twoFingerTap
Performs two finger tap gesture on the given element or on the application element.
#### Supported arguments
* _element_: Element id to double tap on. Application element will be used instead if this
parameter is not provided
#### Usage examples
```csharp
// c#
Dictionary<string, string> tfTap = new Dictionary<string, string>();
tfTap.Add("element", <element_id>);
((IJavaScriptExecutor)driver).ExecuteScript("mobile: twoFingerTap", tfTap));
```
### mobile: tap
Performs tap gesture by coordinates on the given element or on the screen.
#### Supported arguments
* _element_: Element id to long tap on. _x_ and _y_ tap coordinates
will be calulated relatively to the current element position on the
screen if this argument is provided. Otherwise they should be calculated
relatively to screen borders.
* _x_: x tap coordinate of type float. Mandatory parameter
* _y_: y tap coordinate of type float. Mandatory parameter
#### Usage examples
```php
// PHP
$params = array(array('x' => 100.0, 'y' => 50.0, 'element' => element.GetAttribute("id")));
$driver->executeScript("mobile: tap", $params);
```
### mobile: dragFromToForDuration
Performs drag and drop gesture by coordinates. This can be done either on an element or
on the screen
#### Supported arguments
* _element_: Element id to perform drag on. All the coordinates will be calculated
relatively this this element position on the screen. Absolute screen coordinates
are expected if this argument is not set
* _duration_: Float number of seconds in range [0.5, 60]. How long the tap gesture at
starting drag point should be before to start dragging. Mandatory parameter
* _fromX_: The x coordinate of starting drag point (type float). Mandatory parameter
* _fromY_: The y coordinate of starting drag point (type float). Mandatory parameter
* _toX_: The x coordinate of ending drag point (type float). Mandatory parameter
* _toY_: The y coordinate of ending drag point (type float). Mandatory parameter
#### Usage examples
```java
// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, String> params = new HashMap<String, Object>();
params.put("duration", 1.0);
params.put("fromX", 100);
params.put("fromY", 100);
params.put("toX", 200);
params.put("toY", 200);
params.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: dragFromToForDuration", params);
```
### Advanced Topics
Check [WDA Element Commands API](https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m)
to get the information about the gestures implemented in Facebook WebDriverAgent.
Check Apple XCTest documentation on [XCUIElement](https://developer.apple.com/reference/xctest/xcuielement) and
[XCUICoordinate](https://developer.apple.com/reference/xctest/xcuicoordinate) methods list to get the information
about all gestures available there.
@@ -1,5 +1,7 @@
## iOS Predicate
*NOTE*: iOS predicates are usable in iOS 9.3 and below using the `-ios uiautomation` locator strategy and they are usable in iOS 10 and above using the `-ios predicate string` locator strategy
It is worth looking at *'-ios uiautomation'* search strategy with **Predicates**.
[UIAutomation JavaScript API](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/) has following methods which can are very useful.
@@ -11,11 +13,18 @@ It is worth looking at *'-ios uiautomation'* search strategy with **Predicates**
Native JS search strategy (powered by Apple) provides much more flexibility and is like Xpath.
**[Predicates](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html)** can be used to restrict an elements set to select only those ones for which some condition is true.
For example:
'-ios uiautomation' example:
```java
// java
appiumDriver.findElementsByIosUIAutomation("collectionViews()[0].cells().withPredicate(\"ANY staticTexts.isVisible == TRUE\")")
appiumDriver.findElementsByIosUIAutomation("collectionViews()[0].cells().withPredicate(\"ANY staticTexts.isVisible == TRUE\")");
```
'-ios predicate string' example:
```java
// java
appiumDriver.findElementsByIosNsPredicate("isWDVisible == 1");
```
\- will select only those ```UIACollectionCell``` elements that have visible ```UIAStaticText``` child elements, and themselves are childs of 1st ```UIACollectionView``` element that should be located under the main app window. Here ```staticTexts()``` and ```isVisible()``` are methods available in ```UIAElementArray``` and ```UIAElement``` classes respectively. **Note that ```UIAElementArray``` numbering begins with ```0``` unlike Xpath where indexes counting starts from ```1```**
+13 -30
View File
@@ -60,15 +60,18 @@ capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator")
### Mobile Safari on a Real iOS Device
We use the [SafariLauncher
App](https://github.com/snevesbarros/SafariLauncher) to launch Safari and run
tests against mobile Safari. Once Safari has been launched the Remote Debugger
automatically connects using the
[ios-webkit-debug-proxy](https://github.com/google/ios-webkit-debug-proxy). When
working with ios-webkit-debug-proxy, you have to trust the machine before you can
can run tests against your iOS device.
For iOS 9.3 and below (pre-XCUITest), we use the [SafariLauncher
App](https://github.com/snevesbarros/SafariLauncher) app to launch Safari and
run tests against mobile Safari. This is because Safari is an app that is owned
by Apple, and Instruments cannot launch it on real devices. Once Safari has
been launched by SafariLauncher, the Remote Debugger automatically connects
using the
[ios-webkit-debug-proxy](https://github.com/google/ios-webkit-debug-proxy).
When working with `ios-webkit-debug-proxy`, you have to trust the machine before
you can can run tests against your iOS device.
For instruction on how to install and run ios-webkit-debugger-proxy see [iOS webKit debug proxy](/docs/en/advanced-concepts/ios-webkit-debug-proxy.md) documentation.
For instruction on how to install and run ios-webkit-debugger-proxy see
[iOS WebKit debug proxy](/docs/en/advanced-concepts/ios-webkit-debug-proxy.md) documentation.
### Setup
@@ -76,28 +79,8 @@ Before you can run your tests against Safari on a real device you will need to:
* Have the **ios-webkit-debug-proxy** installed, running and listening on port 27753 (see the
[hybrid docs](/docs/en/advanced-concepts/hybrid.md#execution-against-a-real-ios-device) for instructions)
* Turn on **web inspector** on iOS device (**settings > safari >
advanced**)
* 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:
* **Step 1:** Create a **new App Id** and select the WildCard App ID option and set it to "*"
* **Step 2:** Create a **new Development Profile** and for App Id select the one created in step 1.
* **Step 3:** Select your **certificate(s) and device(s)** and click next.
* **Step 4:** Set the profile name and **generate the profile**.
* **Step 5:** Download the profile and open it with a text editor.
* **Step 6:** Search for the **UUID** and the string for it is your **identity code**.
Now simply include your UDID and device name in your desired capabilities:
```center
{
"udid": '...',
"deviceName": '...',
"browserName": "Safari"
}
```
* Turn on **web inspector** on iOS device (**settings > safari > advanced**)
* Make sure that `SafariLauncher` will work (see the [SafariLauncher docs](safari-launcher.md) for instructions)
### Running your test
@@ -3,7 +3,7 @@
### 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:
simulator, for example by executing the following command in the Xcode project (you can use `xcodebuild -showsdks` to see the list of available SDKs):
> xcodebuild -sdk iphonesimulator6.0
@@ -275,8 +275,6 @@ writing your scripts for older devices or hybrid apps.
### Running your test app with Appium (Windows)
Ensure that Appium is listening
Simply ensure that Appium is listening, and run your test with your test runner of choice.
Deploy your test from your test runner of choice
See our [samples](https://github.com/Microsoft/WinAppDriver/tree/master/Samples) for details
See our [samples](https://github.com/Microsoft/WinAppDriver/tree/master/Samples) for details.
@@ -0,0 +1,103 @@
## Mobile Web on iOS 9.3 and below Real Devices: SafariLauncher
Running mobile web tests on iOS real devices with iOS 9.3 or below, using Instruments,
requires the introduction of a third-party app, [SafariLauncher](https://github.com/snevesbarros/SafariLauncher).
This is necessary because with Instruments there is no way to start the Safari
app on the device. The `SafariLauncher` app just launches, and then launches
Safari. Simple!
In some configurations, Appium is able to automatically build, sign, and install
`SafariLauncher` as it needs, and there is nothing else necessary to be done. If,
however, this is not the case, as is more often so with later versions of
[Xcode](https://developer.apple.com/xcode/), the following configuration needs to
be done before Safari tests on real devices can be successfully run.
### Automatic SafariLauncher configuration
The only thing needed for automatic `SafariLauncher` configuration is to create
a **provisioning profile** that can be used to deploy the `SafariLauncher` App.
This requires, in particular, a wildcard certificate, which is not possible if
your Apple developer account is a free one. If that is the case, skip to the
manual configuration below.
To create a profile for the launcher go into the **Apple Developers Member Center** and:
* **Step 1:** Create a **new App Id** and select the WildCard App ID option and set it to "*"
* **Step 2:** Create a **new Development Profile** and for App Id select the one created in step 1.
* **Step 3:** Select your **certificate(s) and device(s)** and click next.
* **Step 4:** Set the profile name and **generate the profile**.
* **Step 5:** Download the profile and open it with a text editor.
* **Step 6:** Search for the **UUID** and the string for it is your **identity code**.
Now simply include your UDID and device name in your desired capabilities:
```js
{
udid: '...',
deviceName: '...',
platformName: 'iOS',
platformVersion: '9.3',
browserName: 'Safari'
}
```
### Manual SafariLauncher configuration
**Note:** This procedure assumes you have [Xcode](https://developer.apple.com/xcode/) 7.3 or 7.3.1.
It is possible to use the version of [SafariLauncher](https://github.com/snevesbarros/SafariLauncher)
that comes with the [appium-ios-driver](https://github.com/appium/appium-ios-driver),
but if you do, each time you update Appium the procedure will have to be done again.
To get a local copy of `SafariLauncher`, first clone it from [GitHub](https://github.com/):
```bash
git clone https://github.com/snevesbarros/SafariLauncher.git
```
Once you have a local copy of the source code for the `SafariLauncher` app, open
[Xcode](https://developer.apple.com/xcode/) and then open the `SafariLauncher` project
![Opening SafariLauncher project](safari-launcher/opening.png)
In the `SafariLauncher` target pane you will see an error, saying that there needs
to be a provisioning profile for this app
![No provisioning profile error](safari-launcher/no-provisioning-profile.png)
In order to fix this, you first need to enter a "Bundle Identifier" for the app. The default
expected by Appium is `com.bytearc.SafariLauncher`, but this might not be available
for you to build. In that case, choose something else, and make note of it. Then
choose a "Team", and allow the provisioning profile to be created
![Fixing provisioning profile error](safari-launcher/changing-bundleid.png)
Finally, make sure your device is connected to the computer, and choose it as the
target
![Choosing device](safari-launcher/choosing-target.png)
And run the build and install actions to compile the app and push it onto your
device
![Running SafariLauncher](safari-launcher/running.png)
Now you have a working `SafariLauncher` on your device. The app itself is a plain
screen that will launch `Safari` at the click of a button
![SafariLauncher on device](safari-launcher/safarilauncher.png)
The last step is only necessary if you chose a bundle identifier for the app that
is different from the default (`com.bytearc.SafariLauncher`). If you did, it is
necessary to send that to Appium when creating a session, using the `bundleId`
desired capability:
```js
{
udid: '...',
deviceName: '...',
platformName: 'iOS',
platformVersion: '9.3',
browserName: 'Safari',
bundleId: 'com.imurchie.SafariLauncher'
}
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -105,7 +105,7 @@ allows you to do what you wanted to do with one of these views, namely, scroll
it!
**Scrolling**
**Scrolling<a name="scrolling">**
To allow access to this special feature, we override the `execute` or
@@ -117,7 +117,7 @@ To scroll, pass direction in which you intend to scroll as parameter.
```javascript
// javascript
driver.execute("mobile: scroll", [{direction: 'down'}])
driver.execute('mobile: scroll', {direction: 'down'})
```
```java
@@ -154,7 +154,7 @@ Sample to scroll using direction and element.
```javascript
// javascript
driver.execute("mobile: scroll", [{direction: 'down', element: element.value}]);
driver.execute('mobile: scroll', {direction: 'down', element: element.value.ELEMENT});
```
```java
@@ -189,6 +189,14 @@ $params = array(array('direction' => 'down', 'element' => element.GetAttribute("
$driver->executeScript("mobile: scroll", $params);
```
**Swiping**
This is an XCUITest driver specific method that is similar to scrolling (for reference, see
https://developer.apple.com/reference/xctest/xcuielement).
This method has the same API as [Scrolling](#scrolling), just replace "mobile: scroll"
with "mobile: swipe"
**Automating Sliders**
@@ -26,7 +26,7 @@ To test a UWP app, you can use any Selenium supported language and simply specif
// Launch the AlarmClock app
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", "Microsoft.WindowsAlarms_8wekyb3d8bbwe!App");
AlarmClockSession = new IOSDriver<IOSElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
AlarmClockSession = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
// Control the AlarmClock app
AlarmClockSession.FindElementByAccessibilityId("AddAlarmButton").Click();
AlarmClockSession.FindElementByAccessibilityId("AlarmNameTextBox").Clear();
@@ -38,7 +38,7 @@ To test a classic Windows app, you can also use any Selenium supported language
// Launch Notepad
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", @"C:\Windows\System32\notepad.exe");
NotepadSession = new IOSDriver<IOSElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
NotepadSession = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
// Control the AlarmClock app
NotepadSession.FindElementByClassName("Edit").SendKeys("This is some text");
```
+4 -1
View File
@@ -1,4 +1,5 @@
/* eslint no-console:0 */
/* eslint-disable promise/prefer-await-to-callbacks */
"use strict";
// turn all logging on since we have tests that rely on npmlog logs actually
@@ -32,10 +33,12 @@ gulp.task('fixShrinkwrap', function (done) {
boilerplate({
build: 'appium',
jscs: false,
jshint: false,
test: {
files: ['${testDir}/**/*-specs.js']
},
extraPrepublishTasks: ['fixShrinkwrap'],
preCommitTasks: ['eslint', 'once'],
});
// generates server arguments readme
@@ -66,7 +69,7 @@ gulp.task('docs', ['transpile'], function () {
}
// handle empty objects
if (JSON.stringify(argOpts.defaultValue) === '{}'){
if (JSON.stringify(argOpts.defaultValue) === '{}') {
argOpts.defaultValue = '{}';
}
+63 -17
View File
@@ -11,6 +11,7 @@ import { SelendroidDriver } from 'appium-selendroid-driver';
import { XCUITestDriver } from 'appium-xcuitest-driver';
import { YouiEngineDriver } from 'appium-youiengine-driver';
import { WindowsDriver } from 'appium-windows-driver';
import { MacDriver } from 'appium-mac-driver';
import B from 'bluebird';
import util from 'util';
@@ -86,6 +87,10 @@ class AppiumDriver extends BaseDriver {
return WindowsDriver;
}
if (caps.platformName.toLowerCase() === 'mac') {
return MacDriver;
}
let msg;
if (caps.automationName) {
msg = `Could not find a driver for automationName '${caps.automationName}' and platformName ` +
@@ -96,6 +101,26 @@ class AppiumDriver extends BaseDriver {
throw new Error(`${msg} Please check your desired capabilities.`);
}
getDriverVersion (driver) {
const NAME_DRIVER_MAP = {
SelendroidDriver: 'appium-selendroid-driver',
AndroidUiautomator2Driver: 'appium-uiautomator2-driver',
XCUITestDriver: 'appium-xcuitest-driver',
YouiEngineDriver: 'appium-youiengine-driver',
FakeDriver: 'appium-fake-driver',
AndroidDriver: 'appium-android-driver',
IosDriver: 'appium-ios-driver',
WindowsDriver: 'appium-windows-driver',
MacDriver: 'appium-mac-driver',
};
if (!NAME_DRIVER_MAP[driver.name]) {
log.warn(`Unable to get version of driver '${driver.name}'`);
return;
}
let {version} = require(`${NAME_DRIVER_MAP[driver.name]}/package.json`);
return version;
}
async getStatus () {
let config = await getAppiumConfig();
let gitSha = config['git-sha'];
@@ -114,16 +139,23 @@ class AppiumDriver extends BaseDriver {
return sessions;
}
async createSession (caps, reqCaps) {
caps = _.defaults(_.clone(caps), this.args.defaultCapabilities);
let InnerDriver = this.getDriverForCaps(caps);
let curSessions;
log.info(`Creating new ${InnerDriver.name} session`);
printNewSessionAnnouncement (driver, caps) {
let driverVersion = this.getDriverVersion(driver);
let introString = driverVersion ?
`Creating new ${driver.name} (v${driverVersion}) session` :
`Creating new ${driver.name} session`;
log.info(introString);
log.info('Capabilities:');
util.inspect(caps);
for (let [cap, value] of _.toPairs(caps)) {
log.info(` ${cap}: ${util.inspect(value)}`);
}
}
async createSession (caps, reqCaps) {
caps = _.defaults(_.clone(caps), this.args.defaultCapabilities);
let InnerDriver = this.getDriverForCaps(caps);
this.printNewSessionAnnouncement(InnerDriver, caps);
// sessionOverride server flag check
// this will need to be re-thought when we go to multiple session support
@@ -140,6 +172,7 @@ class AppiumDriver extends BaseDriver {
}
}
let curSessions;
try {
curSessions = this.curSessionDataForDriver(InnerDriver);
} catch (e) {
@@ -150,18 +183,11 @@ class AppiumDriver extends BaseDriver {
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
// to open another session later on.
// TODO: this should be removed and replaced by a onShutdown callback.
d.onUnexpectedShutdown
.then(() => { throw new Error('Unexpected shutdown'); })
.catch(B.CancellationError, () => {})
.catch((err) => {
log.warn(`Closing session, cause was '${err.message}'`);
log.info(`Removing session ${innerSessionId} from our master session list`);
delete this.sessions[innerSessionId];
})
.done();
// this is an async function but we don't await it because it handles
// an out-of-band promise which is fulfilled if the inner driver
// unexpectedly shuts down
this.attachUnexpectedShutdownHandler(d, innerSessionId);
log.info(`New ${InnerDriver.name} session created successfully, session ` +
`${innerSessionId} added to master session list`);
@@ -172,6 +198,26 @@ class AppiumDriver extends BaseDriver {
return [innerSessionId, dCaps];
}
async attachUnexpectedShutdownHandler (driver, innerSessionId) {
// Remove the session on unexpected shutdown, so that we are in a position
// to open another session later on.
// TODO: this should be removed and replaced by a onShutdown callback.
try {
await driver.onUnexpectedShutdown; // this is a cancellable promise
// if we get here, we've had an unexpected shutdown, so error
throw new Error('Unexpected shutdown');
} catch (e) {
if (e instanceof B.CancellationError) {
// if we cancelled the unexpected shutdown promise, that means we
// no longer care about it, and can safely ignore it
return;
}
log.warn(`Closing session, cause was '${e.message}'`);
log.info(`Removing session ${innerSessionId} from our master session list`);
delete this.sessions[innerSessionId];
}
}
curSessionDataForDriver (InnerDriver) {
let data = _.values(this.sessions)
.filter((s) => s.constructor.name === InnerDriver.name)
+12
View File
@@ -42,6 +42,18 @@ async function postRequest (data, addr, port) {
logger.errorAndThrow(`Syntax error in node configuration file: ${err.message}`);
}
// Move Selenium 3 configuration properties to configuration object
if (!jsonObject.hasOwnProperty('configuration')) {
let configuration = {};
for (var property in jsonObject) {
if (jsonObject.hasOwnProperty(property) && property !== 'capabilities') {
configuration[property] = jsonObject[property];
delete jsonObject[property];
}
}
jsonObject.configuration = configuration;
}
// if the node config does not have the appium/webdriver url, host, and port,
// automatically add it based on how appium was initialized
// otherwise, we will take whatever the user setup
+4 -3
View File
@@ -1,5 +1,6 @@
import { getLogger } from 'appium-logger';
import { logger } from 'appium-support';
let logger = getLogger('Appium');
export default logger;
let log = logger.getLogger('Appium');
export default log;
+13 -14
View File
@@ -1,13 +1,12 @@
import npmlog from 'npmlog';
import { patchLogger } from 'appium-logger';
import winston from 'winston';
import { fs } from 'appium-support';
import { fs, logger } from 'appium-support';
import 'date-utils';
import _ from 'lodash';
// set up distributed logging before everything else
patchLogger(npmlog);
logger.patchLogger(npmlog);
global._global_npmlog = npmlog;
// npmlog is used only for emitting, we use winston for output
@@ -36,7 +35,7 @@ const npmToWinstonLevels = {
error: 'error',
};
let logger = null;
let log = null;
let timeZone = null;
function timestamp () {
@@ -53,7 +52,7 @@ function timestamp () {
// having to create 2 loggers.
function applyStripColorPatch (transport) {
let _log = transport.log.bind(transport);
transport.log = function (level, msg, meta, callback) {
transport.log = function (level, msg, meta, callback) { // eslint-disable-line promise/prefer-await-to-callbacks
let code = /\u001b\[(\d+(;\d+)*)?m/g;
msg = ('' + msg).replace(code, '');
_log(level, msg, meta, callback);
@@ -184,7 +183,7 @@ async function init (args) {
// object
clear();
logger = new (winston.Logger)({
log = new (winston.Logger)({
transports: await _createTransports(args)
});
@@ -196,7 +195,7 @@ async function init (args) {
let prefix = `[${logObj.prefix}]`;
msg = `${prefix.magenta} ${msg}`;
}
logger[winstonLevel](msg);
log[winstonLevel](msg);
if (args.logHandler && typeof args.logHandler === "function") {
args.logHandler(logObj.level, msg);
}
@@ -204,21 +203,21 @@ async function init (args) {
});
logger.setLevels(levels);
log.setLevels(levels);
// 8/19/14 this is a hack to force Winston to print debug messages to stdout rather than stderr.
// TODO: remove this if winston provides an API for directing streams.
if (levels[logger.transports.console.level] === levels.debug) {
logger.debug = function (msg) {
logger.info('[debug] ' + msg);
if (levels[log.transports.console.level] === levels.debug) {
log.debug = function (msg) {
log.info('[debug] ' + msg);
};
}
}
function clear () {
if (logger) {
for (let transport of _.keys(logger.transports)) {
logger.remove(transport);
if (log) {
for (let transport of _.keys(log.transports)) {
log.remove(transport);
}
}
npmlog.removeAllListeners('log');
+35 -1
View File
@@ -48,9 +48,32 @@ function logDeprecationWarning (deprecatedArgs) {
}
function logNonDefaultArgsWarning (args) {
// cleanly print out the default arguments, allowing for prefix and timestamp
function getValueArray (obj, indent = ' ') {
if (!_.isObject(obj)) {
return [obj];
}
let strArr = ['{'];
for (let [arg, value] of _.toPairs(obj)) {
if (!_.isObject(value)) {
strArr.push(`${indent} ${arg}: ${value}`);
} else {
value = getValueArray(value, `${indent} `);
strArr.push(`${indent} ${arg}: ${value.shift()}`);
strArr.push(...value);
}
}
strArr.push(`${indent}}`);
return strArr;
}
logger.info('Non-default server args:');
for (let [arg, value] of _.toPairs(args)) {
logger.info(` ${arg}: ${util.inspect(value)}`);
value = getValueArray(value);
logger.info(` ${arg}: ${value.shift()}`);
for (let val of value) {
logger.info(val);
}
}
}
@@ -132,6 +155,17 @@ async function main (args = null) {
await server.close();
throw err;
}
process.once('SIGINT', async function () {
logger.info(`Received SIGINT - shutting down`);
await server.close();
});
process.once('SIGTERM', async function () {
logger.info(`Received SIGTERM - shutting down`);
await server.close();
});
logServerPort(args.address, args.port);
return server;
+3 -2
View File
@@ -326,7 +326,7 @@ const args = [
}],
[['--suppress-adb-kill-server'], {
dest: 'suppressAdbKillServer',
dest: 'suppressKillServer',
defaultValue: false,
action: 'storeTrue',
required: false,
@@ -782,7 +782,8 @@ function getParser () {
let parser = new ArgumentParser({
version: pkgObj.version,
addHelp: true,
description: 'A webdriver-compatible server for use with native and hybrid iOS and Android applications.'
description: 'A webdriver-compatible server for use with native and hybrid iOS and Android applications.',
prog: process.argv[1] || 'Appium'
});
let allArgs = _.union(args, deprecatedArgs);
parser.rawArgs = allArgs;
+39 -38
View File
@@ -11,7 +11,7 @@
"firefoxos",
"testing"
],
"version": "1.6.0-beta3",
"version": "1.6.4-beta.2",
"author": "https://github.com/appium",
"license": "Apache-2.0",
"repository": {
@@ -34,29 +34,29 @@
"doc": "./docs"
},
"dependencies": {
"appium-android-driver": "^1.10.27",
"appium-base-driver": "^2.0.19",
"appium-fake-driver": "^0.1.10",
"appium-ios-driver": "^1.12.27",
"appium-logger": "^2.1.0",
"appium-selendroid-driver": "^1.3.4",
"appium-support": "^2.3.3",
"appium-uiautomator2-driver": "^0.x",
"appium-xcuitest-driver": "^2.0.25",
"appium-youiengine-driver": "^1.0.6",
"appium-windows-driver": "^0.x",
"argparse": "^1.0.7",
"asyncbox": "^2.3.1",
"appium-android-driver": "1.x",
"appium-base-driver": "2.x",
"appium-fake-driver": "0.x",
"appium-ios-driver": "1.x",
"appium-mac-driver": "1.x",
"appium-selendroid-driver": "1.x",
"appium-support": "2.x",
"appium-uiautomator2-driver": "0.x",
"appium-xcuitest-driver": "2.x",
"appium-youiengine-driver": "1.x",
"appium-windows-driver": "0.x",
"argparse": "1.x",
"asyncbox": "2.x",
"babel-runtime": "=5.8.24",
"bluebird": "^2.10.2",
"continuation-local-storage": "^3.1.7",
"date-utils": "^1.2.21",
"lodash": "^4.13.1",
"npmlog": "^2.0.4",
"request-promise": "^1.0.2",
"source-map-support": "^0.4.0",
"teen_process": "^1.7.1",
"winston": "^2.2.0"
"bluebird": "2.x",
"continuation-local-storage": "3.x",
"date-utils": "1.x",
"lodash": "4.x",
"npmlog": "2.x",
"request-promise": "1.x",
"source-map-support": "0.x",
"teen_process": "1.x",
"winston": "2.x"
},
"scripts": {
"prepublish": "gulp prepublish",
@@ -71,22 +71,23 @@
"test"
],
"devDependencies": {
"appium-gulp-plugins": "^1.4.5",
"babel-eslint": "^6.1.0",
"chai": "^3.5.0",
"chai-as-promised": "^5.3.0",
"eslint": "^2.13.1",
"eslint-config-appium": "^0.0.8",
"eslint-plugin-babel": "^3.3.0",
"eslint-plugin-import": "^1.9.2",
"eslint-plugin-mocha": "^3.0.0",
"gulp": "^3.9.1",
"mocha": "^2.5.3",
"pre-commit": "^1.1.3",
"sinon": "^1.17.4",
"wd": "~0.4.0"
"appium-gulp-plugins": "1.x",
"babel-eslint": "6.x",
"chai": "3.x",
"chai-as-promised": "5.x",
"eslint": "2.x",
"eslint-config-appium": "0.x",
"eslint-plugin-babel": "3.x",
"eslint-plugin-import": "1.x",
"eslint-plugin-mocha": "3.x",
"eslint-plugin-promise": "3.x",
"gulp": "3.x",
"mocha": "2.x",
"pre-commit": "1.x",
"sinon": "1.x",
"wd": "1.x"
},
"optionalDependencies": {
"fsevents": "^1.0.12"
"fsevents": "1.x"
}
}
+6 -18
View File
@@ -32,6 +32,7 @@
"appium-unlock",
"appium-webdriveragent-driver",
"appium-xcode",
"appium-xcuitest-driver",
"authorize-ios",
"io.appium.settings",
"jsonwp-status",
@@ -42,7 +43,6 @@
"appium-ci",
"appium-ci-standalone-tools",
"appium-gulp-plugins",
"appium-package-master",
"appium-transpile-runtime",
"appium-jenkins",
"teen_process",
@@ -70,35 +70,23 @@
"appium-core": [
"imurchie",
"jlipps",
"jonahss",
"moizjv",
"scottdixon",
"sebv"
"dangraham"
],
"appium-contrib": [
"imurchie",
"jlipps",
"jonahss",
"moizjv",
"scottdixon",
"sebv",
"bootstraponline"
"bootstraponline",
"dangraham"
],
"appium-tools": [
"imurchie",
"jlipps",
"jonahss",
"moizjv",
"scottdixon",
"sebv"
"dangraham"
],
"appium-apps": [
"imurchie",
"jlipps",
"jonahss",
"moizjv",
"sebv",
"scottdixon",
"dangraham",
"bootstraponline"
],
"extra-jlipps": [
-1
View File
@@ -5,7 +5,6 @@
"trailing": true,
"node": true,
"eqeqeq": true,
"trailing": true,
"expr": true,
"white": true,
"indent": 2,
+24
View File
@@ -194,6 +194,30 @@ describe('Config', () => {
});
});
describe('parsing args with empty argv[1]', () => {
let argv1;
before(() => {
argv1 = process.argv[1];
});
after(() => {
process.argv[1] = argv1;
});
it('should not fail if process.argv[1] is undefined', () => {
process.argv[1] = undefined;
let args = getParser();
args.prog.should.be.equal('Appium');
});
it('should set "prog" to process.argv[1]', () => {
process.argv[1] = 'Hello World';
let args = getParser();
args.prog.should.be.equal('Hello World');
});
});
describe('validateServerArgs', () => {
let parser = getParser();
parser.debug = true; // throw instead of exit on error; pass as option instead?
+72 -24
View File
@@ -9,11 +9,13 @@ import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { XCUITestDriver } from 'appium-xcuitest-driver';
import { IosDriver } from 'appium-ios-driver';
import { sleep } from 'asyncbox';
chai.should();
chai.use(chaiAsPromised);
const BASE_CAPS = {platformName: 'Fake', deviceName: 'Fake', app: TEST_FAKE_APP};
const SESSION_ID = 1;
describe('AppiumDriver', () => {
describe('getAppiumRouter', () => {
@@ -36,20 +38,20 @@ describe('AppiumDriver', () => {
return [appium, mockFakeDriver];
}
describe('createSession', () => {
let appium
, mockFakeDriver;
let appium;
let mockFakeDriver;
beforeEach(() => {
[appium, mockFakeDriver] = getDriverAndFakeDriver();
});
afterEach(() => {
afterEach(async () => {
mockFakeDriver.restore();
appium.args.defaultCapabilities = {};
await appium.deleteSession(SESSION_ID);
});
it('should call inner driver\'s createSession with desired capabilities', async () => {
mockFakeDriver.expects("createSession")
.once().withExactArgs(BASE_CAPS, undefined, [])
.returns([1, BASE_CAPS]);
.returns([SESSION_ID, BASE_CAPS]);
await appium.createSession(BASE_CAPS);
mockFakeDriver.verify();
});
@@ -59,7 +61,7 @@ describe('AppiumDriver', () => {
appium.args.defaultCapabilities = defaultCaps;
mockFakeDriver.expects("createSession")
.once().withArgs(allCaps)
.returns([1, allCaps]);
.returns([SESSION_ID, allCaps]);
await appium.createSession(BASE_CAPS);
mockFakeDriver.verify();
});
@@ -70,7 +72,7 @@ describe('AppiumDriver', () => {
appium.args.defaultCapabilities = defaultCaps;
mockFakeDriver.expects("createSession")
.once().withArgs(BASE_CAPS)
.returns([1, BASE_CAPS]);
.returns([SESSION_ID, BASE_CAPS]);
await appium.createSession(BASE_CAPS);
mockFakeDriver.verify();
});
@@ -98,7 +100,7 @@ describe('AppiumDriver', () => {
mockFakeDriver.expects("createSession")
.once().withExactArgs(BASE_CAPS, undefined, [])
.returns([1, BASE_CAPS]);
.returns([SESSION_ID, BASE_CAPS]);
await appium.createSession(BASE_CAPS);
sessions = await appium.getSessions();
@@ -111,14 +113,13 @@ describe('AppiumDriver', () => {
});
});
describe('deleteSession', () => {
let appium
, mockFakeDriver;
let appium;
let mockFakeDriver;
beforeEach(() => {
[appium, mockFakeDriver] = getDriverAndFakeDriver();
});
afterEach(() => {
mockFakeDriver.restore();
appium.args.defaultCapabilities = {};
});
it('should remove the session if it is found', async () => {
let [sessionId] = await appium.createSession(BASE_CAPS);
@@ -135,22 +136,32 @@ describe('AppiumDriver', () => {
.returns();
await appium.deleteSession(sessionId);
mockFakeDriver.verify();
// cleanup, since we faked the delete session call
await mockFakeDriver.object.deleteSession();
});
});
describe('getSessions', () => {
let appium;
let sessions;
before(() => {
appium = new AppiumDriver({});
});
afterEach(async () => {
for (let session of sessions) {
await appium.deleteSession(session.id);
}
});
it('should return an empty array of sessions', async () => {
let sessions = await appium.getSessions();
sessions = await appium.getSessions();
sessions.should.be.an.array;
sessions.should.be.empty;
});
it('should return sessions created', async () => {
let session1 = await appium.createSession(_.extend(_.clone(BASE_CAPS), {cap: 'value'}));
let session2 = await appium.createSession(_.extend(_.clone(BASE_CAPS), {cap: 'other value'}));
let sessions = await appium.getSessions();
sessions = await appium.getSessions();
sessions.should.be.an.array;
sessions.should.have.length(2);
sessions[0].id.should.equal(session1[0]);
@@ -158,20 +169,57 @@ describe('AppiumDriver', () => {
sessions[1].id.should.equal(session2[0]);
sessions[1].capabilities.should.eql(session2[1]);
});
describe('getStatus', () => {
let appium;
before(() => {
appium = new AppiumDriver({});
});
it('should return a status', async () => {
let status = await appium.getStatus();
status.build.should.exist;
status.build.version.should.exist;
});
});
describe('getStatus', () => {
let appium;
before(() => {
appium = new AppiumDriver({});
});
it('should return a status', async () => {
let status = await appium.getStatus();
status.build.should.exist;
status.build.version.should.exist;
});
});
describe('sessionExists', () => {
});
describe('attachUnexpectedShutdownHandler', () => {
let appium
, mockFakeDriver;
beforeEach(() => {
[appium, mockFakeDriver] = getDriverAndFakeDriver();
});
afterEach(async () => {
await mockFakeDriver.object.deleteSession();
mockFakeDriver.restore();
appium.args.defaultCapabilities = {};
});
it('should remove session if inner driver unexpectedly exits with an error', async () => {
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
_.keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].unexpectedShutdownDeferred.reject(new Error("Oops"));
// let event loop spin so rejection is handled
await sleep(1);
_.keys(appium.sessions).should.not.contain(sessionId);
});
it('should remove session if inner driver unexpectedly exits with no error', async () => {
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
_.keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].unexpectedShutdownDeferred.resolve();
// let event loop spin so rejection is handled
await sleep(1);
_.keys(appium.sessions).should.not.contain(sessionId);
});
it('should not remove session if inner driver cancels unexpected exit', async () => {
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
_.keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].onUnexpectedShutdown.cancel();
// let event loop spin so rejection is handled
await sleep(1);
_.keys(appium.sessions).should.contain(sessionId);
});
});
describe('getDriverForCaps', () => {
it('should not blow up if user does not provide platformName', () => {
let appium = new AppiumDriver({});
+2 -1
View File
@@ -1,5 +1,6 @@
import path from 'path';
import wd from 'wd';
import B from 'bluebird';
const TEST_HOST = 'localhost';
const TEST_PORT = 4723;
@@ -18,7 +19,7 @@ function initSession (caps) {
after(async () => {
await driver.quit();
});
return new Promise((_resolve) => {
return new B((_resolve) => {
resolve = _resolve;
});
}
+6 -6
View File
@@ -2,15 +2,15 @@
import { init as logsinkInit, clear as logsinkClear } from '../lib/logsink';
import sinon from 'sinon';
import { getLogger } from 'appium-logger';
import { logger } from 'appium-support';
// 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');
let log = logger.getLogger('Appium');
describe('Logger', () => {
describe('logging', () => {
let stderrSpy;
let stdoutSpy;
beforeEach(() => {
@@ -31,9 +31,9 @@ describe('Logger', () => {
const debugMsg = 'some debug';
function doLogging () {
logger.error(errorMsg);
logger.warn(warnMsg);
logger.debug(debugMsg);
log.error(errorMsg);
log.warn(warnMsg);
log.debug(debugMsg);
}
it('should send error, info and debug when loglevel is debug', async () => {