docs: update migration guide to reflect changes to configuration files, arguments, etc.
add a JS example config file
MODIFY
docs/en/advanced-concepts/migrating-to-appium-2.0.md
docs/en/advanced-concepts/migrating-to-appium-2.0.md
@@ -4,7 +4,7 @@ This document is a guide for those who are using Appium 1.x and wish to migrate
## Overview of Appium 2.0
-Appium 2.0 is the most major new release of Appium in over 5 years. The changes in Appium 2.0 are *not* primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2.0 reenvisions Appium as a *platform* where "drivers" (code projects that introduce support for automation of a given platform) and "plugins" (code projects that allow for overriding, altering, extending, or adding behaviors to Appium) can be easily created and shared.
+Appium 2.0 is the most major new release of Appium in over 5 years. The changes in Appium 2.0 are _not_ primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2.0 reenvisions Appium as a _platform_ where "drivers" (code projects that introduce support for automation of a given platform) and "plugins" (code projects that allow for overriding, altering, extending, or adding behaviors to Appium) can be easily created and shared.
At the same time, the Appium project is taking the opportunity to remove many old and deprecated bits of functionality.
@@ -14,7 +14,7 @@ Together these do introduce a few breaking changes to how Appium is installed, h
Have a look at the [Appium 2.0 release notes](https://github.com/appium/appium/releases/tag/v2.0.0-beta) for a more comprehensive list of changes. Here we call out the breaking changes and what you need to do do account for them.
-#### :bangbang: Installing drivers during setup
+### :bangbang: Installing drivers during setup
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server. This is no longer the case. Simply installing Appium 2.0 (e.g., by `npm install -g appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../drivers/driver-cli.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
@@ -32,59 +32,43 @@ npm install -g appium --drivers=xcuitest,uiautomator2
This will install Appium and the two drivers for you in one go.
-#### :bangbang: Driver-specific command line options
+### :bangbang: Driver-specific command line options
With Appium 1.x, command-line options specific to particular drivers were all hosted on the main Appium server. So, for example, `--chromedriver-executable` was a CLI parameter you could use with Appium to set the location of a specific Chromedriver version for use with, say, the UiAutomator2 driver.
-With Appium 2.x, all driver- and platform-specific CLI params have been moved to the drivers themselves. To access them, we use a single CLI param called `--driver-args`, whose value is a JSON string or a path to a JSON file, which when parsed is an object of the following form:
+With Appium 2.x, all driver- and platform-specific CLI params have been moved to the drivers themselves. To access them, you'll now need to prepend the argument with the extension type (either `driver` or `plugin`) and the name of the extension. For example, `--chromedriver-executable` becomes `--driver-uiautomator2-chromedriver-executable`.
-```json
-{
- "<driver-name>": {
- "<arg-name>": <arg-value>,
- ...
- },
- ...
-}
-```
-
-In other words, you can construct an object with parameters for one or more drivers by their name. The parameters which are available to use this way will be documented by the driver itself. So to see what has become of `--chromedriver-executable`, you can head to the UiAutomator2 driver documentation. In this case, we'd start Appium like this:
-
-```
-appium --driver-args='{"uiautomator2": {"chromedriverExecutable": "/path/to/chromedriver/binary"}}'
-```
-
-#### :bangbang: Driver updates
+### :bangbang: Driver updates
In the past, to get updates to your iOS or Android drivers, you'd simply wait for those updates to be rolled into a new release of Appium, and then update your Appium version. With Appium 2.x, the Appium server and the Appium drivers are versioned and released separately. This means that drivers can be on their own release cadence and that you can get driver updates as they happen, rather than waiting for a new Appium server release. The way to check for driver updates is with the CLI:
-```
+```bash
appium driver list --updates
```
If any updates are available, you can then run the `update` command for any given driver:
-```
+```bash
appium driver update xcuitest
```
To update the Appium server itself, you do the same thing as in the past: `npm install -g appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
-#### :bangbang: Protocol changes
+### :bangbang: Protocol changes
Appium's API is based on the [W3C WebDriver Protocol](https://www.w3.org/TR/webdriver/), and it has supported this protocol for years. Before the W3C WebDriver Protocol was designed as a web standard, several other protocols were used for both Selenium and Appium. These protocols were the "JSONWP" (JSON Wire Protocol) and "MSJONWP" (Mobile JSON Wire Protocol). The W3C Protocol differs from the (M)JSONWP protocols in a few small ways.
Up until Appium 2.0, Appium supported both protocols, so that older Selenium/Appium clients could still communicate with newer Appium servers. Moving forward, support for older protocols will be removed.
-:bangbang: *Capabilities*
+### :bangbang: _Capabilities_
One significant difference between old and new protocols is in the format of capabilities. Previously called "desired capabilities", and now called simply "capabilities", there is now a requirement for a so-called "vendor prefix" on any non-standard capabilities. The list of standard capabilities is given in the [WebDriver Protocol spec](https://www.w3.org/TR/webdriver/#capabilities), and includes a few commonly used capabilities such as `browserName` and `platformName`.
These standard capabilities continue to be used as-is. All other capabilities must include a "vendor prefix" in their name. A vendor prefix is a string followed by a colon, such as `appium:`. Most of Appium's capabilities go beyond the standard W3C capabilities and must therefore include vendor prefixes (we recommend that you use `appium:` unless directed otherwise by documentation). For example:
-* `appium:app`
-* `appium:noReset`
-* `appium:deviceName`
+- `appium:app`
+- `appium:noReset`
+- `appium:deviceName`
This requirement may or may not be a breaking change for your test suites when targeting Appium 2.0. If you're using an updated Appium client, the client will add the `appium:` prefix for you on all necessary capabilities. New versions of the Appium Inspector tool will also do this. Cloud-based Appium providers may also do this. So simply be aware that if you get any messages to the effect that your capabilities lack a vendor prefix, this is how you solve that problem.
@@ -106,15 +90,15 @@ To make everyone's lives a bit easier, we've also introduced the option of wrapp
(Of course, each client will have a different way of creating structured capabilities like `appium:options` or other ones that you might have seen such as `goog:chromeOptions`). NB: capabilities that show up in `appium:options` will overwrite capabilities of the same name that show up at the top level of the object.
-:bangbang: *Removed Commands*
+### :bangbang: _Removed Commands_
Commands which were a part of the old JSON Wire Protocol and not a part of the W3C Protocol are no longer available:
-* TODO (these commands are being identified and removed and will be updated here when complete)
+- TODO (these commands are being identified and removed and will be updated here when complete)
If you use a modern Appium or Selenium client, you should no longer have access to these anyway, so any breaking changes should appear on the client side first and foremost.
-#### :bangbang: Image analysis features moved to plugin
+### :bangbang: Image analysis features moved to plugin
One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](#TODO). This allows people to opt into features which require extra time to download or extra system setup. The various image-related features of Appium (image comparison, finding elements by image, etc...) have been moved into an officially supported plugin called [images](https://github.com/appium/appium-plugins/tree/master/packages/images).
@@ -125,19 +109,19 @@ If you use these image-related methods, to continue accessing them you will need
Image-related commands will also be removed on the client side of things, which means you will need to follow the instructions on the plugin README for installing client-side plugins to access these features.
-#### :bangbang: Old drivers removed
+### :bangbang: Old drivers removed
The old iOS and Android (UiAutomator 1) drivers and related tools (e.g., `authorize-ios`) have been removed. They haven't been relevant for many years anyway.
-#### :warning: Internal packages renamed
+### :warning: Internal packages renamed
Some Appium-internal NPM packages have been renamed (for example, `appium-base-driver` is now `@appium/base-driver`). This is not a breaking change for Appium users, only for people who have built software that directly incorporates Appium's code.
-#### :warning: "WD" JavaScript client library no longer supported
+### :warning: "WD" JavaScript client library no longer supported
For many years, some of Appium's authors maintained the [WD](https://github.com/admc/wd) client library. This library has been deprecated and has not been updated for use with the W3C WebDriver protocol. As such, if you're using this library you'll need to move to a more modern one. We recommend [WebdriverIO](https://webdriver.io).
-#### :warning: Appium Inspector split out from Appium Desktop
+### :warning: Appium Inspector split out from Appium Desktop
The inspecting portion of Appium Desktop has been moved to its own app, Appium Inspector: [github.com/appium/appium-inspector](https://github.com/appium/appium-inspector). It's fully compatible with Appium 2.0 servers. Simply download it and run it on its own. You no longer need the GUI Appium Desktop server to inspect apps. The Appium Desktop server will continue to be supported at its original site: [github.com/appium/appium-desktop](https://github.com/appium/appium-desktop). It will simply no longer bundle the Inspector with it.
@@ -147,24 +131,140 @@ You can also now use the Appium Inspector without downloading anything, by visit
Apart from the breaking changes mentioned above, in this section is a list of some of the major new features you may wish to take advantage of with Appium 2.0.
-#### Plugins
+### Plugins
-:tada: *Server Plugins*
+#### :tada: _Server Plugins_
TODO
-:tada: *Client Plugins*
+#### :tada: _Client Plugins_
TODO
-#### :tada: Install drivers and plugins from anywhere
+### :tada: Install drivers and plugins from anywhere
TODO
-#### :tada: Driver and Plugin CLI args
+### :tada: Configuration Files
+
+Appium now supports _configuration files_ in addition to command-line arguments. In a nutshell, nearly all arguments which Appium 1.x required to be provided on the CLI are now able to be expressed via a configuration file. Configuration files may be in JSON, JS, or YAML format.
+
+Please note that CLI arguments have _precedence_ over configuration files; if a value is set in a config file _and_ via CLI argument, the CLI argument is preferred.
+
+#### Supported Config File Locations
+
+Configuration files can be named anything, but the following filenames will be automatically discovered and loaded by Appium:
+
+- `.appiumrc.json`
+- `.appiumrc.yaml`
+- `.appiumrc.yml`
+- `.appiumrc.js`
+- `.appiumrc.cjs`
+- `appium.config.js`
+- `appium.config.cjs`
+- `.appiumrc` (which is considered to be JSON)
+
+Further, the `appium` property in your project's `package.json` can contain the configuration.
+
+Appium will search _up_ the directory tree from the current working directory for one of these files. If it reaches the current user's home directory or filesystem root, it will stop looking.
+
+To specify a custom location for your config file (and avoid searching), use `appium --config-file /path/to/config/file`.
+
+> Note: Configuration files in ESM format are not currently supported.
+
+#### Configuration File Format
+
+You might want to see examples:
+
+- [Appium Configuration - JSON](../../../sample-code/appium.config.sample.json)
+- [Appium Configuration - YAML](../../../sample-code/appium.config.sample.yaml)
+- [Appium Configuration - JS](../../../sample-code/appium.config.sample.js)
+
+Description of the format is available, as well:
+
+- [Appium Configuration File JSON Schema](../../../packages/appium/lib/appium-config.schema.json)
+- [TypeScript declarations for Appium Configuration](../../../packages/appium/types/appium-config.d.ts)
+
+To describe in words, the config file will have a root `server` property, and all arguments are child properties. For certain properties which must be supplied as comma-delimited lists, JSON strings, and/or external filepaths, these instead will be of their "native" type. For example, `--use-plugins <value>` needs `<value>` to be comma-delimited string or path to a delimited file. However, the config file just wants an array, e.g.,:
+
+```json
+{
+ "server": {
+ "use-plugins": ["my-plugin", "some-other-plugin"]
+ }
+}
+```
+
+For `driver`-and-`plugin`-specific configuration, these live under the `server.driver` and `server.plugin` properties, respectively. Each driver or plugin will have its own named property, and the values of any specific configuration it provides are under this. For example:
+
+```json
+{
+ "server": {
+ "driver": {
+ "xcuitest": {
+ "webkit-debug-proxy-port": 5400
+ }
+ }
+ }
+}
+```
+
+> Note: The above configuration corresponds to the `--driver-xcuitest-webkid-debug-proxy-port` CLI argument.
+
+All properties are case-sensitive and will be in kebab-case. For example, `callback-port` is allowed, but `callbackPort` is not.
+
+### :tada: Driver and Plugin CLI args
TODO
+#### For Extension Authors
+
+To define CLI arguments (or configuration properties), your extension must provide a _schema_. In the `appium` property of your extension's `package.json`, add a `schema` property. This will either a) be a schema itself, or b) be a path to a schema.
+
+The rules for these schemas:
+
+- Schemas must conform to [JSON Schema Draft-07](https://ajv.js.org/json-schema.html#draft-07).
+- Schemas must be in JSON or JS (CommonJS) format.
+- Custom `$id` values are unsupported. To use `$ref`, provide a value relative to the schema root, e.g., `/properties/foo`.
+- Known values of the `format` keyword are likely supported, but various other keywords may be unsupported. If you find a keyword that is unsupported which you need to use, please [ask for support](https://github.com/appium/appium/issues/new) or send a PR!
+- The schema must be of type `object` (`{"type": "object"}`), containing the arguments in a `properties` keyword. Nested properties are unsupported.
+
+Example:
+
+```json
+{
+ "type": "object",
+ "properties": {
+ "test-web-server-port": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 65535,
+ "description": "The port to use for the test web server"
+ },
+ "test-web-server-host": {
+ "type": "string",
+ "description": "The host to use for the test web server",
+ "default": "sillyhost"
+ }
+ }
+}
+```
+
+The above schema defines two properties which can be set via CLI argument or configuration file. If this extension is a _driver_ and its name is "horace", the CLI args would be `--driver-horace-test-web-server-port` and `--driver-horace-test-web-server-host`, respectively. Alternatively, a user could provide a configuration file containing:
+
+```json
+{
+ "server": {
+ "driver": {
+ "horace": {
+ "test-web-server-port": 1234,
+ "test-web-server-host": "localhorse"
+ }
+ }
+ }
+}
+```
+
## Special Notes for Cloud Providers
The rest of this document has applied to Appium generally, but some of the architectural changes in Appium 2.0 will constitute breaking changes for Appium-related service providers, whether a cloud-based Appium host or an internal service. At the end of the day, the maintainer of the Appium server is responsible for installing and making available the various Appium drivers and plugins that end users may wish to use.
@@ -176,7 +276,7 @@ With Appium 2.0, we enter a new era where end users may wish to target various i
In addition to the standard `platformName`, `appium:deviceName`, `appium:automationName`, and `appium:platformVersion`, we recommend adopting the capability `$cloud:appiumOptions`, where the label `$cloud` is not meant to be interpreted literally but instead should be replaced by your vendor prefix (so for HeadSpin it would be `headspin`, Sauce Labs it would be `sauce`, and BrowserStack it would be `browserstack`, to name just a few examples). The `$cloud:appiumOptions` capability would itself be a JSON object, with the following internal keys:
| Capability | Used for | Example |
-|----------|-------|-------|
+| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `version` | Designating which version of the Appium server is used to host and manage drivers. If ommitted, behavior left up to the provider, but the recommendation would be to provide the latest official version. | `2.0.0` |
| `automationVersion` | Designating which version of the specified driver should be used. | `1.55.2` |
| `automation` | Designating a custom driver to use (see below for more info). This would override `appium:automationName` and `$cloud:automationVersion` | `{"name": "org/custom-driver", "source": "github", "package": "custom-driver"}` |
@@ -196,7 +296,7 @@ Appium extensions (drivers and plugins) have a set of properties that specify wh
"$cloud:appiumOptions": {
"appiumVersion": "2.0.0",
"automationVersion": "3.52.0",
- "plugins": ["images"],
+ "plugins": ["images"]
}
}
```
@@ -214,12 +314,12 @@ The previous example still looks a bit disorganized, so of course we also recomm
"platformVersion": "14.4",
"deviceName": "iPhone 11",
"app": "Some-App.app.zip",
- "automationName": "XCUITest",
+ "automationName": "XCUITest"
},
"$cloud:appiumOptions": {
"appiumVersion": "2.0.0",
"automationVersion": "3.52.0",
- "plugins": ["images"],
+ "plugins": ["images"]
}
}
```
@@ -228,10 +328,10 @@ The previous example still looks a bit disorganized, so of course we also recomm
Some service providers may wish to dynamically allow access to all of the features of the Appium 2.0 CLI, including downloading arbitrary drivers and plugins. To represent these extensions, we can define special JSON "extension objects", with the following keys:
-* `name`: the name of the extension. This would be an NPM package name (if downloading from NPM), or a git or GitHub spec (if downloading from a git server or GitHub).
-* `version`: the version of the extension, e.g., the NPM package version or Git SHA.
-* (optional) `source`: a denotation of where the extension can be downloaded from. Recommended to support the following values: `appium`, `npm`, `git`, `github`. Here, `appium` means "Appium's own official list", and should be the default value if this key is not included.
-* (optional) `package`: when downloading extensions from git or github, the NPM package name of the extension must also be provided. This is optional for non-git sources.
+- `name`: the name of the extension. This would be an NPM package name (if downloading from NPM), or a git or GitHub spec (if downloading from a git server or GitHub).
+- `version`: the version of the extension, e.g., the NPM package version or Git SHA.
+- (optional) `source`: a denotation of where the extension can be downloaded from. Recommended to support the following values: `appium`, `npm`, `git`, `github`. Here, `appium` means "Appium's own official list", and should be the default value if this key is not included.
+- (optional) `package`: when downloading extensions from git or github, the NPM package name of the extension must also be provided. This is optional for non-git sources.
Since each session is handled by a single driver, the `$cloud:appiumOptions`/`$automation` capability could be used with an extension object value to denote this driver, for example:

ADD
sample-code/appium.config.sample.js
+module.exports = {
+ server: {
+ address: '127.0.0.1',
+ 'allow-cors': true,
+ 'allow-insecure': ['foo', 'bar'],
+ 'base-path': '/',
+ 'callback-address': '127.0.0.1',
+ 'callback-port': 4723,
+ 'debug-log-spacing': true,
+ 'default-capabilities': {
+ key: 'value',
+ },
+ 'deny-insecure': ['baz', 'quux'],
+ driver: {
+ xcuitest: {
+ key: 'value',
+ },
+ },
+ 'keep-alive-timeout': 600,
+ 'local-timezone': true,
+ log: '/tmp/appium.log',
+ 'log-level': 'info',
+ 'log-no-colors': false,
+ 'log-timestamp': true,
+ 'long-stacktrace': false,
+ 'no-perms-check': false,
+ nodeconfig: {
+ key: 'value',
+ },
+ plugin: {
+ images: {
+ key: 'value',
+ },
+ },
+ port: 4723,
+ 'relaxed-security': false,
+ 'session-override': false,
+ 'strict-caps': true,
+ tmp: '/tmp',
+ 'trace-dir': '/tmp/appium-instruments',
+ 'use-drivers': ['foo', 'bar'],
+ 'use-plugins': ['baz', 'quux'],
+ webhook: 'https://some-url.com',
+ },
+};

docs: update migration guide to reflect changes to configuration files, arguments, etc.

- add a JS example config file