mirror of
https://github.com/appium/appium.git
synced 2026-11-10 11:54:49 +08:00
Compare commits
64
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c1d20517c | ||
|
|
05bcc5e5af | ||
|
|
f2a0365f6f | ||
|
|
fd346480c6 | ||
|
|
e25dd38cd5 | ||
|
|
11d3e89db2 | ||
|
|
cdd8a65887 | ||
|
|
a7d70f3880 | ||
|
|
d972a6a0eb | ||
|
|
b25121336a | ||
|
|
1f2c053573 | ||
|
|
d2f7384e8d | ||
|
|
ad1eb24c65 | ||
|
|
9a4f354a25 | ||
|
|
9c0cb8690f | ||
|
|
51e13d0373 | ||
|
|
3dff11253d | ||
|
|
0df5ee003a | ||
|
|
576e9f88c8 | ||
|
|
a068dcbc7d | ||
|
|
22ca747107 | ||
|
|
06e7f3489d | ||
|
|
070cdfe44f | ||
|
|
1e00b73d87 | ||
|
|
59dd7268bf | ||
|
|
73d0aa5d1c | ||
|
|
a7882e9bab | ||
|
|
fcf7b80f92 | ||
|
|
6fc90a17b2 | ||
|
|
a0c92f5bd1 | ||
|
|
78d85f77e8 | ||
|
|
dfd17074e9 | ||
|
|
4dd95c096e | ||
|
|
0592bc505f | ||
|
|
8471a16e13 | ||
|
|
5f1ba37f4c | ||
|
|
d6736c1311 | ||
|
|
b79ed2bed5 | ||
|
|
50e83da607 | ||
|
|
8dd2bc6ef6 | ||
|
|
9de6f409ec | ||
|
|
d2d8ea7a10 | ||
|
|
5672843744 | ||
|
|
19c30b490b | ||
|
|
59001214da | ||
|
|
00033044e0 | ||
|
|
6903a6d0eb | ||
|
|
179ae7abe5 | ||
|
|
fc8a46499a | ||
|
|
22ec92a24d | ||
|
|
b602693716 | ||
|
|
5b40b87236 | ||
|
|
04dc62e7a5 | ||
|
|
ba5661c427 | ||
|
|
8bfa1b5a4d | ||
|
|
39ebb34408 | ||
|
|
1b56d851fa | ||
|
|
cb950dffb8 | ||
|
|
85dce4a72b | ||
|
|
2e7938578d | ||
|
|
9b07df9959 | ||
|
|
0e98664333 | ||
|
|
80b2da9c44 | ||
|
|
7528fcf890 |
@@ -133,11 +133,6 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/tsconfig/**']
|
||||
|
||||
- label: '@appium/typedoc-plugin-appium'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/typedoc-plugin-appium/**']
|
||||
|
||||
- label: '@appium/types'
|
||||
sync: true
|
||||
matcher:
|
||||
|
||||
@@ -13,4 +13,4 @@ jobs:
|
||||
name: Auto-Label PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: fuxingloh/multi-labeler@6704db0bcba106d07482efabbc79d3092af74fa2 # v2
|
||||
- uses: fuxingloh/multi-labeler@v2
|
||||
|
||||
@@ -51,9 +51,9 @@ jobs:
|
||||
outputs:
|
||||
versions: ${{ steps.generate-matrix.outputs.versions }}
|
||||
steps:
|
||||
- name: Select 3 most recent LTS versions of Node.js
|
||||
- name: Select 2 most recent LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:3] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT"
|
||||
run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:2] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
test:
|
||||
needs:
|
||||
@@ -70,14 +70,14 @@ jobs:
|
||||
# - macos-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci --foreground-scripts
|
||||
@@ -88,9 +88,9 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
|
||||
@@ -9,16 +9,27 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prepare_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
versions: ${{ steps.generate-matrix.outputs.versions }}
|
||||
steps:
|
||||
- name: Select 2 most recent LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:2] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
check:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Check
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x]
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Appium
|
||||
|
||||
@@ -5,7 +5,6 @@ on:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/typedoc.json'
|
||||
- '**/tsconfig*.json'
|
||||
- '**/package*.json'
|
||||
- '**/*mkdocs*.ya?ml'
|
||||
@@ -21,7 +20,6 @@ on:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/typedoc.json'
|
||||
- '**/tsconfig*.json'
|
||||
- '**/package*.json'
|
||||
- '**/*mkdocs*.ya?ml'
|
||||
@@ -39,9 +37,9 @@ jobs:
|
||||
name: Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
|
||||
@@ -11,11 +11,11 @@ jobs:
|
||||
name: Run FOSSA Analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@cb39a46f27f14697fec763d60fb23ad347e2befa # tag=v1
|
||||
uses: bahmutov/npm-install@v1
|
||||
- name: Install fossa-cli
|
||||
run: ./scripts/install-fossa.sh -d
|
||||
- name: Run FOSSA analysis
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for "On Hold" label
|
||||
uses: egmacke/action-check-label@0eb29f801fb482a95c9bd2dd22834ecc8f4e8af9 # v2
|
||||
uses: egmacke/action-check-label@v2
|
||||
with:
|
||||
label: On Hold
|
||||
state: absent
|
||||
|
||||
@@ -17,16 +17,16 @@ jobs:
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
|
||||
@@ -23,8 +23,8 @@ jobs:
|
||||
name: Check Renovate Configs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Validate Renovate Config
|
||||
uses: rinchsan/renovate-config-validator@1ea1e8514f6a33fdd71c40b0a5fa3512b9e7b936 # tag=v0
|
||||
uses: rinchsan/renovate-config-validator@v0.0.12
|
||||
with:
|
||||
pattern: '{.renovaterc.json,renovate/default.json}'
|
||||
|
||||
@@ -60,5 +60,3 @@ appium.zip
|
||||
packages/*/LICENSE
|
||||
local_appium_home
|
||||
*.tgz
|
||||
typedoc-docs
|
||||
packages/appium/docs/*/reference
|
||||
|
||||
Vendored
-16
@@ -44,22 +44,6 @@
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"type": "node"
|
||||
},
|
||||
{
|
||||
"console": "integratedTerminal",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"name": "Typedoc",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/typedoc",
|
||||
"args": ["--logLevel", "Verbose"],
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/lodash/**",
|
||||
"**/node_modules/**/handlebars/**"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"type": "node"
|
||||
}
|
||||
],
|
||||
"version": "0.2.0"
|
||||
|
||||
Vendored
-8
@@ -14,14 +14,6 @@
|
||||
"label": "npm: dev",
|
||||
"detail": "npm run dev",
|
||||
"isBackground": true
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "typedoc",
|
||||
"problemMatcher": [],
|
||||
"label": "npm: typedoc",
|
||||
"detail": "typedoc --logLevel Verbose",
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,10 +26,6 @@ module.exports = (wallaby) => {
|
||||
'./packages/*/package.json',
|
||||
'./packages/*/tsconfig*.json',
|
||||
'./packages/*/test/**/fixture?(s)/**/*',
|
||||
{
|
||||
instrument: false,
|
||||
pattern: './packages/typedoc-plugin-appium/resources/**/*',
|
||||
},
|
||||
{
|
||||
binary: true,
|
||||
pattern: './packages/support/test/unit/assets/sample_binary.plist',
|
||||
@@ -42,10 +38,6 @@ module.exports = (wallaby) => {
|
||||
instrument: false,
|
||||
pattern: './packages/base-driver/static/**/*',
|
||||
},
|
||||
{
|
||||
instrument: false,
|
||||
pattern: './packages/typedoc-plugin-appium/lib/theme/resources/**',
|
||||
},
|
||||
{
|
||||
instrument: false,
|
||||
pattern: './packages/*/test/**/__snapshots__/**/*',
|
||||
|
||||
@@ -16,12 +16,14 @@ See the full list of
|
||||
[officially-supported](https://appium.io/docs/en/latest/ecosystem/#drivers) and
|
||||
[third-party](https://appium.io/docs/en/latest/ecosystem/#other-drivers) drivers for more details.
|
||||
|
||||
:bangbang: The current Appium 2.0 documentation can be found [here](https://appium.io/docs/en/latest/).
|
||||
|
||||
:bangbang: Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. All recent versions of officially supported platform drivers are not compatible to Appium 1.x, and require Appium 2 to run. [Please read the migration guide from 1.x to 2.0](https://appium.io/docs/en/latest/guides/migrating-1-to-2/) to manage the Appium server.
|
||||
|
||||
:bangbang: If you still use the deprecated Appium Desktop containing the built-in server then you won't be able to upgrade to Appium 2. Consider switching to [Appium Inspector](https://github.com/appium/appium-inspector) instead.
|
||||
|
||||
### Documentation
|
||||
|
||||
The current Appium documentation is available at [__https://appium.io__](https://appium.io).
|
||||
|
||||
### Requirements
|
||||
|
||||
- macOS, Linux or Windows operating system
|
||||
@@ -35,16 +37,16 @@ These are only server requirements. Each driver might have its own requirements.
|
||||
To install Appium 2 server using Node Package Manager (npm) run the following command:
|
||||
|
||||
```bash
|
||||
npm i --location=global appium
|
||||
npm i -g appium
|
||||
```
|
||||
|
||||
To update Appium 2 server using Node Package Manager (npm) run the following command:
|
||||
|
||||
```bash
|
||||
npm install --location=global appium@latest
|
||||
npm i -g appium@latest
|
||||
```
|
||||
|
||||
:bangbang: Make sure Appium 1 is fully uninstalled before upgrading it to Appium 2 (`npm uninstall --location=global appium`). Unexpected errors might appear if this has not been done.
|
||||
:bangbang: Make sure Appium 1 is fully uninstalled before upgrading it to Appium 2 (`npm uninstall -g appium`). Unexpected errors might appear if this has not been done.
|
||||
|
||||
### Drivers
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# Roadmap
|
||||
|
||||
This is not a traditional roadmap. We don't have a typical product team with a typical product
|
||||
manager. The fact that the items below exist on a roadmap is no indication that we will ever have
|
||||
the opportunity to work on them. Instead this is more like a wishlist of outcomes that the project
|
||||
thinks would be valuable. If and when we get additional contributions of development work, this is
|
||||
a set of items that would be great for someone to work on! Ideally, interested devs would find
|
||||
something on this list and own it from start to finish! Let anyone on the project know if you're
|
||||
interested and we can help get you going.
|
||||
|
||||
### Core projects
|
||||
- **WebDriver BiDi support in the Appium server**: the WebDriver BiDi spec is underway, which details a different method for communicating with drivers. We should implement handling for these methods in our server so that Appium drivers can take advantage of the BiDi spec without additional work on their part.
|
||||
- **Redevelop automatically generated command docs**: due to changing TypeDoc support and the departure of one of our team, we were forced to remove our TypeDoc-based automatic docs generation tool. It would be nice to bring this back in a more maintainable form!
|
||||
|
||||
### Driver/platform-specific projects
|
||||
- **Better maintenance for our Android drivers**: we're looking for Android specialists to help maintain our Android drivers (UiAutomator2 and Espresso)
|
||||
- **Better maintenance for our iOS driver**: we're looking for iOS specialists to help maintain our XCUITest driver
|
||||
- **Better maintenance for [appium-ios-device](https://github.com/appium/appium-ios-device)**: this project is using outdated approaches and libraries. If it could be improved it would have a big impact on the performance of the XCUITest driver
|
||||
|
||||
### Client library projects
|
||||
- **Selenium compatibility client updates**: we'd like to rearchitect our flagship Appium clients to extend rather than wrap Selenium clients, reducing the overall surface area of the Appium clients and making them work more closely with existing Selenium client functionality.
|
||||
|
||||
### Appium Inspector projects
|
||||
- **Full support for web inspection**: currently the Appium Inspector has poor to no support for inspecing web pages (either mobile browsers or web content embedded in webviews). It's a common requirement to inspect web elements as part of writing Appium tests, and at the present time users are required to leave the Inspector and open up a browser's devtools.
|
||||
- **Record/Playback**: we have a basic record-to-code feature already. It would be nice to be able to save recorded steps and play them back with a little player/editor.
|
||||
- **Support for more platforms**: currently there is a fair bit of specialized handling for iOS and Android in the Appium inspector. Other platforms either work poorly or not at all with the Inspector. It would be great to establish a way for drivers to report all the information about how they work to the Inspector, so it can support any platform without needing special-cased code for it.
|
||||
- **Locator analysis and comparison**: it would be nice for users to get more information about the relative suitability of using different locators to find elements, as poor locator performance is a leading cause of Appium test instability.
|
||||
- **Dark theme**: for true hackers!
|
||||
- **Export/import of saved gestures**: it's currently not possible to port your saved gestures to other instances of the Inspector (i.e., to share with team members).
|
||||
- **Bulk export/import saved sessions**: would be nice to take your sessions and capabilities with you or to share with colleagues.
|
||||
Generated
+4008
-2792
File diff suppressed because it is too large
Load Diff
+19
-24
@@ -63,7 +63,7 @@
|
||||
"sync-pkgs": "run-p sync-pkgs:*",
|
||||
"sync-pkgs:appium-readme": "sync-monorepo-packages --force --no-package-json --packages=packages/appium README.md",
|
||||
"sync-pkgs:common-fields": "sync-monorepo-packages --fields=author,license,bugs,homepage,engines",
|
||||
"sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\" --packages=\"!packages/typedoc-plugin-appium\" --packages=\"!packages/eslint-config-appium-ts\" ",
|
||||
"sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\" --packages=\"!packages/eslint-config-appium-ts\" ",
|
||||
"sync-pkgs:license": "sync-monorepo-packages --force --no-package-json LICENSE",
|
||||
"test": "run-s test:quick",
|
||||
"test:ci": "run-s test:smoke test:unit test:types test:e2e",
|
||||
@@ -73,7 +73,6 @@
|
||||
"test:smoke": "smoker --all test:smoke",
|
||||
"test:types": "lerna run test:types",
|
||||
"test:unit": "lerna run test",
|
||||
"typedoc": "typedoc --logLevel Verbose",
|
||||
"upload": "gulp github-upload",
|
||||
"zip": "zip -qr ./appium.zip ./packages/appium",
|
||||
"zip-and-upload": "run-s zip upload"
|
||||
@@ -90,63 +89,59 @@
|
||||
"@tsconfig/node14": "14.1.0",
|
||||
"@types/chai": "4.3.11",
|
||||
"@types/chai-as-promised": "7.1.8",
|
||||
"@types/diff": "5.0.8",
|
||||
"@types/diff": "5.0.9",
|
||||
"@types/mocha": "10.0.6",
|
||||
"@types/node": "20.10.0",
|
||||
"@types/node": "20.10.5",
|
||||
"@types/semver": "7.5.6",
|
||||
"@types/sinon": "10.0.20",
|
||||
"@types/sinon": "17.0.2",
|
||||
"@types/sinon-chai": "3.2.12",
|
||||
"@types/source-map-support": "0.5.10",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/ws": "8.5.10",
|
||||
"@types/yargs": "17.0.32",
|
||||
"@typescript-eslint/eslint-plugin": "6.12.0",
|
||||
"@typescript-eslint/parser": "6.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "6.14.0",
|
||||
"@typescript-eslint/parser": "6.14.0",
|
||||
"asyncbox": "3.0.0",
|
||||
"chai": "4.3.10",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"chai-webdriverio-async": "2.8.0",
|
||||
"conventional-changelog-conventionalcommits": "7.0.2",
|
||||
"cpy-cli": "5.0.0",
|
||||
"eslint": "8.54.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-find-rules": "4.1.0",
|
||||
"eslint-import-resolver-typescript": "3.6.1",
|
||||
"eslint-plugin-import": "2.29.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-mocha": "10.2.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"fancy-log": "2.0.0",
|
||||
"finalhandler": "1.2.0",
|
||||
"get-port": "5.1.1",
|
||||
"handlebars": "4.7.8",
|
||||
"husky": "8.0.3",
|
||||
"json-schema-to-typescript": "13.1.1",
|
||||
"lerna": "7.4.2",
|
||||
"lint-staged": "15.1.0",
|
||||
"lerna": "8.0.1",
|
||||
"lint-staged": "15.2.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"midnight-smoker": "7.0.4",
|
||||
"midnight-smoker": "8.0.0",
|
||||
"mjpeg-consumer": "2.0.0",
|
||||
"mjpeg-server": "0.3.1",
|
||||
"mocha": "10.2.0",
|
||||
"mocha-chai-jest-snapshot": "1.1.4",
|
||||
"npm-run-all": "4.1.5",
|
||||
"prettier": "3.1.0",
|
||||
"prettier": "3.1.1",
|
||||
"rewiremock": "3.14.5",
|
||||
"rimraf": "5.0.5",
|
||||
"serve-static": "1.15.0",
|
||||
"sinon": "16.1.3",
|
||||
"sinon": "17.0.1",
|
||||
"sinon-chai": "3.7.0",
|
||||
"sync-monorepo-packages": "1.0.2",
|
||||
"through2": "4.0.2",
|
||||
"ts-node": "10.9.1",
|
||||
"tsd": "0.29.0",
|
||||
"typedoc": "0.23.28",
|
||||
"typedoc-plugin-markdown": "3.14.0",
|
||||
"typedoc-plugin-resolve-crossmodule-references": "0.3.3",
|
||||
"typescript": "5.0.4",
|
||||
"ts-node": "10.9.2",
|
||||
"tsd": "0.30.0",
|
||||
"typescript": "5.2.2",
|
||||
"validate.js": "0.13.1",
|
||||
"webdriverio": "8.24.1",
|
||||
"ws": "8.14.2",
|
||||
"webdriverio": "8.26.2",
|
||||
"ws": "8.15.1",
|
||||
"yaml-js": "0.3.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -3,6 +3,34 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.3.0](https://github.com/appium/appium/compare/appium@2.2.3...appium@2.3.0) (2023-12-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Load drivers and plugins asynchronously ([#19512](https://github.com/appium/appium/issues/19512)) ([06e7f34](https://github.com/appium/appium/commit/06e7f3489dff820fa16b16e47417acd0c10e0b05))
|
||||
* **docs:** enhance documentation ([#19528](https://github.com/appium/appium/issues/19528)) ([a7d70f3](https://github.com/appium/appium/commit/a7d70f388020ab7f942ec2b4b94c4a2a61b110b5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Respect the value of no-perms-check server arg ([#19518](https://github.com/appium/appium/issues/19518)) ([22ca747](https://github.com/appium/appium/commit/22ca74710718ddeda0526acd9dd3dd1703001e22))
|
||||
* **appium:** update dependency @sidvind/better-ajv-errors to v2.1.2 ([9b07df9](https://github.com/appium/appium/commit/9b07df99592852cbf1096fc4bd94ffd4395c423d))
|
||||
* **appium:** update dependency @sidvind/better-ajv-errors to v2.1.3 ([78d85f7](https://github.com/appium/appium/commit/78d85f77e8e1e0493a66afc6123f7bc6bc5c8d17))
|
||||
* **appium:** Verify if script path is always under the module root ([#19543](https://github.com/appium/appium/issues/19543)) ([e25dd38](https://github.com/appium/appium/commit/e25dd38cd593d478c07012b4aa14fcd96788d294))
|
||||
* **docutils:** remove `@appium/typedoc-plugin-appium` and all other uses of `typedoc` ([#19465](https://github.com/appium/appium/issues/19465)) ([7528fcf](https://github.com/appium/appium/commit/7528fcf890f79f4017f5e718bb1952bf907ee479))
|
||||
* **docutils:** update dependency mike to v2.0.0 ([#19485](https://github.com/appium/appium/issues/19485)) ([0003304](https://github.com/appium/appium/commit/00033044e08f932b5daf1234cfb381c6f46c8bb8))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.26.0 ([dfd1707](https://github.com/appium/appium/commit/dfd17074e94b2406caa87184ac73d992706e8e4d))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.26.1 ([070cdfe](https://github.com/appium/appium/commit/070cdfe44f3dcd1c5530512b70191719a0047b8c))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.26.2 ([#19537](https://github.com/appium/appium/issues/19537)) ([1f2c053](https://github.com/appium/appium/commit/1f2c053573f0df91449365dfe19dbd350f09ee89))
|
||||
* **support:** update dependency teen_process to v2.0.109 ([85dce4a](https://github.com/appium/appium/commit/85dce4a72b21e017b4661ddf997c096817e5fd7f))
|
||||
* **support:** update dependency teen_process to v2.0.110 ([b602693](https://github.com/appium/appium/commit/b60269371662de4c42ccd7586512c9d685d95d52))
|
||||
* **support:** update dependency teen_process to v2.0.112 ([#19491](https://github.com/appium/appium/issues/19491)) ([d2d8ea7](https://github.com/appium/appium/commit/d2d8ea7a105eb93f59793fbc4d3438a66a191cd8))
|
||||
* **support:** update dependency teen_process to v2.1.1 ([b79ed2b](https://github.com/appium/appium/commit/b79ed2bed5329b904b15fa5b1fbde7885087c9ad))
|
||||
* **types:** update dependency type-fest to v4 ([#19104](https://github.com/appium/appium/issues/19104)) ([8bfa1b5](https://github.com/appium/appium/commit/8bfa1b5a4d090b0102dbb914c9b72aea52d96788))
|
||||
|
||||
|
||||
|
||||
## [2.2.3](https://github.com/appium/appium/compare/appium@2.2.2...appium@2.2.3) (2023-12-04)
|
||||
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@ See the full list of
|
||||
[officially-supported](https://appium.io/docs/en/latest/ecosystem/#drivers) and
|
||||
[third-party](https://appium.io/docs/en/latest/ecosystem/#other-drivers) drivers for more details.
|
||||
|
||||
:bangbang: The current Appium 2.0 documentation can be found [here](https://appium.io/docs/en/latest/).
|
||||
|
||||
:bangbang: Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. All recent versions of officially supported platform drivers are not compatible to Appium 1.x, and require Appium 2 to run. [Please read the migration guide from 1.x to 2.0](https://appium.io/docs/en/latest/guides/migrating-1-to-2/) to manage the Appium server.
|
||||
|
||||
:bangbang: If you still use the deprecated Appium Desktop containing the built-in server then you won't be able to upgrade to Appium 2. Consider switching to [Appium Inspector](https://github.com/appium/appium-inspector) instead.
|
||||
|
||||
### Documentation
|
||||
|
||||
The current Appium documentation is available at [__https://appium.io__](https://appium.io).
|
||||
|
||||
### Requirements
|
||||
|
||||
- macOS, Linux or Windows operating system
|
||||
@@ -35,16 +37,16 @@ These are only server requirements. Each driver might have its own requirements.
|
||||
To install Appium 2 server using Node Package Manager (npm) run the following command:
|
||||
|
||||
```bash
|
||||
npm i --location=global appium
|
||||
npm i -g appium
|
||||
```
|
||||
|
||||
To update Appium 2 server using Node Package Manager (npm) run the following command:
|
||||
|
||||
```bash
|
||||
npm install --location=global appium@latest
|
||||
npm i -g appium@latest
|
||||
```
|
||||
|
||||
:bangbang: Make sure Appium 1 is fully uninstalled before upgrading it to Appium 2 (`npm uninstall --location=global appium`). Unexpected errors might appear if this has not been done.
|
||||
:bangbang: Make sure Appium 1 is fully uninstalled before upgrading it to Appium 2 (`npm uninstall -g appium`). Unexpected errors might appear if this has not been done.
|
||||
|
||||
### Drivers
|
||||
|
||||
|
||||
@@ -2,13 +2,25 @@ INHERIT: ../../docutils/base-mkdocs.yml
|
||||
site_name: Appium Documentation
|
||||
repo_url: https://github.com/appium/appium
|
||||
repo_name: appium/appium
|
||||
copyright: Copyright © 2012 OpenJS Foundation
|
||||
edit_uri: edit/master/packages/appium/docs
|
||||
copyright: Copyright © 2012 OpenJS Foundation - <a href="#__consent">Change cookie settings</a>
|
||||
|
||||
theme:
|
||||
logo: assets/images/appium-logo-white.png
|
||||
favicon: assets/images/appium-logo.png
|
||||
features:
|
||||
- navigation.sections
|
||||
|
||||
plugins:
|
||||
redirects:
|
||||
redirect_maps:
|
||||
'intro/requirements.md': 'quickstart/requirements.md'
|
||||
'ecosystem/build-drivers.md': 'developing/build-drivers.md'
|
||||
'ecosystem/build-plugins.md': 'developing/build-plugins.md'
|
||||
'ecosystem/build-docs.md': 'developing/build-docs.md'
|
||||
'reference/commands/base-driver.md': 'commands/base-driver.md'
|
||||
'reference/commands/execute-driver-plugin.md': 'commands/execute-driver-plugin.md'
|
||||
'reference/commands/images-plugin.md': 'commands/images-plugin.md'
|
||||
'reference/commands/relaxed-caps-plugin.md': 'commands/relaxed-caps-plugin.md'
|
||||
'reference/commands/universal-xml-plugin.md': 'commands/universal-xml-plugin.md'
|
||||
|
||||
extra_css:
|
||||
- assets/stylesheets/extra.css
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
---
|
||||
title: Server CLI Args
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Server Command-Line Arguments
|
||||
---
|
||||
|
||||
To start the Appium server, you may either run `appium` or `appium server`. The `server` subcommand
|
||||
is considered to be the default, so if you omit it, Appium will interpret this as your request to
|
||||
run the Appium server. (You could run different subcommands, like `appium driver` or `appium
|
||||
plugin`: see the [Extensions CLI](./extensions.md) for more info).
|
||||
run the Appium server.
|
||||
|
||||
The invocation of `appium` (or `appium server`) takes a number of arguments, which are detailed
|
||||
The invocation of `appium` (or `appium server`) can take a number of arguments, which are detailed
|
||||
below.
|
||||
|
||||
!!! note
|
||||
@@ -17,39 +19,39 @@ below.
|
||||
a configuration file.
|
||||
|
||||
|
||||
<!-- WARNING: anything between the AUTOGEN-START and AUTOGEN-STOP tags will get replaced by
|
||||
automatic docs generation tooling! Do not edit by hand! -->
|
||||
<!-- AUTOGEN-START -->
|
||||
|Argument |Description|Type|Default|Aliases|
|
||||
|<div style="width:12em">Argument</div>|Description|Type|<div style="width:8em">Default</div>|Aliases|
|
||||
|--|--|--|--|--|
|
||||
|`--address`|IP address to listen on|string|`0.0.0.0`|`-a`|
|
||||
|`--allow-cors`|Whether the Appium server should allow web browser connections from any host|boolean|`false`||
|
||||
|`--allow-insecure`|Set which insecure features are allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Note that features defined via "deny-insecure" will be disabled, even if also listed here. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--allow-insecure`|Set which insecure features are allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Note that features defined via `--deny-insecure` will be disabled, even if also listed here. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--base-path`|Base path to use as the prefix for all webdriver routes running on the server|string|`""`|`-pa`|
|
||||
|`--callback-address`|Callback IP address (default: same as "address")|string||`-ca`|
|
||||
|`--callback-port`|Callback port (default: same as "port") (Value must be between `1` and `65535`)|integer|`4723`|`-cp`|
|
||||
|`--callback-address`|Callback IP address (default: same as `--address`)|string||`-ca`|
|
||||
|`--callback-port`|Callback port (default: same as `--port`) (Value must be between `1` and `65535`)|integer|`4723`|`-cp`|
|
||||
|`--debug-log-spacing`|Add exaggerated spacing in logs to help with visual inspection|boolean|`false`||
|
||||
|`--default-capabilities`|Set the default desired capabilities, which will be set on each session unless overridden by received capabilities. If a string, a path to a JSON file containing the capabilities, or raw JSON.|object||`-dc`|
|
||||
|`--deny-insecure`|Set which insecure features are not allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Features listed here will not be enabled even if also listed in "allow-insecure", and even if "relaxed-security" is enabled. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--deny-insecure`|Set which insecure features are not allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Features listed here will not be enabled even if also listed in `--allow-insecure`, and even if `--relaxed-security` is enabled. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--driver`|Driver-specific configuration. Keys should correspond to driver package names|object|||
|
||||
|`--keep-alive-timeout`|Number of seconds the Appium server should apply as both the keep-alive timeout and the connection timeout for all requests. A value of 0 disables the timeout.|integer|`600`|`-ka`|
|
||||
|`--keep-alive-timeout`|Number of seconds the Appium server should apply as both the keep-alive timeout and the connection timeout for all requests. Setting this to `0` disables the timeout.|integer|`600`|`-ka`|
|
||||
|`--local-timezone`|Use local timezone for timestamps|boolean|`false`||
|
||||
|`--log`|Also send log output to this file|string||`-g`|
|
||||
|`--log-filters`|One or more log filtering rules|array|||
|
||||
|`--log-level`|Log level (console[:file]) (Value must be one of: `info`, `info:debug`, `info:info`, `info:warn`, `info:error`, `warn`, `warn:debug`, `warn:info`, `warn:warn`, `warn:error`, `error`, `error:debug`, `error:info`, `error:warn`, `error:error`, `debug`, `debug:debug`, `debug:info`, `debug:warn`, `debug:error`)|string|`debug`||
|
||||
|`--log-no-colors`|Do not use color in console output|boolean|`false`||
|
||||
|`--log-timestamp`|Show timestamps in console output|boolean|`false`||
|
||||
|`--plugins-import-chunk-size`|The maximum amount of plugins that could be imported in parallel on server startup|number|`7`||
|
||||
|`--drivers-import-chunk-size`|The maximum amount of drivers that could be imported in parallel on server startup|number|`3`||
|
||||
|`--long-stacktrace`|Add long stack traces to log entries. Recommended for debugging only.|boolean|`false`||
|
||||
|`--no-perms-check`|Do not check that needed files are readable and/or writable|boolean|`false`||
|
||||
|`--no-perms-check`|Skip various permission checks on the server startup if set to true|boolean|`false`||
|
||||
|`--nodeconfig`|Path to configuration JSON file to register Appium as a node with Selenium Grid 3; otherwise the configuration itself|object|||
|
||||
|`--plugin`|Plugin-specific configuration. Keys should correspond to plugin package names|object|||
|
||||
|`--port`|Port to listen on (Value must be between `1` and `65535`)|integer|`4723`|`-p`|
|
||||
|`--relaxed-security`|Disable additional security checks, so it is possible to use some advanced features, provided by drivers supporting this option. Only enable it if all the clients are in the trusted network and it's not the case if a client could potentially break out of the session sandbox. Specific features can be overridden by using "deny-insecure"|boolean|`false`||
|
||||
|`--relaxed-security`|Disable additional security checks, so it is possible to use some advanced features, provided by drivers supporting this option. Only enable it if all the clients are in the trusted network and it's not the case if a client could potentially break out of the session sandbox. Specific features can be overridden by using `--deny-insecure`|boolean|`false`||
|
||||
|`--session-override`|Enables session override (clobbering)|boolean|`false`||
|
||||
|`--ssl-cert-path`|Absolute path to the `.cert` file if TLS is used. Must be provided together with `--ssl-key-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|
||||
|`--ssl-key-path`|Absolute path to the `.key` file if TLS is used. Must be provided together with `--ssl-cert-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|
||||
|`--strict-caps`|Cause sessions to fail if desired caps are sent in that Appium does not recognize as valid for the selected device|boolean|`false`||
|
||||
|`--tmp`|Absolute path to directory Appium can use to manage temp files. Defaults to C:\Windows\Temp on Windows and /tmp otherwise.|string|||
|
||||
|`--trace-dir`|Absolute path to directory Appium can use to save iOS instrument traces; defaults to <tmp>/appium-instruments|string|||
|
||||
|`--tmp`|Absolute path to directory Appium can use to manage temp files|string|Windows: `C:\Windows\Temp`<br>Others: `/tmp`||
|
||||
|`--trace-dir`|Absolute path to directory Appium can use to save iOS instrument traces|string|`<tmp>/appium-instruments`||
|
||||
|`--use-drivers`|A list of drivers to activate. By default, all installed drivers will be activated.|array<string>|`[]`||
|
||||
|`--use-plugins`|A list of plugins to activate. To activate all plugins, the value should be an array with a single item "all".|array<string>|`[]`||
|
||||
|`--use-plugins`|A list of plugins to activate. To activate all plugins, the value should be an array with a single item `"all"`.|array<string>|`[]`||
|
||||
|`--webhook`|Also send log output to this http listener|string||`-G`|
|
||||
<!-- AUTOGEN-STOP -->
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Server Environment Variables
|
||||
---
|
||||
|
||||
The primary way of configuring the Appium server is via [CLI Args](./args.md). However, some more
|
||||
The primary way of configuring the Appium server is via [Command-Line Arguments](./args.md). However, some more
|
||||
advanced features are toggled or configured via environment variables. To set environment
|
||||
variables, refer to the documentation for your operating system and terminal. These are the
|
||||
environment variables that the Appium server understands:
|
||||
@@ -14,5 +17,5 @@ environment variables that the Appium server understands:
|
||||
|`APPIUM_PREFER_SYSTEM_UNZIP`|Set to `0` or `false` to request that Appium not use the `unzip` binary included on your system for unzipping downloaded apps or other artifacts. Instead it will use a JS-based unzip library. This could help on some systems with non-existent or non-standard `unzip` commands. Note that if unzipping fails using the system library, the fallback library will be attempted in any case, so setting this env var merely saves time in the event you know the system unzip will fail.|
|
||||
|`APPIUM_HOST`|Same as the `--address` CLI arg|
|
||||
|`APPIUM_PORT`|Same as the `--port` CLI arg|
|
||||
|`APPIUM_RELOAD_EXTENSIONS`|Set to `1` to cause Appium to re-require extensions when new sessions are created. This is mostly useful for [building extensions](../ecosystem/build-drivers.md)|
|
||||
|`APPIUM_RELOAD_EXTENSIONS`|Set to `1` to cause Appium to re-require extensions when new sessions are created. This is mostly useful for [building extensions](../developing/build-drivers.md)|
|
||||
|`APPIUM_OMIT_PEER_DEPS`|Adds `--omit=peer` to all the NPM commands run internally by Appium. Mostly an internal feature.|
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
---
|
||||
title: The Extension CLI
|
||||
title: Extension Command-Line Usage
|
||||
---
|
||||
|
||||
Appium allows for the flexible installation and management of _drivers_ (which provide Appium with
|
||||
the capability to automate a given platform) and *plugins* (which can augment or alter the way
|
||||
individual Appium commands work). For a conceptual understanding of these entities, please review
|
||||
the [Introduction](../intro/index.md). Management of drivers and plugins is handled by Appium's
|
||||
Extension CLI.
|
||||
Appium allows for the flexible installation and management of various _extensions_, such as _drivers_
|
||||
(which provide Appium with the capability to automate a given platform) and _plugins_ (which can
|
||||
augment or alter the way individual Appium commands work). For a conceptual understanding of these
|
||||
entities, please review the [Introduction](../intro/index.md).
|
||||
|
||||
Management of drivers and plugins is handled by Appium's Extension CLI (command-line interface).
|
||||
|
||||
!!! note
|
||||
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
---
|
||||
title: CLI Intro
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Command-Line Overview
|
||||
---
|
||||
|
||||
When you install Appium globally via `npm`, an executable shell script named `appium` is placed in
|
||||
your global Node `bin` folder, often also symlinked to places like `/usr/local/bin`. If your `PATH`
|
||||
is set up to look for programs in appropriate directory, then you will be able to run `appium` from
|
||||
the command line of your terminal, like any other executable. The `appium` program has three main
|
||||
subcommands, each of which has its own set of documentation:
|
||||
Appium provides a command-line executable (`appium`), which will likely be your main way of interacting with
|
||||
the Appium server. This section of the Appium documentation describes how to use this executable.
|
||||
|
||||
1. The [`server`](./args.md) subcommand starts an Appium server listening for new session requests,
|
||||
and takes a variety of parameters related to the operation of the server and also those consumed
|
||||
by active drivers or plugins.
|
||||
2. The [Extension](./extensions) (`driver` and `plugin`) subcommands assist in managing Appium
|
||||
drivers and plugins.
|
||||
To start off, you can run `appium -v` or `appium --version` to return the installed version,
|
||||
or run `appium -h` or `appium --help` to return the help message.
|
||||
|
||||
The main `appium` executable provides 3 subcommands:
|
||||
|
||||
1. `appium server` (or simply `appium`) - launch an Appium server
|
||||
- [See here for accepted arguments](./args.md)
|
||||
- For advanced features, [see here for accepted environment variables](./env-vars.md)
|
||||
2. `appium driver` - manage Appium drivers
|
||||
- [See here for accepted arguments](./extensions.md)
|
||||
3. `appium plugin` - manage Appium plugins
|
||||
- [See here for accepted arguments](./extensions.md)
|
||||
|
||||
Like the main command, you can also run each subcommand with the `-h` or `--help` flag to learn more about it.
|
||||
|
||||
@@ -0,0 +1,517 @@
|
||||
# Driver: base-driver
|
||||
|
||||
### `createSession`
|
||||
|
||||
`POST` **`/session`**
|
||||
|
||||
Historically the first two arguments were reserved for JSONWP capabilities.
|
||||
Appium 2 has dropped the support of these, so now we only accept capability
|
||||
objects in W3C format and thus allow any of the three arguments to represent
|
||||
the latter.
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `desiredCapabilities?` | `W3CDriverCaps`<`C`\> | the new session capabilities |
|
||||
| `requiredCapabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `capabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
|
||||
|
||||
#### Response
|
||||
|
||||
`CreateResult`
|
||||
|
||||
The capabilities object representing the created session
|
||||
|
||||
### `deleteSession`
|
||||
|
||||
`DELETE` **`/session/:sessionId`**
|
||||
|
||||
Returns capabilities for the session and event history (if applicable)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`SingularSessionData`<`C`, `SessionData`\>
|
||||
|
||||
A session data object
|
||||
|
||||
### `getSession`
|
||||
|
||||
`GET` **`/session/:sessionId`**
|
||||
|
||||
Returns capabilities for the session and event history (if applicable)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Response
|
||||
|
||||
`SingularSessionData`<`C`, `SessionData`\>
|
||||
|
||||
A session data object
|
||||
|
||||
### `findElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific element |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
|
||||
### `findElementFromElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element/:elementId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found. Only
|
||||
look for elements among the set of descendants of a given element
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-element](https://w3c.github.io/webdriver/#find-element-from-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific element |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
|
||||
### `findElementFromShadowRoot`
|
||||
|
||||
`POST` **`/session/:sessionId/shadow/:shadowId/element`**
|
||||
|
||||
Find an element from a shadow root
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element inside the shadow root matching the selector
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly-empty list of element objects
|
||||
|
||||
### `findElementsFromElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element/:elementId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector. Only
|
||||
look for elements among the set of descendants of a given element
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements-from-element](https://w3c.github.io/webdriver/#find-elements-from-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly-empty list of element objects
|
||||
|
||||
### `findElementsFromShadowRoot`
|
||||
|
||||
`POST` **`/session/:sessionId/shadow/:shadowId/elements`**
|
||||
|
||||
Find elements from a shadow root
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
|
||||
#### Response
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly empty list of elements inside the shadow root matching the selector
|
||||
|
||||
### `getLog`
|
||||
|
||||
`POST` **`/session/:sessionId/log`**
|
||||
|
||||
Get the log for a given log type.
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
### `getLog`
|
||||
|
||||
`POST` **`/session/:sessionId/se/log`**
|
||||
|
||||
Get the log for a given log type.
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
### `getLogEvents`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/events`**
|
||||
|
||||
Get a list of events that have occurred in the current session
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `type?` | `string` \| `string`[] | filter the returned events by including one or more types |
|
||||
|
||||
#### Response
|
||||
|
||||
`EventHistory` \| `Record`<`string`, `number`\>
|
||||
|
||||
The event history for the session
|
||||
|
||||
### `getLogTypes`
|
||||
|
||||
`GET` **`/session/:sessionId/log/types`**
|
||||
|
||||
Get available log types as a list of strings
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`string`[]
|
||||
|
||||
### `getLogTypes`
|
||||
|
||||
`GET` **`/session/:sessionId/se/log/types`**
|
||||
|
||||
Get available log types as a list of strings
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`string`[]
|
||||
|
||||
### `getPageSource`
|
||||
|
||||
`GET` **`/session/:sessionId/source`**
|
||||
|
||||
Get the current page/app source as HTML/XML
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`string`
|
||||
|
||||
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
|
||||
|
||||
### `getSessions`
|
||||
|
||||
`GET` **`/sessions`**
|
||||
|
||||
Get data for all sessions running on an Appium server
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`MultiSessionData`<`C`\>[]
|
||||
|
||||
A list of session data objects
|
||||
|
||||
### `getSettings`
|
||||
|
||||
`GET` **`/session/:sessionId/appium/settings`**
|
||||
|
||||
Update the session's settings dictionary with a new settings object
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `updateSettings`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/settings`**
|
||||
|
||||
Update the session's settings dictionary with a new settings object
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `settings` | `Settings` | A key-value map of setting names to values. Settings not named in the map will not have their value adjusted. |
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `getStatus`
|
||||
|
||||
`GET` **`/status`**
|
||||
|
||||
**`Summary`**
|
||||
|
||||
Retrieve the server's current status.
|
||||
|
||||
**`Description`**
|
||||
|
||||
Returns information about whether a remote end is in a state in which it can create new sessions and can additionally include arbitrary meta information that is specific to the implementation.
|
||||
|
||||
The readiness state is represented by the ready property of the body, which is false if an attempt to create a session at the current time would fail. However, the value true does not guarantee that a New Session command will succeed.
|
||||
|
||||
Implementations may optionally include additional meta information as part of the body, but the top-level properties ready and message are reserved and must not be overwritten.
|
||||
|
||||
<!-- comment source: builtin-interface -->
|
||||
|
||||
#### Examples
|
||||
|
||||
<!-- BEGIN:EXAMPLES -->
|
||||
##### JavaScript
|
||||
<!-- BEGIN:EXAMPLE lang=JavaScript -->
|
||||
|
||||
```js
|
||||
// webdriver.io example
|
||||
await driver.status();
|
||||
```
|
||||
|
||||
<!-- END:EXAMPLE -->
|
||||
##### Python
|
||||
<!-- BEGIN:EXAMPLE lang=Python -->
|
||||
|
||||
```python
|
||||
driver.get_status()
|
||||
```
|
||||
|
||||
<!-- END:EXAMPLE -->
|
||||
##### Java
|
||||
<!-- BEGIN:EXAMPLE lang=Java -->
|
||||
|
||||
```java
|
||||
driver.getStatus();
|
||||
```
|
||||
|
||||
<!-- END:EXAMPLE -->
|
||||
##### Ruby
|
||||
<!-- BEGIN:EXAMPLE lang=Ruby -->
|
||||
|
||||
```ruby
|
||||
# ruby_lib example
|
||||
remote_status
|
||||
|
||||
# ruby_lib_core example
|
||||
@driver.remote_status
|
||||
```
|
||||
|
||||
<!-- END:EXAMPLE -->
|
||||
<!-- END:EXAMPLES -->
|
||||
|
||||
#### Response
|
||||
|
||||
`Object`
|
||||
|
||||
### `getTimeouts`
|
||||
|
||||
`GET` **`/session/:sessionId/timeouts`**
|
||||
|
||||
Set the various timeouts associated with a session
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `timeouts`
|
||||
|
||||
`POST` **`/session/:sessionId/timeouts`**
|
||||
|
||||
Set the various timeouts associated with a session
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `type?` | `string` | used only for the old (JSONWP) command, the type of the timeout |
|
||||
| `ms?` | `string` \| `number` | used only for the old (JSONWP) command, the ms for the timeout |
|
||||
| `script?` | `number` | the number in ms for the script timeout, used for the W3C command |
|
||||
| `pageLoad?` | `number` | the number in ms for the pageLoad timeout, used for the W3C command |
|
||||
| `implicit?` | `string` \| `number` | the number in ms for the implicit wait timeout, used for the W3C command |
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `implicitWait`
|
||||
|
||||
`POST` **`/session/:sessionId/timeouts/implicit_wait`**
|
||||
|
||||
Set the implicit wait timeout
|
||||
|
||||
**`Deprecated`**
|
||||
|
||||
Use `timeouts` instead
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `ms` | `string` \| `number` | the timeout in ms |
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `logCustomEvent`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/log_event`**
|
||||
|
||||
Add a custom-named event to the Appium event log
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `vendor` | `string` | the name of the vendor or tool the event belongs to, to namespace the event |
|
||||
| `event` | `string` | the name of the event itself |
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
|
||||
### `reset`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/app/reset`**
|
||||
|
||||
Reset the current session (run the delete session and create session subroutines)
|
||||
|
||||
**`Deprecated`**
|
||||
|
||||
Use explicit session management commands instead
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
``null``
|
||||
@@ -0,0 +1,22 @@
|
||||
# Plugin: execute-driver
|
||||
|
||||
### `executeDriverScript`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/execute_driver`**
|
||||
|
||||
Implementation of a command within a plugin
|
||||
|
||||
At minimum, `D` must be `ExternalDriver`, but a plugin can be more narrow about which drivers it supports.
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type |
|
||||
| :------ | :------ |
|
||||
| `script` | [script: string, scriptType: string, timeoutMs: number] |
|
||||
| `type?` | [script: string, scriptType: string, timeoutMs: number] |
|
||||
|
||||
#### Response
|
||||
|
||||
`unknown`
|
||||
@@ -0,0 +1,67 @@
|
||||
# Plugin: images
|
||||
|
||||
### `compareImages`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/compare_images`**
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type |
|
||||
| :------ | :------ |
|
||||
| `mode` | `any`[] |
|
||||
| `options?` | `any`[] |
|
||||
|
||||
#### Response
|
||||
|
||||
`ComparisonResult`
|
||||
|
||||
### `findElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any` | the locator strategy |
|
||||
| `value` | `any` | the selector to combine with the strategy to find the specific element |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any` | the locator strategy |
|
||||
| `value` | `any` | the selector to combine with the strategy to find the specific elements |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
A possibly-empty list of element objects
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Intro to Commands
|
||||
---
|
||||
|
||||
Here you can find various commands exposed by the main Appium module through its base driver, as
|
||||
well as the commands available in several plugins.
|
||||
|
||||
!!! note
|
||||
|
||||
The Appium base driver only exposes a few commands, as it is not meant to be used on its own.
|
||||
Please refer to the documentation of your [Appium driver](../ecosystem/drivers.md) to learn
|
||||
about the commands it exposes, and then check your [Appium client](../ecosystem/clients.md)
|
||||
documentation for the exact syntax of that command.
|
||||
|
||||
The command listings can be found here:
|
||||
|
||||
* [Base Driver](./base-driver.md)
|
||||
* [Execute Driver Plugin](./execute-driver-plugin.md)
|
||||
* [Images Plugin](./images-plugin.md)
|
||||
* [Relaxed Caps Plugin](./relaxed-caps-plugin.md)
|
||||
* [Universal XML Plugin](./universal-xml-plugin.md)
|
||||
@@ -0,0 +1,27 @@
|
||||
# Plugin: relaxed-caps
|
||||
|
||||
### `createSession`
|
||||
|
||||
`POST` **`/session`**
|
||||
|
||||
Start a new automation session
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `desiredCapabilities?` | `any` | the new session capabilities |
|
||||
| `requiredCapabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `capabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
The capabilities object representing the created session
|
||||
@@ -0,0 +1,68 @@
|
||||
# Plugin: universal-xml
|
||||
|
||||
### `findElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any`[] | the locator strategy |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any`[] | the locator strategy |
|
||||
|
||||
#### Response
|
||||
|
||||
`any`
|
||||
|
||||
A possibly-empty list of element objects
|
||||
|
||||
### `getPageSource`
|
||||
|
||||
`GET` **`/session/:sessionId/source`**
|
||||
|
||||
Get the current page/app source as HTML/XML
|
||||
|
||||
**`See`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
|
||||
`string`
|
||||
|
||||
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
|
||||
@@ -323,7 +323,7 @@ One of the design goals of this system is the following:
|
||||
_An extension should be able to register custom CLI arguments with the Appium, and a user should be
|
||||
able to use them like any other argument_.
|
||||
|
||||
Previously, Appium 2.0 accepted arguments in this manner (via `--driverArgs`), but validation was
|
||||
Previously, Appium 2 accepted arguments in this manner (via `--driverArgs`), but validation was
|
||||
hand-rolled and required extension implementors to use a custom API. It also required the user to
|
||||
awkwardly pass a JSON string as the configuration on the command-line. Further, no contextual help
|
||||
(via `--help`) existed for these arguments.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Contributing Code
|
||||
---
|
||||
|
||||
To contribute to the Appium code base make sure to check out the Git repository.
|
||||
|
||||
!!! info
|
||||
|
||||
If you are VS Code user you can easily check out the project using [Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md).
|
||||
|
||||
It is advised to [fork](https://github.com/appium/appium/fork) before cloning it to your system.
|
||||
|
||||
```sh
|
||||
export GITHUB_USERNAME=<your-username>
|
||||
git clone git@github.com:$GITHUB_USERNAME/appium.git
|
||||
```
|
||||
|
||||
After cloning you can go ahead and install the project dependencies:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
From here on there are several things you can do.
|
||||
|
||||
### Watch Files
|
||||
|
||||
When developing Appium code we have to watch all JavaScript and TypeScript files to re-compile them after every change. You can run this watch process via:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Start Appium in Dev-Mode
|
||||
|
||||
To test your changes you can run Appium in dev mode via:
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
The project maintains a set of different test variations you can run to verify the quality of the code.
|
||||
|
||||
#### Linting
|
||||
|
||||
Appium uses [`eslint`](https://eslint.org/) for static code analysis and linting. You can run these checks via:
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
#### Unit
|
||||
|
||||
```sh
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
You can also run tests for specific workspaces, e.g.:
|
||||
|
||||
```sh
|
||||
export APPIUM_WORKSPACE=@appium/doctor
|
||||
npm run test:unit -w $APPIUM_WORKSPACE
|
||||
```
|
||||
|
||||
#### Smoke and E2E
|
||||
|
||||
```sh
|
||||
npm run test:slow
|
||||
```
|
||||
|
||||
### Deploy Docs Locally
|
||||
|
||||
Our documentation system uses [MKDocs](https://www.mkdocs.org/) and therefore requires [Python](https://www.python.org/) to be installed on your system. You can run the docs by:
|
||||
|
||||
```sh
|
||||
# installing needed Python dependencies
|
||||
pip install -r packages/docutils/requirements.txt
|
||||
# build the project
|
||||
npm run build
|
||||
# run dev server
|
||||
npm run dev:docs
|
||||
```
|
||||
|
||||
You should be able to view the page at `http://127.0.0.1:8000/docs/en`:
|
||||
|
||||
```sh
|
||||
open http://127.0.0.1:8000/docs/en
|
||||
```
|
||||
@@ -1,8 +1,18 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Contributing to Appium
|
||||
cwd: ../../../../../
|
||||
---
|
||||
|
||||
Appium is open source, available under an Apache 2.0 license. Appium's copyright is held by the
|
||||
[OpenJS Foundation](https://openjsf.org), and Appium receives contributions from many companies
|
||||
across several software industries, regardless of their competitive status. (3rd-party drivers and
|
||||
plugins are available under the licenses provided by their authors.)
|
||||
|
||||
As such, we welcome contributions! The project moves forward in relation to the investment of
|
||||
contributions of code, documentation, maintenance, and support from companies and volunteers.
|
||||
|
||||
This section of Appium's documentation is for those who are interested in contributing to Appium's
|
||||
development. It contains developer overviews, guides, and notes. Use the navigation menu to find
|
||||
a specific topic. All the information in these guides assumes in-depth familiarity with Appium
|
||||
@@ -19,103 +29,10 @@ already.
|
||||
|
||||
The project offers a variety of ways to contribute, e.g.:
|
||||
|
||||
- contributing code
|
||||
- [contributing code](./develop.md)
|
||||
- improving documentation
|
||||
- creating educational content (blog posts, tutorials, videos, etc.)
|
||||
- spreading the good word about the project (e.g. via Twitter)
|
||||
- filing bugs if you discover them while using Appium
|
||||
- making feature requests if you are missing something in the project or help triaging bugs
|
||||
- supporting users in the [Appium forum](https://discuss.appium.io/)
|
||||
|
||||
## The Appium Development Process
|
||||
|
||||
To contribute to the Appium code base make sure to check out the Git repository.
|
||||
|
||||
!!! info
|
||||
|
||||
If you are VS Code user you can easily check out the project using [Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md).
|
||||
|
||||
It is advised to [fork](https://github.com/appium/appium/fork) before cloning it to your system.
|
||||
|
||||
```sh { name=clone }
|
||||
export GITHUB_USERNAME=<your-username>
|
||||
git clone git@github.com:$GITHUB_USERNAME/appium.git
|
||||
```
|
||||
|
||||
After cloning you can go ahead and install the project dependencies:
|
||||
|
||||
```sh { name=install }
|
||||
npm install
|
||||
```
|
||||
|
||||
From here on there are several things you can do.
|
||||
|
||||
### Watch Files
|
||||
|
||||
When developing Appium code we have to watch all JavaScript and TypeScript files to re-compile them after every change. You can run this watch process via:
|
||||
|
||||
```sh { name=watch, background=true }
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Start Appium in Dev-Mode
|
||||
|
||||
To test your changes you can run Appium in dev mode via:
|
||||
|
||||
```sh { name=start }
|
||||
npm start
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
The project maintains a set of different test variations you can run to verify the quality of the code.
|
||||
|
||||
#### Linting
|
||||
|
||||
Appium uses EsLint for static code analysis and linting. You can run these checks via:
|
||||
|
||||
```sh { name=test-linting }
|
||||
npm run lint
|
||||
```
|
||||
|
||||
#### Unit
|
||||
|
||||
Run via:
|
||||
|
||||
```sh { name=test-unit }
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
You can also run tests for specific workspaces, e.g.:
|
||||
|
||||
```sh { name=test-workspace }
|
||||
export APPIUM_WORKSPACE=@appium/doctor
|
||||
npm run test:unit -w $APPIUM_WORKSPACE
|
||||
```
|
||||
|
||||
#### Smoke and e2e Tests
|
||||
|
||||
Run via:
|
||||
|
||||
```sh { name=test-slow }
|
||||
npm run test:slow
|
||||
```
|
||||
|
||||
### Deploy Docs Locally
|
||||
|
||||
Our documentation system uses [MKDocs](https://www.mkdocs.org/) and therefor requires [Python](https://www.python.org/) to be installed on your system. You can run the docs by:
|
||||
|
||||
```sh
|
||||
# installing needed Python dependencies
|
||||
pip install -r packages/docutils/requirements.txt
|
||||
# build the project
|
||||
npm run build
|
||||
# run dev server
|
||||
npm run dev:docs
|
||||
```
|
||||
|
||||
You should be able to view the page at `http://127.0.0.1:8000/docs/en`:
|
||||
|
||||
```sh
|
||||
open http://127.0.0.1:8000/docs/en
|
||||
```
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: Building Documentation
|
||||
---
|
||||
|
||||
Once you've [built a driver](./build-drivers.md) or [built a plugin](./build-plugins.md) for Appium,
|
||||
you will hopefully want to document how that extension works for your users. The most basic way of
|
||||
doing this is to write up a quick `README.md` and keep it in the root of your project's repository.
|
||||
However, this can involve a lot of effort.
|
||||
|
||||
The Appium project has built tools to help with this, and we've packaged up these tools so our
|
||||
ecosystem developers building drivers and plugins can _also_ use them. The best way to get going
|
||||
with these tools is probably to look at an existing Appium driver repo to see how it's done, for
|
||||
example the [XCUITest driver repo](https://github.com/appium/appium-xcuitest-driver). But this guide
|
||||
will outline the basic approach.
|
||||
|
||||
### Conceptual architecture
|
||||
|
||||
Appium settled on [MkDocs](https://www.mkdocs.org/) as a Markdown-based documentation site
|
||||
generator. It uses a Python toolchain (and not Node.js), but it turned out to be the best option
|
||||
for our purposes. You can adjust this, but by default Appium's utilities also assume that you'll be
|
||||
using the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/) theme/extension for
|
||||
MkDocs.
|
||||
|
||||
In order to make different versions of your docs available (one for each minor release of your
|
||||
extension, typically), we also bundle [Mike](https://github.com/jimporter/mike).
|
||||
|
||||
From here, building a basic docs site is as easy as collecting your Markdown files together and
|
||||
defining how you want them to be organized.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To take advantage of Appium's documentation utilities, you'll need to install:
|
||||
|
||||
- [Python v3+](https://www.python.org/downloads/)
|
||||
- [pip](https://pip.pypa.io/en/stable/installation/) (this may be installed automatically with Python)
|
||||
- The `@appium/docutils` package:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @appium/docutils
|
||||
```
|
||||
|
||||
### Initializing an Extension for Building Docs
|
||||
|
||||
To prepare your extension for generating documentation, run the following command:
|
||||
|
||||
```bash
|
||||
npx appium-docs init
|
||||
```
|
||||
|
||||
This will:
|
||||
|
||||
1. Create a `tsconfig.json` if one does not already exist. This is necessary even if your extension
|
||||
is not written in TypeScript.
|
||||
2. Create a `mkdocs.yml` with the necessary configuration for MkDocs.
|
||||
|
||||
### Documenting Your Extension
|
||||
|
||||
At this point, you can begin documenting your extension. By default, MkDocs will look for Markdown
|
||||
files in the `docs` directory. You can therefore create your Markdown documentation files, place
|
||||
them in `docs`, and add links to these files in `mkdocs.yml`.
|
||||
|
||||
Refer to the [MkDocs documentation](https://www.mkdocs.org/user-guide/writing-your-docs/) for
|
||||
information on how to organize and structure your documentation.
|
||||
|
||||
### Building the Docs
|
||||
|
||||
At this point, you can use the `appium-docs` CLI tool. Run this tool with no arguments to get the
|
||||
full help output and see all the available subcommands and parameters. Here are a few usage
|
||||
examples:
|
||||
|
||||
```bash
|
||||
# Generate reference and build the mkdocs site into the site dir
|
||||
npx appium-docs build
|
||||
|
||||
# Same as build, but host the docs on a local dev server
|
||||
# and watch for changes and rebuild when files change
|
||||
npx appium-docs build --serve
|
||||
|
||||
# Build the docs and deploy them with mike versioning to the docs-site branch
|
||||
# using the included commit message.
|
||||
# This is particularly useful for pushing content to a GitHub pages branch!
|
||||
npx appium-docs build \
|
||||
--deploy \
|
||||
-b docs-site \
|
||||
-m 'docs: auto-build docs for appium-xcuitest-driver@%s'
|
||||
```
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Building Appium Drivers
|
||||
title: Building Drivers
|
||||
---
|
||||
|
||||
Appium wants to make it easy for anyone to develop their own automation drivers as part of the
|
||||
@@ -32,7 +32,7 @@ coding it up and making it available as an Appium driver should be the easy part
|
||||
|
||||
One of the greatest things about building an Appium driver is that there are already a number of
|
||||
open source Appium drivers which you can look at for reference. There is
|
||||
a [fake-driver](https://github.com/appium/appium/tree/2.0/packages/fake-driver) sample driver which
|
||||
a [fake-driver](https://github.com/appium/appium/tree/master/packages/fake-driver) sample driver which
|
||||
does basically nothing other than showcase some of the things described in this guide.
|
||||
|
||||
And of course, all of Appium's official drivers are open source and available in repositories at
|
||||
@@ -52,7 +52,7 @@ All Appium drivers are fundamentally Node.js packages, and therefore must have a
|
||||
|
||||
Your `package.json` must include `appium` as a `peerDependency`. The requirements for the
|
||||
dependency versions should be as loose as possible (unless you happen to know your driver will only
|
||||
work with certain versions of Appium). For Appium 2.0, for example, this would look something like
|
||||
work with certain versions of Appium). For Appium 2, for example, this would look something like
|
||||
`^2.0.0`, declaring that your driver works with any version of Appium that starts with 2.x.
|
||||
|
||||
Your `package.json` must contain an `appium` field, like this (we call this the 'Appium extension
|
||||
@@ -276,7 +276,7 @@ You handle WebDriver commands by implementing functions in your driver class. Ea
|
||||
WebDriver Protocol, plus the various Appium extensions, has a corresponding function that you
|
||||
implement if you want to support that command in your driver. The best way to see which commands
|
||||
Appium supports and which method you need to implement for each command is to look at Appium's
|
||||
[routes.js](https://github.com/appium/appium/blob/2.0/packages/base-driver/lib/protocol/routes.js).
|
||||
[routes.js](https://github.com/appium/appium/blob/master/packages/base-driver/lib/protocol/routes.js).
|
||||
Each route object in this file tells you the command name as well as the parameters you'd expect to
|
||||
receive for that command.
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: Building Appium Plugins
|
||||
title: Building Plugins
|
||||
---
|
||||
|
||||
This is a high-level guide for developing Appium plugins, which is not something most Appium users
|
||||
need to know or care about. If you are not familiar with Appium plugins yet from a user
|
||||
perspective, check out the [list of plugins](./index.md#plugins) to play around with some and get
|
||||
perspective, check out the [list of plugins](../ecosystem/plugins.md) to play around with some and get
|
||||
an idea of the sorts of things that plugins can do. Plugins are a powerful system for augmenting
|
||||
Appium's functionality or changing the way Appium works. They can be distributed to other Appium
|
||||
users and can extend Appium's ecosystem in all kinds of interesting ways! (There is also
|
||||
@@ -27,7 +27,7 @@ There are a wide variety of open source Appium plugins available for perusal. It
|
||||
recommended to explore the code for some other plugins before embarking on writing your own. The
|
||||
Appium team maintains a set of official plugins in the [Appium GitHub
|
||||
repo](https://github.com/appium/appium). Links to other open source plugins can be found in the
|
||||
[Plugin list](./index.md#plugins)
|
||||
[Plugin list](../ecosystem/plugins.md)
|
||||
|
||||
## Basic requirements for plugins
|
||||
|
||||
@@ -41,7 +41,7 @@ Node.js so it can be loaded by Appium.
|
||||
|
||||
Your `package.json` must include `appium` as a `peerDependency`. The requirements for the
|
||||
dependency versions should be as loose as possible (unless you happen to know your plugin will only
|
||||
work with certain versions of Appium). For Appium 2.0, for example, this would look something like
|
||||
work with certain versions of Appium). For Appium 2, for example, this would look something like
|
||||
`^2.0.0`, declaring that your plugin works with any version of Appium that starts with 2.x.
|
||||
|
||||
Your `package.json` must contain an `appium` field, like this (we call this the 'Appium extension
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Intro to Development
|
||||
---
|
||||
|
||||
Appium 2 is built with a modular structure, which means that Appium extensions (drivers and plugins)
|
||||
are decoupled from the main Appium module, and you only need to install the extensions that you
|
||||
want to use. This modular structure also unlocks the ability to develop entirely new extensions!
|
||||
|
||||
This section of the Appium documentation is intended to help aspiring developers with creating their
|
||||
own Appium extension:
|
||||
|
||||
* For creating a driver, see the [Build Drivers](./build-drivers.md) page
|
||||
* For creating a plugin, take a look at the [Build Plugins](build-plugins.md) page
|
||||
* Drivers and plugins both need documentation, so check out the [Build Documentation](./build-docs.md) page
|
||||
@@ -1,242 +0,0 @@
|
||||
---
|
||||
title: Building Docs for Appium Extensions
|
||||
---
|
||||
|
||||
Once you've [built a driver](./build-drivers.md) or [built a plugin](./build-plugins.md) for Appium,
|
||||
you will hopefully want to document how that extension works for your users. The most basic way of
|
||||
doing this is to write up a quick `README.md` and keep it in the root of your project's repository.
|
||||
However, this can involve a lot of duplication of effort, especially when documenting things like
|
||||
Appium commands.
|
||||
|
||||
Let's say your driver implements ~25 of the standard WebDriver protocol commands. You could write
|
||||
up a description of these commands, how they map to the protocol, what parameters they take, and
|
||||
what behaviour will result on your particular platform. But this information is already more or
|
||||
less stored in your code, as the command implementation (and any docstrings or comments). Having
|
||||
this information in two places creates an opportunity for the docs to get out of sync with the
|
||||
reality of the code. Wouldn't it be nice to generate command reference documentation straight from
|
||||
the code?
|
||||
|
||||
Another problem with the basic single file `README.md` approach is that many extensions might want a
|
||||
whole set of documents including longer prose guides (like this one). It might be nice to have code
|
||||
examples where you can toggle between different programming languages. It might be nice to be able
|
||||
to add a project-specific logo. And so on.
|
||||
|
||||
The Appium project has built tools to do all these things, and we've packaged up these tools so our
|
||||
ecosystem developers building drivers and plugins can _also_ use them. The best way to get going
|
||||
with these tools is probably to look at an existing Appium driver repo to see how it's done, for
|
||||
example the [XCUITest driver repo](https://github.com/appium/appium-xcuitest-driver). But this guide
|
||||
will outline the basic approach.
|
||||
|
||||
### Conceptual architecture
|
||||
|
||||
Appium settled on [MkDocs](https://www.mkdocs.org/) as a Markdown-based documentation site
|
||||
generator. It uses a Python toolchain (and not Node.js), but it turned out to be the best option
|
||||
for our purposes. You can adjust this, but by default Appium's utilities also assume that you'll be
|
||||
using the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/) theme/extension for
|
||||
MkDocs.
|
||||
|
||||
From here, building a basic docs site is as easy as collecting your Markdown files together and
|
||||
creating a sort of manifest file defining how you want them to be organized.
|
||||
|
||||
The other main piece is automatic documentation generation from your code files. Appium maintains
|
||||
a plugin for [TypeDoc](https://typedoc.org/). This plugin is incorporated into our doc utility.
|
||||
When you give it an entrypoint for you driver or plugin, it will scan and parse all your code files
|
||||
looking for Appium command implementations. A set of Markdown reference files will be generated for these
|
||||
commands, which will then be included in your docs site.
|
||||
|
||||
> Note: Implementing an extension in TypeScript is _not_ a requirement for generating documentation,
|
||||
> but for automated doc generation to work, you will need to apply TypeScript-supported JSDoc-style
|
||||
> docstrings to your JS codebase. See ["JS Projects Utilizing TypeScript"](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html) for more information.
|
||||
|
||||
In order to make different versions of your docs available (one for each minor release of your
|
||||
extension, typically), we also bundle [Mike](https://github.com/jimporter/mike).
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To take advantage of Appium's documentation utilities, you'll need to install:
|
||||
|
||||
- [Python v3+](https://www.python.org/downloads/)
|
||||
- [pip](https://pip.pypa.io/en/stable/installation/) (this may be installed automatically with Python)
|
||||
- The `@appium/docutils` package:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @appium/docutils
|
||||
```
|
||||
|
||||
### Initializing an Extension for Building Docs
|
||||
|
||||
To prepare your extension for generating documentation, run the following command:
|
||||
|
||||
```bash
|
||||
npx appium-docs init --entry-point <my-entry-point.js>
|
||||
```
|
||||
|
||||
...where `<my-entry-point.js>` is the **source entry point** to your extension. If you _are not_ transpiling your code via TypeScript, Babel, etc., this is typically the same as the value of the `main` property in `package.json`. If you _are_ transpiling, this is typically different. For example, your `main` property may be `dist/index.js`, but your **source entry point** is `src/index.ts`.
|
||||
|
||||
This will:
|
||||
|
||||
1. Create a `tsconfig.json` if one does not already exist. This is necessary even if your extension is not written in TypeScript.
|
||||
2. Create a `typedoc.json` with the necessary configuration for TypeDoc.
|
||||
3. Create a `mkdocs.yml` with the necessary configuration for MkDocs.
|
||||
4. Modify your `package.json` to add a `typedoc.entryPoint` property with a value of your entry point (as specified above).
|
||||
|
||||
### Documenting Your Extension
|
||||
|
||||
At this point, you can begin documenting your extension. You don't need to do this all at once, but you should make the following changes, at minimum.
|
||||
|
||||
#### `newMethodMap` and `executeMethodMap`
|
||||
|
||||
The static properties `newMethodMap` and `executeMethodMap` may be present on your extension's main class. If they are not, then you can skip to the next section. If they are, you will need to make the following changes, depending on your extension's language.
|
||||
|
||||
##### JavaScript
|
||||
|
||||
```js
|
||||
// note: this is equivalent to the TypeScript example below
|
||||
|
||||
class MyExtension {
|
||||
static newMethodMap = /** @type {const} */({
|
||||
// ...
|
||||
});
|
||||
|
||||
static executeMethodMap = /** @type {const} */({
|
||||
// ...
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
##### TypeScript
|
||||
|
||||
```ts
|
||||
class MyExtension {
|
||||
static newMethodMap = {
|
||||
// ...
|
||||
} as const;
|
||||
|
||||
static executeMethodMap = {
|
||||
// ...
|
||||
} as const;
|
||||
}
|
||||
```
|
||||
|
||||
#### Driver Constraints
|
||||
|
||||
> Note: Plugin authors can skip this section.
|
||||
|
||||
Your driver may have a property `desiredCapConstraints`. It should also follow the same pattern as `newMethodMap` and `executeMethodMap` above. For example:
|
||||
|
||||
```js
|
||||
class MyExtension {
|
||||
desiredCapConstraints = /** @type {const} */({
|
||||
myCapability: {
|
||||
presence: true,
|
||||
isString: true
|
||||
},
|
||||
myOtherCap: {
|
||||
isBoolean: true
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
(For extensions written in TypeScript, use `as const` as before.)
|
||||
|
||||
#### Commands
|
||||
|
||||
The documentation for a command, as defined in your extension, comes from multiple places. These sources are then combined as needed into the final output.
|
||||
|
||||
In Appium, new commands are defined in `newMethodMap` and execute methods are defined in `executeMethodMap`. **The value of these properties are used to build your documentation.** In particular, parameter names and optional/required status _override_ whatever method implementation does. So for example, if your `newMethodMap` contains:
|
||||
|
||||
```js
|
||||
class MyExtension {
|
||||
static newMethodMap = /** @type {const} */({
|
||||
'/session/:sessionId/myThing': {
|
||||
/**
|
||||
* Does my thing
|
||||
*/
|
||||
GET: {command: 'doMyThing', payloadParams: {required: ['a', 'b']}},
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
...and your `doMyThing` method implementation looks like this:
|
||||
|
||||
```js
|
||||
class MyExtension {
|
||||
/**
|
||||
* Doesn't do my thing
|
||||
* @param {any} a - Whatever
|
||||
* @param {number} d - Some number
|
||||
* @param {boolean} c - Some boolean
|
||||
* @returns {Promise<boolean>} Some other boolean
|
||||
*/
|
||||
async doMyThing(a, d = 1, c = false) {
|
||||
// ...
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The documentation will show that the `doMyThing` method accepts required parameters `a` and `b`. Even though `b` is named `d` in the implementation--and it's optional--it will be ignored. Likewise, since the definition in `newMethodMap` knows nothing about `c`, it too is ignored.
|
||||
|
||||
In addition, the _description_ from the docstring in `newMethodMap` overrides the description in the method implementation; it will describe the command `doMyThing` as "Does my thing".
|
||||
|
||||
The `@param` tags and `@returns` tag from the method's docstring provide information about the expected and returned types, as well as a description of each. This is not expressible via `newMethodMap` and `executeMethodMap` alone; it provides more information for your extension's users.
|
||||
|
||||
> Note for TypeScript users: while the _types_ will already be present, providing `@param` and `@returns` tags is still useful for providing descriptions.
|
||||
|
||||
All commands must be `async`, so they will return `Promise<T>` where type `T` is the type of whatever the `Promise` fulfills with. In the generated documentation, the `Promise` is ignored, and only `T` is reported. So for `doMyThing`, the return type of the command, as output in the documentation, will be `boolean`.
|
||||
|
||||
This is because while extensions must be written in JavaScript, we're documenting an API which can be called from any language; that language likely won't have a concept of a `Promise`. Likewise, `undefined` or `void` types will be output as `null` (since that is a concept that translates well to multiple languages).
|
||||
|
||||
#### Optional: `README.md`
|
||||
|
||||
If you have a `README.md`, it will be pulled in to the generated docs site automatically. This behavior can be disabled by adding the following to `typedoc.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"readme": "none"
|
||||
}
|
||||
```
|
||||
|
||||
#### Next Steps
|
||||
|
||||
Appium provides type definitions for extension authors; these are available via Appium itself and the [`@appium/types`](https://npm.im/@appium/types) package.
|
||||
|
||||
Of note, drivers should both extend `BaseDriver` _and_ implement the `ExternalDriver` interface exported by `@appium/types`. This will help ensure that your driver's implementation is correct and usable by different clients.
|
||||
|
||||
You're encouraged to look at the official test/example extensions, [`@appium/fake-driver`](https://npm.im/@appium/fake-driver) and [`@appium/fake-plugin`](https://npm.im/@appium/fake-plugin) for canonical examples of how to use these types.
|
||||
|
||||
#### Resources
|
||||
|
||||
How to type more complex return values or parameters is beyond the scope of this document. For more information, see:
|
||||
|
||||
- For extensions written in JS, the [TypeScript documentation](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html)
|
||||
- For tags in addition to what TS natively recognizes, see the [TypeDoc documentation](https://typedoc.org/guides/doccomments/)
|
||||
|
||||
Likewise, refer to the [MkDocs documentation](https://www.mkdocs.org/user-guide/writing-your-docs/) for further information on how to customize your MkDocs output.
|
||||
|
||||
### Usage
|
||||
|
||||
At this point, you can use the `appium-docs` CLI tool. Run this tool with no arguments to get the
|
||||
full help output and see all the available subcommands and parameters. Here are a few usage
|
||||
examples:
|
||||
|
||||
```bash
|
||||
# Generate reference and build the mkdocs site into the site dir
|
||||
npx appium-docs build
|
||||
|
||||
# Same as build, but host the docs on a local dev server
|
||||
# and watch for changes and rebuild when files change
|
||||
npx appium-docs build --serve
|
||||
|
||||
# Build the docs and deploy them with mike versioning to the docs-site branch
|
||||
# using the included commit message and rebase strategy on the branch.
|
||||
# This is particularly useful for pushing content to a GitHub pages branch!
|
||||
npx appium-docs build \
|
||||
--deploy \
|
||||
-b docs-site \
|
||||
-m 'docs: auto-build docs for appium-xcuitest-driver@%s' \
|
||||
--rebase
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Clients
|
||||
---
|
||||
|
||||
You need a client to write and run Appium scripts. You'll want to become very
|
||||
familiar with your client documentation (as well as the documentation of any Selenium client that
|
||||
the Appium client depends on) since that will be your primary interface to Appium.
|
||||
|
||||
To learn more about clients, read our [Client Intro](../intro/clients.md).
|
||||
|
||||
### Official Clients
|
||||
|
||||
These clients are currently maintained by the Appium team:
|
||||
|
||||
|Client|Language|
|
||||
|-|-|
|
||||
|[Appium Java client](https://github.com/appium/java-client)|Java|
|
||||
|[Appium Python client](https://github.com/appium/python-client)|Python|
|
||||
|[Appium Ruby Core client](https://github.com/appium/ruby_lib_core) (Recommended)<br>[Appium Ruby client](https://github.com/appium/ruby_lib)|Ruby|
|
||||
|[Appium .NET client](https://github.com/appium/dotnet-client)|C#|
|
||||
|
||||
### Other Clients
|
||||
|
||||
These clients are not maintained by the Appium team and can be used with other languages:
|
||||
|
||||
|Client|Language|
|
||||
|-|-|
|
||||
|[WebdriverIO](https://webdriver.io/docs/appium)|Node.js|
|
||||
|[Nightwatch.js](https://nightwatchjs.org/guide/mobile-app-testing/introduction.html)|Node.js|
|
||||
|[RobotFramework](https://github.com/serhatbolsu/robotframework-appiumlibrary)|DSL|
|
||||
|
||||
In general, any W3C WebDriver spec-compatible client will also integrate well with Appium, though
|
||||
some Appium-specific commands may not be implemented in other clients.
|
||||
|
||||
!!! note
|
||||
|
||||
If you maintain an Appium client that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the documentation for the client.
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Drivers
|
||||
---
|
||||
|
||||
You can't use Appium without at least one driver! Click on the link for each driver to see the
|
||||
specific installation instructions and documentation for that driver.
|
||||
|
||||
Generally, drivers can be installed using their listed installation key, with the following command:
|
||||
```
|
||||
appium driver install <installation key>
|
||||
```
|
||||
|
||||
To learn more about drivers, check out the [Driver Intro](../intro/drivers.md).
|
||||
|
||||
### Official Drivers
|
||||
|
||||
These drivers are currently maintained by the Appium team:
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|
|
||||
|--|--|--|--|
|
||||
|[Chromium](https://github.com/appium/appium-chromium-driver)|`chromium`|macOS, Windows, Linux|Web|
|
||||
|[Espresso](https://github.com/appium/appium-espresso-driver)|`espresso`|Android|Native|
|
||||
|[Gecko](https://github.com/appium/appium-geckodriver)|`gecko`|macOS, Windows, Linux, Android|Web|
|
||||
|[Mac2](https://github.com/appium/appium-mac2-driver)|`mac2`|macOS|Native|
|
||||
|[Safari](https://github.com/appium/appium-safari-driver)|`safari`|macOS, iOS|Web|
|
||||
|[UiAutomator2](https://github.com/appium/appium-uiautomator2-driver)|`uiautomator2`|Android|Native, Hybrid, Web|
|
||||
|[XCUITest](https://github.com/appium/appium-xcuitest-driver)|`xcuitest`|iOS|Native, Hybrid, Web|
|
||||
|
||||
### Other Drivers
|
||||
|
||||
These drivers are not maintained by the Appium team and can be used to target additional platforms:
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|Supported By|
|
||||
|--|--|--|--|--|
|
||||
|[Flutter](https://github.com/appium/appium-flutter-driver)|`--source=npm appium-flutter-driver`|iOS, Android|Native|Community|
|
||||
|[LG WebOS](https://github.com/headspinio/appium-lg-webos-driver)|`--source=npm appium-lg-webos-driver`|LG TV|Web|HeadSpin|
|
||||
|[Linux](https://github.com/fantonglang/appium-linux-driver)|`--source=npm @stdspa/appium-linux-driver`|Linux|Native|`@fantonglang`|
|
||||
|[Roku](https://github.com/headspinio/appium-roku-driver)|`--source=npm @headspinio/appium-roku-driver`|Roku|Native|HeadSpin|
|
||||
|[Tizen](https://github.com/Samsung/appium-tizen-driver)|`--source=npm appium-tizen-driver`|Android|Native|Community / Samsung|
|
||||
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|
||||
|[Windows](https://github.com/appium/appium-windows-driver)|`--source=npm appium-windows-driver`|Windows|Native|Community / Microsoft|
|
||||
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|
||||
|
||||
!!! note
|
||||
|
||||
If you maintain an Appium driver that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the driver documentation.
|
||||
@@ -1,107 +1,45 @@
|
||||
---
|
||||
title: The Appium Ecosystem
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Ecosystem Overview
|
||||
---
|
||||
|
||||
Appium has an ecosystem of related software and tools. In this guide we'll discuss important
|
||||
officially-supported and community-supported projects.
|
||||
Appium has a wide ecosystem of related software and tools. This section of the Appium documentation
|
||||
aims to compile a listing of various officially-supported and community-supported Appium projects:
|
||||
|
||||
## Appium Inspector
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
Appium has a graphical client which can be used to manually perform Appium commands, inspect app
|
||||
hierarchies, view screenshots, and more. It's very useful for Appium test development. You can
|
||||
learn more about the inspector here: [Appium Inspector](https://github.com/appium/appium-inspector)
|
||||
- :material-car: __Drivers__
|
||||
|
||||
## Drivers
|
||||
---
|
||||
|
||||
You can't use Appium without at least one driver! Here are the drivers that are currently
|
||||
maintained by the Appium team. Click on the link for each driver to see the specific installation
|
||||
instructions and documentation for that driver.
|
||||
Link Appium to your test device
|
||||
|
||||
To learn more about what drivers are and how they work, check out the [Driver
|
||||
Intro](../intro/drivers.md)
|
||||
[:octicons-arrow-right-24: View all drivers](./drivers.md)
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|
|
||||
|--|--|--|--|
|
||||
|[Chromium](https://github.com/appium/appium-chromium-driver)|`chromium`|macOS, Windows, Linux|Web|
|
||||
|[Espresso](https://github.com/appium/appium-espresso-driver)|`espresso`|Android|Native|
|
||||
|[Gecko](https://github.com/appium/appium-geckodriver)|`gecko`|macOS, Windows, Linux, Android|Web|
|
||||
|[Mac2](https://github.com/appium/appium-mac2-driver)|`mac2`|macOS|Native|
|
||||
|[Safari](https://github.com/appium/appium-safari-driver)|`safari`|macOS, iOS|Web|
|
||||
|[UiAutomator2](https://github.com/appium/appium-uiautomator2-driver)|`uiautomator2`|Android|Native, Hybrid, Web|
|
||||
|[XCUITest](https://github.com/appium/appium-xcuitest-driver)|`xcuitest`|iOS|Native, Hybrid, Web|
|
||||
- :octicons-code-16: __Clients__
|
||||
|
||||
And of course, you can install any other drivers you find out there by using the Appium driver CLI.
|
||||
---
|
||||
|
||||
### Other drivers
|
||||
Link Appium to your automation code
|
||||
|
||||
These drivers are not maintained by the Appium team and can be used to target additional platforms.
|
||||
[:octicons-arrow-right-24: View all clients](./clients.md)
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|Supported By|
|
||||
|--|--|--|--|--|
|
||||
|[Flutter](https://github.com/appium-userland/appium-flutter-driver)|`--source=npm appium-flutter-driver`|iOS, Android|Native|Community|
|
||||
|[LG WebOS](https://github.com/headspinio/appium-lg-webos-driver)|`--source=npm appium-lg-webos-driver`|LG TV|Web|HeadSpin|
|
||||
|[Linux](https://github.com/fantonglang/appium-linux-driver)|`--source=npm @stdspa/appium-linux-driver`|Linux|Native|`@fantonglang`|
|
||||
|[Roku](https://github.com/headspinio/appium-roku-driver)|`--source=npm @headspinio/appium-roku-driver`|Roku|Native|HeadSpin|
|
||||
|[Tizen](https://github.com/Samsung/appium-tizen-driver)|`--source=npm appium-tizen-driver`|Android|Native|Community / Samsung|
|
||||
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|
||||
|[Windows](https://github.com/appium/appium-windows-driver)|`--source=npm appium-windows-driver`|Windows|Native|Community / Microsoft|
|
||||
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|
||||
- :fontawesome-solid-plug: __Plugins__
|
||||
|
||||
!!! note
|
||||
---
|
||||
|
||||
If you maintain an Appium driver that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the driver documentation.
|
||||
Modify and extend Appium functionality
|
||||
|
||||
## Clients
|
||||
[:octicons-arrow-right-24: View all plugins](./plugins.md)
|
||||
|
||||
You need clients to write and run Appium scripts. To learn more about clients, read our [Client
|
||||
Intro](../intro/clients.md). Here is the list of known Appium clients. You'll want to become very
|
||||
familiar with your client documentation (as well as the documentation of any Selenium client that
|
||||
the Appium client depends on) since that is what you will use as your primary interface to Appium.
|
||||
- :material-wrench: __Tools__
|
||||
|
||||
|Client|Language|Supported By|
|
||||
|-|-|-|
|
||||
|[Appium Java client](https://github.com/appium/java-client)|Java|Appium Team|
|
||||
|[Appium Python client](https://github.com/appium/python-client)|Python|Appium Team|
|
||||
|[Appium Ruby Core client](https://github.com/appium/ruby_lib_core) (Recommended)<br>[Appium Ruby client](https://github.com/appium/ruby_lib)|Ruby|Appium Team|
|
||||
|[WebDriverIO](https://webdriver.io)<br>[Nightwatch](https://nightwatchjs.org/)|Node.js|Community|
|
||||
|[Appium .NET client](https://github.com/appium/dotnet-client)|C#|Appium Team*|
|
||||
|[RobotFramework](https://github.com/serhatbolsu/robotframework-appiumlibrary)|DSL|Community|
|
||||
---
|
||||
|
||||
In general, any W3C WebDriver spec-compatible client will also integrate well with Appium, though
|
||||
some Appium-specific commands may not be implemented in other clients.
|
||||
Interact with Appium in other ways
|
||||
|
||||
## Plugins
|
||||
|
||||
Appium Plugins offer ways to extend or modify Appium's behaviour. This is the list of plugins that
|
||||
are currently maintained by the Appium Team:
|
||||
|
||||
|Plugin|Installation Key|Description|Supported By|
|
||||
|---|---|---|---|
|
||||
|[Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)|`execute-driver`|Run entire batches of commands in a single call to the Appium server|Appium Team|
|
||||
|[Images](https://github.com/appium/appium/tree/master/packages/images-plugin)|`images`|Image matching and comparison features|Appium Team|
|
||||
|[Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)|`relaxed-caps`|Relax Appium's requirement for vendor prefixes on capabilities|Appium Team|
|
||||
|[Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)|`universal-xml`|Instead of the standard XML format for iOS and Android, use an XML definition that is the same across both platforms|Appium Team|
|
||||
|
||||
### Other plugins
|
||||
|
||||
|Plugin|Installation Key|Description|Supported By|
|
||||
|---|---|---|---|
|
||||
|[AltUnity](https://github.com/headspinio/appium-altunity-plugin)|`--source=npm appium-altunity-plugin`|Target Unity games and apps for automation with a new context, via the AltUnityTester framework|HeadSpin|
|
||||
|[Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)|`--source=npm appium-device-farm`|Manage and create driver session on connected android devices and iOS Simulators.|`@AppiumTestDistribution`|
|
||||
|[OCR](https://github.com/jlipps/appium-ocr-plugin)|`--source=npm appium-ocr-plugin`|Find elements via OCR text|`@jlipps`|
|
||||
|[Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)|`--source=npm appium-reporter-plugin`|Generates standalone consolidated html report with screenshots. Reports can be fetched from appium server, without worrying about heavy lifting such as screenshot capturing, report generation etc.|`@AppiumTestDistribution`|
|
||||
|
||||
!!! note
|
||||
|
||||
If you maintain an Appium plugin that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the documentation for the plugin.
|
||||
|
||||
## Helper tools
|
||||
|
||||
The following tools might also be useful for Appium users:
|
||||
|
||||
|Name|Description|Supported By|
|
||||
|---|---|---|
|
||||
|[appium-installer](https://github.com/AppiumTestDistribution/appium-installer)|Help set up an Appium environment for Android and iOS|`@AppiumTestDistribution`|
|
||||
[:octicons-arrow-right-24: View all tools](./tools.md)
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Plugins
|
||||
---
|
||||
|
||||
Plugins offer various ways to extend or modify Appium's behaviour. They are _completely optional_
|
||||
and are not needed for standard automation functionality, but you may find them to be useful
|
||||
for more specialised automation workflows.
|
||||
|
||||
Generally, plugins can be installed using their listed installation key, with the following command:
|
||||
```
|
||||
appium plugin install <installation key>
|
||||
```
|
||||
|
||||
### Official Plugins
|
||||
|
||||
These plugins are are currently maintained by the Appium team:
|
||||
|
||||
|<div style="width:7em">Plugin</div>|<div style="width:8em">Installation Key</div>|Description|
|
||||
|---|---|---|
|
||||
|[Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)|`execute-driver`|Run entire batches of commands in a single call to the Appium server|
|
||||
|[Images](https://github.com/appium/appium/tree/master/packages/images-plugin)|`images`|Image matching and comparison features|
|
||||
|[Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)|`relaxed-caps`|Relax Appium's requirement for vendor prefixes on capabilities|
|
||||
|[Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)|`universal-xml`|Instead of the standard XML format for iOS and Android, use an XML definition that is the same across both platforms|
|
||||
|
||||
### Other Plugins
|
||||
|
||||
These plugins are not maintained by the Appium team and can provide additional functionality:
|
||||
|
||||
|<div style="width:6em">Plugin</div>|<div style="width:19em">Installation Key</div>|Description|<div style="width:13em">Supported By</div>|
|
||||
|---|---|---|---|
|
||||
|[AltUnity](https://github.com/headspinio/appium-altunity-plugin)|`--source=npm appium-altunity-plugin`|Target Unity games and apps for automation with a new context, via the AltUnityTester framework|HeadSpin|
|
||||
|[Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)|`--source=npm appium-device-farm`|Manage and create driver session on connected android devices and iOS Simulators.|`@AppiumTestDistribution`|
|
||||
|[OCR](https://github.com/jlipps/appium-ocr-plugin)|`--source=npm appium-ocr-plugin`|Find elements via OCR text|`@jlipps`|
|
||||
|[Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)|`--source=npm appium-reporter-plugin`|Generates standalone consolidated html report with screenshots. Reports can be fetched from appium server, without worrying about heavy lifting such as screenshot capturing, report generation etc.|`@AppiumTestDistribution`|
|
||||
|
||||
!!! note
|
||||
|
||||
If you maintain an Appium plugin that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the documentation for the plugin.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium-Related Tools
|
||||
---
|
||||
|
||||
There are several Appium tools that have been created to to assist with things not directly related
|
||||
to testing, such as Appium installation, test development, and more.
|
||||
|
||||
### Appium Inspector
|
||||
|
||||
Appium has a graphical client which can be used to inspect application screenshots, view the
|
||||
application hierarchy, run Appium commands, record app interactions, and more. It is very useful
|
||||
for Appium test development.
|
||||
|
||||
Find downloads and more information on its GitHub page: [Appium Inspector](https://github.com/appium/appium-inspector)
|
||||
|
||||
### Appium Doctor
|
||||
|
||||
The `appium-doctor` CLI tool can be used to validate proper environment setup for Android and iOS
|
||||
automation, and identify any common configuration issues. It can be installed with `npm`:
|
||||
|
||||
```sh
|
||||
npm install -g @appium/doctor
|
||||
```
|
||||
|
||||
Learn more on its GitHub page: [Appium Doctor](https://github.com/appium/appium/tree/master/packages/doctor)
|
||||
|
||||
### Other Tools
|
||||
|
||||
These tools are not maintained by the Appium team and can be used to assist with other problems:
|
||||
|
||||
|Name|Description|Supported By|
|
||||
|---|---|---|
|
||||
|[appium-installer](https://github.com/AppiumTestDistribution/appium-installer)|Help set up an Appium environment for Android and iOS|`@AppiumTestDistribution`|
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: Application Bundles Caching Logic
|
||||
title: Caching of Application Bundles
|
||||
---
|
||||
|
||||
Appium Base driver provides a feature which enables caching of application builds provided, for example,
|
||||
Appium's base driver provides a feature which enables caching of application builds provided, for example,
|
||||
as `app` capability value or to endpoints similar to the `installApp` one. This article explains common caching
|
||||
principles, so you could create more performant and efficient test suite execution strategies.
|
||||
|
||||
@@ -15,13 +15,13 @@ bundle for each test.
|
||||
## What Is Cached
|
||||
|
||||
Caching could be applied to application bundles generated by
|
||||
[configureApp](../../../../../packages/base-driver/lib/basedriver/helpers.js) helper call. Inherited drivers
|
||||
can customize their caching logic by providing own `onPostProcess` property definition, but the general
|
||||
[`configureApp`](https://github.com/appium/appium/blob/master/packages/base-driver/lib/basedriver/helpers.js#L107) helper call.
|
||||
Inherited drivers can customize their caching logic by providing own `onPostProcess` property definition, but the general
|
||||
rule of thumb is that we need to cache locally all application bundles need to be downloaded and/or extracted
|
||||
first before they could be actually installed on the device under test. On iOS, for example, these are .ipa or
|
||||
.zip compressed application bundles or .aab on Android.
|
||||
first before they could be actually installed on the device under test. On iOS, for example, these are `.ipa` or
|
||||
`.zip` compressed application bundles, or .`aab` on Android.
|
||||
|
||||
## How Remote Application Bundles Are Cached
|
||||
## Caching of Remote Application Bundles
|
||||
|
||||
In order to validate whether an app bundle downloaded from the given URL could be (re)used from the cache the following
|
||||
steps are applied:
|
||||
@@ -33,16 +33,16 @@ or the header value cannot be parsed as a valid datetime then no caching is appl
|
||||
3. The script checks if the given URL is already present in the cache. If the app is not cached yet then it gets downloaded
|
||||
and its current header values along with hashsum are added to the cache.
|
||||
4. If the URL was already in the cache then the script verifies that:
|
||||
- the current `Last-Modified` datetime is not different from the previous one
|
||||
- the difference between the current `Last-Modified` datetime and the cached one is not greater than max-age (if present)
|
||||
- the hashsum of the cached file/folder is not changed (e.g. it was not corrupted while sitting in the cache)
|
||||
- the current `Last-Modified` datetime is not different from the previous one
|
||||
- the difference between the current `Last-Modified` datetime and the cached one is not greater than max-age (if present)
|
||||
- the hashsum of the cached file/folder is not changed (e.g. it was not corrupted while sitting in the cache)
|
||||
5. If all validations above succeed then the cached build is returned, otherwise the currently cached entry gets
|
||||
deleted and a new one is downloaded instead.
|
||||
|
||||
## How Local Application Bundles Are Cached
|
||||
## Caching of Local Application Bundles
|
||||
|
||||
It only makes sense to cache application bundles if they need some preprocessing before being installed on the device under test.
|
||||
For example, on iOS .ipa bundles must be unzipped, because the system installer only works with .app folders.
|
||||
For example, on iOS `.ipa` bundles must be unzipped, because the system installer only works with `.app` folders.
|
||||
|
||||
1. The script verifies if the given bundle path is already present in the cache. If the bundle was not in the cache yet
|
||||
then it gets preprocessed and added there.
|
||||
@@ -62,5 +62,5 @@ of it. It is a [LRU Cache](https://www.npmjs.com/package/lru-cache) with the fol
|
||||
!!! warning
|
||||
|
||||
Note: The cache root folder is set up for automatic deletion on Appium process termination. This would only
|
||||
work if Appium server is killed with SIGINT or SIGTERM. If SIGKILL is used then no cache cleanup
|
||||
work if Appium server is killed with `SIGINT` or `SIGTERM`. If `SIGKILL` is used then no cache cleanup
|
||||
would be performed.
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
---
|
||||
title: Capabilities
|
||||
title: Session Capabilities
|
||||
---
|
||||
|
||||
"Capabilities" is the name given to the set of parameters used to start an Appium session. The
|
||||
information in the set is used to describe what sort of "capabilities" you want your session to
|
||||
have, for example, a certain mobile operating system or a certain version of a device. When you
|
||||
start your Appium session, your Appium client will include the set of capabilities you've defined
|
||||
as an object in the JSON-formatted body of the request. Capabilities are represented as key-value
|
||||
pairs, with values allowed to be any valid JSON type, including other objects. Appium will then
|
||||
examine the capabilities and make sure that it can satisfy them before proceeding to start the
|
||||
session and return an ID representing the session to your client library.
|
||||
information in the set describes what sort of "capabilities" you want your session to have, for
|
||||
example, a certain mobile operating system or a certain version of a device. Capabilities are
|
||||
represented as key-value pairs, with values allowed to be any valid JSON type, including
|
||||
other objects.
|
||||
|
||||
The W3C WebDriver spec's [section on Capabilities](https://w3c.github.io/webdriver/#capabilities)
|
||||
identifies a small set of 10 standard capabilities, including the following:
|
||||
@@ -20,7 +17,7 @@ identifies a small set of 10 standard capabilities, including the following:
|
||||
| `browserVersion` | `string` | The specific version of the browser |
|
||||
| `platformName` | `string` | The type of platform hosting the browser |
|
||||
|
||||
## Appium capabilities
|
||||
## Common Appium Capabilities
|
||||
|
||||
Appium understands these browser-focused capabilities, but introduces a number of additional
|
||||
capabilities. According to the WebDriver spec, any
|
||||
@@ -30,26 +27,26 @@ introducing the capability), ending in a `:`. Appium's vendor prefix is
|
||||
client you are using, the prefix may be added automatically or in conjunction with certain
|
||||
interfaces, but it is always a good practice to explicitly include it for clarity.
|
||||
|
||||
Here is a list of all the globally-recognized Appium capabilities. Notes:
|
||||
Here is a list of all the globally-recognized Appium capabilities:
|
||||
|
||||
- Individual drivers and plugins can support other capabilities, so refer to their documentation for lists of extension-specific
|
||||
capability names.
|
||||
- Some drivers might not implement support for all of these capabilities
|
||||
- A few Appium extension capabilities are required to start any Appium session; these are noted below as "Required"
|
||||
!!! info
|
||||
|
||||
| Capability | Type | Required? | Description |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `platformName` | `string` | Required | The type of platform hosting the app or browser |
|
||||
| `appium:automationName` | `string` | Required | The name of the Appium driver to use |
|
||||
| `browserName` | `string` | | The name of the browser to launch and automate, if the driver supports web browsers as a special case |
|
||||
| `appium:app` | `string` | | The path to an installable application |
|
||||
| `appium:deviceName` | `string` | | The name of a particular device to automate, e.g., `iPhone 14` (currently only actually useful for specifying iOS simulators, since in other situations it's typically recommended to use a specific device id via the `appium:udid` capability). |
|
||||
| `appium:platformVersion` | `string` | | The version of a platform, e.g., for iOS, `16.0` |
|
||||
| `appium:newCommandTimeout` | `number` | | The number of seconds the Appium server should wait for clients to send commands before deciding that the client has gone away and the session should shut down |
|
||||
| `appium:noReset` | `boolean` | | If true, instruct an Appium driver to avoid its usual reset logic during session start and cleanup (default `false`) |
|
||||
| `appium:fullReset` | `boolean` | | If true, instruct an Appium driver to augment its usual reset logic with additional steps to ensure maximum environmental reproducibility (default `false`) |
|
||||
| `appium:eventTimings` | `boolean` | | If true, instruct an Appium driver to collect [Event Timings](./event-timing.md) (default `false`) |
|
||||
| `appium:printPageSourceOnFindFailure` | `boolean` | | If true, collect the page source and print it to the Appium log whenever a request to find an element fails (default `false`) |
|
||||
Individual drivers and plugins can support other capabilities, so refer to their documentation
|
||||
for lists ofspecific capability names. Some drivers may also not support all of these capabilities
|
||||
|
||||
| <div style="width:12em">Capability</div> | Type | Required? | Description |
|
||||
|--------------------------------------------|-----------|-----------|----------------------------|
|
||||
| `platformName` | `string` | yes | The type of platform hosting the app or browser |
|
||||
| `appium:automationName` | `string` | yes | The name of the Appium driver to use |
|
||||
| `browserName` | `string` | no | The name of the browser to launch and automate, if the driver supports web browsers as a special case |
|
||||
| `appium:app` | `string` | no | The path to an installable application |
|
||||
| `appium:deviceName` | `string` | no | The name of a particular device to automate, e.g., `iPhone 14` (currently only actually useful for specifying iOS simulators, since in other situations it's typically recommended to use a specific device id via the `appium:udid` capability). |
|
||||
| `appium:platformVersion` | `string` | no | The version of a platform, e.g., for iOS, `16.0` |
|
||||
| `appium:newCommandTimeout` | `number` | no | The number of seconds the Appium server should wait for clients to send commands before deciding that the client has gone away and the session should shut down |
|
||||
| `appium:noReset` | `boolean` | no | If true, instruct an Appium driver to avoid its usual reset logic during session start and cleanup (default `false`) |
|
||||
| `appium:fullReset` | `boolean` | no | If true, instruct an Appium driver to augment its usual reset logic with additional steps to ensure maximum environmental reproducibility (default `false`) |
|
||||
| `appium:eventTimings` | `boolean` | no | If true, instruct an Appium driver to collect [Event Timings](./event-timing.md) (default `false`) |
|
||||
| `appium:printPageSourceOnFindFailure` | `boolean` | no | If true, collect the page source and print it to the Appium log whenever a request to find an element fails (default `false`) |
|
||||
|
||||
|
||||
Some drivers place more complex constraints on capabilities as a group. For example, while the
|
||||
@@ -70,7 +67,7 @@ Each Appium client has its own way of constructing capabilities and starting a s
|
||||
examples of doing this in each client library, head to the [Ecosystem](../ecosystem/index.md) page
|
||||
and click through to the appropriate client documentation.
|
||||
|
||||
## `appium:options`
|
||||
## Using `appium:options` to Group Capabilities
|
||||
|
||||
If you use a lot of `appium:` capabilities in your tests, it can get a little repetitive. You can
|
||||
combine all capabilities as an object value of a single `appium:options` capability instead, in
|
||||
@@ -97,14 +94,17 @@ your client documentation for further examples on how to achieve this.
|
||||
If you include the same capabilities both inside and outside of `appium:options`, the values
|
||||
inside of `appium:options` take precedence.
|
||||
|
||||
## Always-match and first-match capabilities
|
||||
## Always-Match and First-Match Capabilities
|
||||
|
||||
The W3C spec allows clients to give the Appium server some flexibility in the kind of session it
|
||||
creates in response to a new session request. This is through the concept of "always-match" and
|
||||
"first-match" capabilities:
|
||||
|
||||
- Always-match capabilities consist of a single set of capabilities, every member of which must be satisfied by the server in order for the new session request to proceed.
|
||||
- First-match capabilities consist of an array of capability sets. Each set is merged with the always-match capabilities, and the first set that the server knows how to handle will be the set that is used to start the session.
|
||||
- Always-match capabilities consist of a single set of capabilities, every member of which must
|
||||
be satisfied by the server in order for the new session request to proceed.
|
||||
- First-match capabilities consist of an array of capability sets. Each set is merged with the
|
||||
always-match capabilities, and the first set that the server knows how to handle will be the set
|
||||
that is used to start the session.
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -122,7 +122,7 @@ defined in the W3C spec, so if you use these features, Appium will work as expec
|
||||
defining always-match and first-match capabilities is unique to each client library, so refer to
|
||||
the documentation for your client library to see examples of how it works.
|
||||
|
||||
## Special notes for cloud providers
|
||||
## Special Notes for Cloud Providers
|
||||
|
||||
!!! warning
|
||||
|
||||
@@ -131,11 +131,10 @@ the documentation for your client library to see examples of how it works.
|
||||
|
||||
When managing an Appium cloud, your users may wish to target various independent versions of Appium
|
||||
drivers and plugins. It is of course up to each service provider how they wish to implement the
|
||||
discovery, installation, and availability of any official or third party drivers or plugins. _But
|
||||
the Appium team makes the following recommendations in terms of the *capabilities* service
|
||||
providers support, for consistency across the industry._ This is a recommendation only, and not
|
||||
a standard, but adopting it will help users to navigate the increased complexity that working with
|
||||
Appium 2.0 in a cloud environment may bring.
|
||||
discovery, installation, and availability of any official or third party drivers or plugins. But
|
||||
the Appium team does provide several suggestions, for consistency across the industry. _These are
|
||||
recommendations only,_ and not a standard, but adopting it will help users to navigate the increased
|
||||
complexity that working with Appium 2 in a cloud environment may bring.
|
||||
|
||||
### Suggested capabilities
|
||||
|
||||
@@ -146,12 +145,12 @@ vendor prefix (so for HeadSpin it would be `headspin`, Sauce Labs it would be `s
|
||||
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"}` |
|
||||
| `plugins` | Designating the list of plugins (and potentially versions of plugins) to be activated (see below for more info). | `["images", "universal-xml"]` |
|
||||
| <div style="width:10em">Capability</div> | Usage | Example |
|
||||
| ---------------------------------------- | ------ | ------- |
|
||||
| `version` | The version of the Appium server that is used to host and manage drivers. If omitted, the behavior is left up to the provider, but the recommendation would be to provide the latest official version. | `2.0.0` |
|
||||
| `automationVersion` | The version of the driver (as specified by `appium:automationName`) that should be used. | `1.55.2` |
|
||||
| `automation` | The name of 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"}` |
|
||||
| `plugins` | The list of plugins (and potentially versions of plugins) that should be activated (see below for more info). | `["images", "universal-xml"]` |
|
||||
|
||||
### Basic example
|
||||
|
||||
@@ -209,13 +208,17 @@ set of capabilities into the following:
|
||||
### Extension objects
|
||||
|
||||
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
|
||||
2 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. It is 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:
|
||||
@@ -253,10 +256,10 @@ requested:
|
||||
}
|
||||
```
|
||||
|
||||
These serve as illustrative examples for the recommendations here. Of course it is up to the
|
||||
These serve as illustrative examples for the recommendations here. Of course, it is up to the
|
||||
service providers to implement the handling of these capabilities at their front end / load
|
||||
balancer, to perform any error checking, or to actually run any of the `appium driver` or `appium
|
||||
plugin` CLI commands that support the end user's request. This section is merely a suggestion as to
|
||||
how service providers might design their user-facing capabilities API in a way which in principle
|
||||
supports all of the capabilities Appium itself would provide to the end user if they were running
|
||||
Appium on their own.
|
||||
supports all of the capabilities that Appium itself would provide to the end user if they were
|
||||
running Appium on their own.
|
||||
|
||||
@@ -34,7 +34,8 @@ discovered and loaded by Appium:
|
||||
- `appium.config.cjs`
|
||||
- `.appiumrc` (which is considered to be JSON)
|
||||
|
||||
Further, _if your project uses Node.js,_ you can use store the configuration inside an `appium` property in your `package.json` and it will be automatically discovered.
|
||||
Further, _if your project uses Node.js,_ you can use store the configuration inside an `appium`
|
||||
property in your `package.json` and it will be automatically discovered.
|
||||
|
||||
### Config File Search
|
||||
|
||||
@@ -57,9 +58,10 @@ A description of the format is available, as well:
|
||||
- [TypeScript declarations for Appium Configuration](https://github.com/appium/appium/blob/master/packages/types/lib/config.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 on the command-line 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.,:
|
||||
child properties. For certain properties which must be supplied on the command-line 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
|
||||
{
|
||||
@@ -91,5 +93,6 @@ and the values of any specific configuration it provides are under this. For exa
|
||||
|
||||
The above configuration corresponds to the `--driver-xcuitest-webkit-debug-proxy-port` CLI argument.
|
||||
|
||||
All properties are case-sensitive and will be in [kebab-case](https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-separated_words). For example, `callback-port` is
|
||||
allowed, but `callbackPort` is not.
|
||||
All properties are case-sensitive and will be in
|
||||
[kebab-case](https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-separated_words).
|
||||
For example, `callback-port` is allowed, but `callbackPort` is not.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
---
|
||||
title: The Context API
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Managing Contexts
|
||||
---
|
||||
|
||||
A common feature of many app platforms is the ability for developers to embed web content inside of
|
||||
@@ -16,7 +19,7 @@ basic commands that Appium has added to the W3C WebDriver spec for this purpose:
|
||||
|-----------------------|-----------------------------|-------------------|-----------------------------------------------|-----------------|
|
||||
| `Get Contexts` | `GET /session/:id/contexts` | | Get a list of the available contexts | `array<string>` |
|
||||
| `Get Current Context` | `GET /session/:id/context` | | Get the name of the active context | `string` |
|
||||
| `Set Context` | `POST /session/:id/context` | `name` (`string)` | Switch into the context with the given `name` | `null` |
|
||||
| `Set Context` | `POST /session/:id/context` | `name` (`string`) | Switch into the context with the given `name` | `null` |
|
||||
|
||||
This API is flexible enough to handle a variety of semantic interpretations on the part of the
|
||||
driver. For example, the XCUITest driver includes two kinds of contexts: the native app context and
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
---
|
||||
title: The Event Timing API
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Retrieving Event Timings
|
||||
---
|
||||
|
||||
Appium comes with the ability to retrieve timing information about startup
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Execute Methods
|
||||
---
|
||||
|
||||
@@ -15,7 +18,8 @@ by client libraries. There are two main strategies for this:
|
||||
There are pros and cons for each strategy, but it is ultimately up to the extension author to
|
||||
decide how they wish implement new commands.
|
||||
|
||||
This guide is designed to specifically help you understand the "Execute Method" strategy. This pattern is commonly used in official Appium drivers and other third-party extensions.
|
||||
This guide is designed to specifically help you understand the "Execute Method" strategy. This
|
||||
pattern is commonly used in official Appium drivers and other third-party extensions.
|
||||
Here's an example of how the `Execute Script` command is designed to work in the world of WebDriver
|
||||
and browser automation:
|
||||
|
||||
@@ -51,20 +55,23 @@ and browser automation:
|
||||
```
|
||||
|
||||
What's happening here is that we are defining a snippet of Javascript (technically,
|
||||
a function body) to be executed within the web browser. The client can send arguments which are serialized, sent over HTTP, and finally provided to the function as parameters. In this example, we are essentially defining
|
||||
an addition function. The return value of the `Execute Script` command is whatever the return value
|
||||
of the Javascript snippet is! In the case of this example, that value would be the number `7` (`3`
|
||||
+ `4`).
|
||||
a function body) to be executed within the web browser. The client can send arguments which are
|
||||
serialized, sent over HTTP, and finally provided to the function as parameters. In this example,
|
||||
we are essentially defining an addition function. The return value of the `Execute Script` command
|
||||
is whatever the return value of the Javascript snippet is! In the case of this example, that value
|
||||
would be the number `7` (`3` + `4`).
|
||||
|
||||
Each client library has its own way of calling the command and providing any arguments to the
|
||||
script function, but the function itself—the snippet—is always a string and is the same across all languages.
|
||||
Each client library has its own way of calling the command and providing any arguments to the script
|
||||
function, but the function itself—the snippet—is always a string and is the same across all languages.
|
||||
|
||||
In the world of Appium, we are usually not automating a web browser, which means this command is
|
||||
not particularly useful. But it *is* useful as a way to encode the name of an arbitrary command and
|
||||
to provide parameters. For example, the [XCUITest
|
||||
Driver](https://github.com/appium/appium-xcuitest-driver) has implemented a command that lets a client
|
||||
terminate a running application if you know the ID (the `bundleId`) of the app. The way that the
|
||||
driver makes this command available is via the Execute Method `mobile: terminateApp`. Instead of providing a JavaScript function to the "Execute Script" command, the user provides a _known string_ as defined by the driver. The only other thing a client needs to know is the set of
|
||||
driver makes this command available is via the Execute Method `mobile: terminateApp`. Instead of
|
||||
providing a JavaScript function to the "Execute Script" command, the user provides a _known string_
|
||||
as defined by the driver. The only other thing a client needs to know is the set of
|
||||
parameters for the method, which are documented by the driver. In this case, we have a parameter
|
||||
named `bundleId`, whose value should be a string encoding the ID of the app to terminate. Here is
|
||||
how this Execute Method would be called:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Log Filtering
|
||||
title: Filtering the Appium Log
|
||||
---
|
||||
|
||||
Sometimes it might be necessary to hide sensitive information, like passwords, device identifiers,
|
||||
@@ -18,8 +18,11 @@ Each rule is an object with a set of predefined properties. The following rule p
|
||||
supported:
|
||||
|
||||
- `pattern`: A valid Javascript RegExp pattern to replace. Must be a valid non-empty pattern.
|
||||
- `text`: A simple non-empty exact text match to replace. Either this property or the above one must be provided. `pattern` has priority over `text` if both are provided.
|
||||
- `flags`: Regular expression flags for the given pattern. Supported flags are the same as for the standard JavaScript [RegExp constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Advanced_searching_with_flags_2). Note that the `g` (global matching) flag is always enabled.
|
||||
- `text`: A simple non-empty exact text match to replace. Either this property or the above one must
|
||||
be provided. `pattern` has priority over `text` if both are provided.
|
||||
- `flags`: Regular expression flags for the given pattern. Supported flags are the same as for the
|
||||
standard JavaScript [RegExp constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Advanced_searching_with_flags_2).
|
||||
Note that the `g` (global matching) flag is always enabled.
|
||||
- `replacer`: The replacer value to use. By default it is `**SECURE**`. Empty values are allowed.
|
||||
|
||||
### Config Examples
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Managing Appium Drivers and Plugins
|
||||
title: Managing Drivers and Plugins
|
||||
---
|
||||
|
||||
To do anything useful with Appium, you need to have at least one [Driver](../intro/drivers.md)
|
||||
@@ -8,9 +8,11 @@ installed, otherwise Appium won't know how to automate anything. There is an ent
|
||||
|
||||
This guide helps explain how to manage these drivers and plugins. There are
|
||||
two basic strategies: using Appium's extension CLI interface, or managing extensions yourself in an
|
||||
npm-based project.
|
||||
`npm`-based project.
|
||||
|
||||
> Note: Alternative package managers are not supported by Appium at the time of this writing.
|
||||
!!! note
|
||||
|
||||
Other package managers are not currently supported.
|
||||
|
||||
## Using Appium's Extension CLI
|
||||
|
||||
@@ -22,7 +24,8 @@ or remove. Here's an example of how you might install a driver using the CLI:
|
||||
appium driver install xcuitest
|
||||
```
|
||||
|
||||
This command will install the latest version of the [XCUITest Driver](https://github.com/appium/appium-xcuitest-driver). The Extension CLI comes with a variety
|
||||
This command will install the latest version of the
|
||||
[XCUITest Driver](https://github.com/appium/appium-xcuitest-driver). The Extension CLI comes with a variety
|
||||
of commands and parameters; see the documentation for that command for all the specifics.
|
||||
|
||||
The all-important question when Appium is managing your extensions for you is: where are they installed?
|
||||
@@ -53,17 +56,18 @@ These installed packages will be managed by `extensions.yaml` in `$APPIUM_HOME/n
|
||||
## Do-It-Yourself with `npm`
|
||||
|
||||
Because Appium and Appium drivers are Node.js programs, if you are integrating your Appium scripts
|
||||
into your own Node.js project, there is an alternative way to manage drivers and plugins: via `npm`, like any other dependency.
|
||||
Basically, whenever you run Appium, if you have not explicitly set `APPIUM_HOME`, it will:
|
||||
into your own Node.js project, there is an alternative way to manage drivers and plugins: via `npm`,
|
||||
like any other dependency. Basically, whenever you run Appium, if you have not explicitly set
|
||||
`APPIUM_HOME`, it will:
|
||||
|
||||
1. Try to determine whether the _current directory_ is inside an `npm` package.
|
||||
1. If so, it will check whether `appium` is a dependency (dev, prod, or peer) in the project's
|
||||
`package.json`
|
||||
1. If so, _unless you have specified `APPIUM_HOME` in your environment_, Appium will ignore load drivers and plugins defined in that
|
||||
`package.json` file instead.
|
||||
1. If so, _unless you have specified `APPIUM_HOME` in your environment_, Appium will ignore load
|
||||
drivers and plugins defined in that `package.json` file instead.
|
||||
|
||||
This means you are freely able to add Appium drivers and plugins as regular package dependencies or dev dependencies. For
|
||||
example, if your project has a `package.json` which includes the following:
|
||||
This means you are freely able to add Appium drivers and plugins as regular package dependencies or
|
||||
dev dependencies. For example, if your project has a `package.json` which includes the following:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
---
|
||||
title: Migrating from Appium 1.x to Appium 2.x
|
||||
title: Migrating to Appium 2
|
||||
---
|
||||
|
||||
This document is a guide for those who are using Appium 1.x and wish to migrate to Appium 2.x. It contains a list of breaking changes and how to migrate your environments or test suites to ensure compatibility with Appium 2.0.
|
||||
This document is a guide for those who are using Appium 1 and wish to migrate to Appium 2. It
|
||||
contains a list of breaking changes and how to migrate your environments or test suites to ensure
|
||||
compatibility with Appium 2.
|
||||
|
||||
## Overview of Appium 2.0
|
||||
## Overview of Appium 2
|
||||
|
||||
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 is the most major new release of Appium in over 5 years. The changes in Appium 2 are _not_
|
||||
primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2
|
||||
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.
|
||||
At the same time, the Appium project is taking the opportunity to remove many old and deprecated
|
||||
bits of functionality.
|
||||
|
||||
Together these do introduce a few breaking changes to how Appium is installed, how drivers and various features are managed, and protocol support. These are detailed below.
|
||||
Together these do introduce a few breaking changes to how Appium is installed, how drivers and
|
||||
various features are managed, and protocol support. These are detailed below.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
Here we call out the breaking changes and what you need to do to account for them.
|
||||
|
||||
### :bangbang: Default server base path
|
||||
|
||||
With Appium 1.x, the server would accept commands by default on `http://localhost:4723/wd/hub`. The
|
||||
With Appium 1, the server would accept commands by default on `http://localhost:4723/wd/hub`. The
|
||||
`/wd/hub` base path was a legacy convention from the days of migrating from Selenium 1 to Selenium
|
||||
2, and is no longer relevant. As such the default base path for the server is now `/`. If you want
|
||||
to retain the old behaviour, you can set the base path via a command line argument as follows:
|
||||
@@ -31,40 +37,51 @@ You can also set server arguments as [Config file](./config.md) properties.
|
||||
|
||||
### :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 --location=global appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
||||
When you installed Appium 1, 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 (e.g., by `npm i -g appium`),
|
||||
will install the Appium server only, but no drivers. To install drivers, you must instead use the
|
||||
new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the
|
||||
XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
||||
|
||||
```bash
|
||||
appium driver install uiautomator2 # installs the latest driver version
|
||||
appium driver install xcuitest@4.12.2 # installs a specific driver version
|
||||
```
|
||||
|
||||
At this point, your drivers are installed and ready. There's a lot more you can do with this CLI so be sure to check out the docs on it.
|
||||
If you're running in a CI environment or want to install Appium along with some drivers all in one step, you can do so using some special flags during install, for example:
|
||||
At this point, your drivers are installed and ready. There's a lot more you can do with the Appium 2
|
||||
command line, so be sure to check out [its documentation](../cli/index.md). If you're running in a CI
|
||||
environment or want to install Appium along with some drivers all in one step, you can do so using
|
||||
some special flags during install, for example:
|
||||
|
||||
```bash
|
||||
npm install --location=global appium --drivers=xcuitest,uiautomator2
|
||||
npm i -g appium --drivers=xcuitest,uiautomator2
|
||||
```
|
||||
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with `npm uninstall --location=global appium`) if you get an installation or startup error.
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1
|
||||
`npm` packages (with `npm uninstall -g appium`) if you get an installation or startup error.
|
||||
|
||||
### :bangbang: Drivers installation path
|
||||
|
||||
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server.
|
||||
The path was `/path/to/appium/node_modules`.
|
||||
For example, `appium-webdriveragent` to build WebDriverAgent manually was `/path/to/appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent`.
|
||||
When you installed Appium 1, all available drivers would be installed at the same time as the main
|
||||
Appium server, at `/path/to/appium/node_modules`. For example, `appium-webdriveragent` was located
|
||||
at `/path/to/appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent`.
|
||||
|
||||
Appium 2.0 installs such dependencies in `APPIUM_HOME` environment variable. The default path is `~/.appium`.
|
||||
So, the path to `appium-webdriveragent` could be `$APPIUM_HOME/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent` after installing the XCUITest driver package.
|
||||
Appium 2 installs such dependencies in the path defined by the `APPIUM_HOME` environment variable.
|
||||
The default path is `~/.appium`. So, `appium-webdriveragent` would now be located at
|
||||
`$APPIUM_HOME/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent`.
|
||||
|
||||
### :bangbang: Chromedriver installation flags
|
||||
|
||||
In Appium 1.x it was possible to customize the way Chromedriver was installed (as part of the UiAutomator2 driver for example), using the following command line flags:
|
||||
In Appium 1, it was possible to customize the way Chromedriver was installed (as part of the
|
||||
UiAutomator2 driver for example), using the following command line flags:
|
||||
|
||||
* `--chromedriver-skip-install`
|
||||
* `--chromedriver-version`
|
||||
* `--chromedriver-cdnurl`
|
||||
|
||||
Because Appium 2.0 now installs drivers for you, and because these flags were implemented as NPM config flags, they will no longer work. Instead, use the following environment variables during driver installation:
|
||||
Because Appium 2 now installs drivers for you, and because these flags were implemented as `npm`
|
||||
config flags, they will no longer work. Instead, use the following environment variables during
|
||||
driver installation:
|
||||
|
||||
* `APPIUM_SKIP_CHROMEDRIVER_INSTALL`
|
||||
* `CHROMEDRIVER_VERSION`
|
||||
@@ -78,16 +95,23 @@ APPIUM_SKIP_CHROMEDRIVER_INSTALL=1 appium driver install uiautomator2
|
||||
|
||||
### :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 1, 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 the corresponding functionality, you'll need to refer to the driver/plugin documentation. In some cases, the extension will continue to expose CLI parameters. For example, the XCUITest driver used to expose a parameter `--webdriveragent-port`. Now, to access this parameter, it should be prefixed with `driver-xcuitest`, to differentiate it from parameters other drivers might also expose. To use this parameter, you thus need to start Appium with something like:
|
||||
With Appium 2, all driver- and platform-specific CLI params have been moved to the drivers themselves.
|
||||
To access the corresponding functionality, you'll need to refer to the driver/plugin documentation.
|
||||
In some cases, the extension will continue to expose CLI parameters. For example, the XCUITest driver
|
||||
used to expose a parameter `--webdriveragent-port`. Now, to access this parameter, it should be
|
||||
prefixed with `driver-xcuitest`, to differentiate it from parameters other drivers might also expose.
|
||||
To use this parameter, you thus need to start Appium with something like:
|
||||
|
||||
```bash
|
||||
appium --driver-xcuitest-webdriveragent-port=5000
|
||||
```
|
||||
|
||||
Some drivers have done away with CLI args entirely in favour of default capabilities instead. With
|
||||
the above-mentioned `--chromedriver-executable` param for example, you now need to take advantage
|
||||
Some drivers have done away with CLI args entirely in favour of default capabilities. With the
|
||||
above-mentioned `--chromedriver-executable` parameter for example, you now need to take advantage
|
||||
of the `appium:chromedriverExecutable` capability supported by the UiAutomator2 driver. To set this
|
||||
capability from the command line, do the following:
|
||||
|
||||
@@ -107,7 +131,11 @@ main Appium server will not define the route corresponding to the command.
|
||||
|
||||
### :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:
|
||||
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, the
|
||||
Appium server and the Appium drivers are versioned and released separately. This means that drivers
|
||||
can be on their own release cadence, and you can get the latest driver version right away, 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
|
||||
@@ -119,12 +147,15 @@ If any updates are available, you can then run the `update` command for any give
|
||||
appium driver update xcuitest
|
||||
```
|
||||
|
||||
(For a complete description of the update command, check out the [Extension
|
||||
CLI](../cli/extensions.md) doc)
|
||||
(For a complete description of the update command, check out the
|
||||
[Extension CLI](../cli/extensions.md#update) documentation)
|
||||
|
||||
To update the Appium server itself, you do the same thing as in the past: `npm install --location=global appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
|
||||
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.
|
||||
|
||||
If you would like to update to a specific version, not the latest, please uninstall the driver and install the desired version using the `install` subcommand instead of `update`.
|
||||
If you would like to update to a specific driver version, not the latest, please uninstall the driver
|
||||
and install the desired version using the `install` subcommand instead of `update`.
|
||||
|
||||
```bash
|
||||
appium driver uninstall xcuitest
|
||||
@@ -133,25 +164,45 @@ appium driver install xcuitest@4.11.1
|
||||
|
||||
### :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 "MJSONWP" (Mobile JSON Wire Protocol). The W3C Protocol differs from the (M)JSONWP protocols in a few small ways.
|
||||
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 "MJSONWP" (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.
|
||||
Up until Appium 2, Appium supported both protocols, so that older Selenium/Appium clients could
|
||||
still communicate with newer Appium servers. Appium 2 removes support for older protocols and is
|
||||
now only compatible with the W3C WebDriver Protocol.
|
||||
|
||||
### :bangbang: _Capabilities_
|
||||
### :bangbang: Capabilities must use vendor prefix
|
||||
|
||||
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`.
|
||||
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:
|
||||
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`
|
||||
|
||||
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 (at least one maintained by the Appium team), the client will add the `appium:` prefix for you on all necessary capabilities automatically. New versions of [Appium Inspector](https://github.com/appium/appium-inspector) 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.
|
||||
This requirement may or may not be a breaking change for your test suites when targeting Appium 2.
|
||||
If you're using an updated Appium client (at least one maintained by the Appium team), the client
|
||||
will add the `appium:` prefix for you on all necessary capabilities automatically. New versions of
|
||||
[Appium Inspector](https://github.com/appium/appium-inspector) 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.
|
||||
|
||||
On a related note, it will no longer be possible to start Appium sessions using WebDriver clients that don't support the W3C protocol (see below for a comment to this effect for the WD library).
|
||||
|
||||
To make everyone's lives a bit easier, we've also introduced the option of wrapping up all Appium-related capabilities into one object capability, `appium:options`. You can bundle together anything that you would normally put an `appium:` prefix on into this one capability. Here's an example (in raw JSON) of how you might start an iOS session on the Safari browser using `appium:options`:
|
||||
To make everyone's lives a bit easier, we've also introduced the option of grouping up all
|
||||
Appium-related capabilities into one object capability, `appium:options`. You can bundle together
|
||||
anything that you would normally put an `appium:` prefix on into this one capability. Here's an
|
||||
example (in raw JSON) of how you might start an iOS session on the Safari browser using `appium:options`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -165,101 +216,145 @@ 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. (The new `appium:options` syntax support by cloud providers may vary.)
|
||||
(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`).
|
||||
|
||||
For more information on capabilities, have a look at the [Capabilities Guide](caps.md).
|
||||
!!! note
|
||||
|
||||
### :bangbang: _Removed Commands_
|
||||
Capabilities included in the `appium:options` object will overwrite capabilities of the same
|
||||
name that are used outside of this object. (The `appium:options` syntax support by cloud
|
||||
providers may vary.)
|
||||
|
||||
In addition to commands which have been moved to driver implementations, commands which were a part of the old JSON Wire Protocol and not a part of the W3C Protocol are no longer available:
|
||||
For more information on capabilities, have a look at the [Capabilities Guide](./caps.md).
|
||||
|
||||
### :bangbang: Removed Commands
|
||||
|
||||
In addition to commands which have been moved to driver implementations, 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)
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](../ecosystem/index.md). 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/tree/master/packages/images-plugin).
|
||||
One of the design goals for Appium 2 is to migrate non-core features into special extensions called
|
||||
[plugins](../ecosystem/plugins.md). 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/tree/master/packages/images-plugin).
|
||||
|
||||
If you use these image-related methods, to continue accessing them you will need to do two things.
|
||||
If you use these image-related methods, to continue accessing them you will need to do two things:
|
||||
|
||||
1. Install the plugin: `appium plugin install images`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=images`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of
|
||||
plugins designated on the command line, e.g., `appium --use-plugins=images`
|
||||
|
||||
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.
|
||||
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: Execute Driver Script command moved to plugin
|
||||
|
||||
If you use the advanced Execute Driver Script feature (which allows you to send in a WebdriverIO script to have it executed completely on the server instead of command-by-command from the client), this functionality has been moved to a plugin. Here's what to do to keep using it:
|
||||
If you use the advanced Execute Driver Script feature (which allows you to send in a WebdriverIO
|
||||
script to have it executed completely on the server instead of command-by-command from the client),
|
||||
this functionality has been moved to a plugin. Here's what to do to keep using it:
|
||||
|
||||
1. Install the plugin: `appium plugin install execute-driver`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=execute-driver`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of
|
||||
plugins designated on the command line, e.g., `appium --use-plugins=execute-driver`
|
||||
|
||||
### :bangbang: External Files No Longer Supported for `--nodeconfig`, `--default-capabilities`, `--allow-insecure` and `--deny-insecure`
|
||||
|
||||
These options can be provided as strings on the command line (a JSON string for `--nodeconfig` and a comma-separated list of strings for `--allow-insecure` and `--deny-insecure`). Arguments provided on the command line will likely need to be quoted or escaped.
|
||||
These options can be provided as strings on the command line (a JSON string for `--nodeconfig` and
|
||||
a comma-separated list of strings for `--allow-insecure` and `--deny-insecure`). Arguments provided
|
||||
on the command line will likely need to be quoted or escaped.
|
||||
|
||||
The recommended method to provide these options is now via a [configuration file](#tada-configuration-files).
|
||||
The recommended method to provide these options is through a [configuration file](./config.md).
|
||||
|
||||
In summary, if you are using a JSON Appium config file, you can simply cut-and-paste the contents of your "nodeconfig" JSON file into the value of the `server.nodeconfig` property. Any CSV-like files you had previously provided for `--allow-insecure` and `--deny-insecure` become the values of the `server.allow-insecure` and `server.deny-insecure` properties in the Appium config files (respectively); both are arrays of strings.
|
||||
In summary, if you are using a JSON Appium config file, you can simply cut-and-paste the contents
|
||||
of your "nodeconfig" JSON file into the value of the `server.nodeconfig` property. Any CSV-like
|
||||
files you had previously provided for `--allow-insecure` and `--deny-insecure` become the values
|
||||
of the `server.allow-insecure` and `server.deny-insecure` properties in the Appium config files
|
||||
(respectively); both are arrays of strings.
|
||||
|
||||
### :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.
|
||||
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.
|
||||
|
||||
### :bangbang: Server can no longer be started with `--port 0`
|
||||
|
||||
In Appium 1.x, it was possible to specify `--port 0` during server startup. This had the effect of
|
||||
starting Appium on a random free port. In Appium 2.0, port values must be `1` or higher. The random
|
||||
port assignment was never an intentional feature of Appium 1.x, but a consequence of how Node's
|
||||
HTTP servers work and the fact that there was no port input validation in Appium 1.x. If you want
|
||||
In Appium 1, it was possible to specify `--port 0` during server startup. This had the effect of
|
||||
starting Appium on a random free port. In Appium 2, port values must be `1` or higher. The random
|
||||
port assignment was never an intentional feature of Appium 1, but a consequence of how Node's
|
||||
HTTP servers work and the fact that there was no port input validation in Appium 1. If you want
|
||||
to find a random free port to start Appium on, you must now take care of this on your own prior to
|
||||
starting Appium. Starting Appium on an explicit and known port is the correct practice moving
|
||||
forward.
|
||||
|
||||
### :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.
|
||||
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).
|
||||
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 Desktop replaced with Appium Inspector
|
||||
|
||||
The inspector functionality of Appium Desktop has been moved to its own app: [Appium Inspector](https://github.com/appium/appium-inspector). It's fully compatible with standalone Appium 2.0 servers, but also works with later versions of Appium 1.x servers. Appium Desktop itself has been deprecated and is not compatible with Appium 2.0.
|
||||
The inspector functionality of Appium Desktop has been moved to its own app:
|
||||
[Appium Inspector](https://github.com/appium/appium-inspector). It is fully compatible with
|
||||
standalone Appium 2 servers, but also works with later versions of Appium 1 servers. Appium Desktop
|
||||
itself has been deprecated and is not compatible with Appium 2.
|
||||
|
||||
In addition to the app, Appium Inspector also has a browser version, accessible at https://inspector.appiumpro.com. Note that in order to use the browser version with a local Appium server, you'll need to first start the server with the `--allow-cors` flag.
|
||||
In addition to the app, Appium Inspector also has a browser version, accessible at
|
||||
[inspector.appiumpro.com](https://inspector.appiumpro.com). Note that in order to use the
|
||||
browser version with a local Appium server, you'll need to first start the server with the
|
||||
`--allow-cors` flag.
|
||||
|
||||
## Major New Features
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### Plugins
|
||||
|
||||
#### :tada: _Server Plugins_
|
||||
#### :tada: Server Plugins
|
||||
|
||||
Appium extension authors can now develop their own server plugins, which can intercept and modify
|
||||
any Appium command, or even adjust the way the underlying Appium HTTP server itself works. To learn
|
||||
more about plugins, read the new [Appium Introduction](../intro/index.md). Interested in building
|
||||
a plugin? Check out the [Building Plugins](../ecosystem/build-plugins.md) guide.
|
||||
a plugin? Check out the [Building Plugins](../developing/build-plugins.md) guide.
|
||||
|
||||
### :tada: Install drivers and plugins from anywhere
|
||||
|
||||
You're no longer limited to the drivers that come with Appium, or that the Appium team even knows
|
||||
about! Appium extension authors can now develop custom drivers, which can be downloaded or
|
||||
installed via Appium's [Extension CLI](../cli/extensions.md) from NPM, Git, GitHub, or even the
|
||||
installed via Appium's [Extension CLI](../cli/extensions.md) from `npm`, `git`, GitHub, or even the
|
||||
local filesystem. Interested in building a driver? Check out the [Building
|
||||
Drivers](../ecosystem/build-drivers.md) guide.
|
||||
Drivers](../developing/build-drivers.md) guide.
|
||||
|
||||
### :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. See the [Config Guide](config.md) for a full explanation.
|
||||
Appium now supports _configuration files_ in addition to command-line arguments. In a nutshell,
|
||||
nearly all arguments which Appium 1 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. See the
|
||||
[Config Guide](./config.md) for a full explanation.
|
||||
|
||||
## 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.
|
||||
The rest of this document has applied to Appium generally, but some of the architectural changes in
|
||||
Appium 2 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.
|
||||
|
||||
We encourage cloud providers to thoroughly read and understand our [recommendation for cloud
|
||||
provider capabilities](caps.md#special-notes-for-cloud-providers) in order to support user needs in
|
||||
provider capabilities](./caps.md#special-notes-for-cloud-providers) in order to support user needs in
|
||||
an industry-compatible way!
|
||||
|
||||
@@ -15,7 +15,7 @@ But because many Appium users might not be able to guarantee such a safe environ
|
||||
team puts many features behind a security protection mechanism which forces system admins (the
|
||||
people that are in charge of starting the Appium server) to _explicitly opt-in_ to these features.
|
||||
(Third-party driver and plugin authors can also [hide behaviour behind security
|
||||
flags](../ecosystem/build-drivers.md).)
|
||||
flags](../developing/build-drivers.md).)
|
||||
|
||||
For security reasons, Appium client sessions can _not_ request feature enablement via capabilities;
|
||||
this is the responsibility of the server admin who configures and launches the Appium server.
|
||||
@@ -25,11 +25,11 @@ this is the responsibility of the server admin who configures and launches the A
|
||||
The [Server CLI Args](../cli/args.md) doc outlines three relevant arguments which may be passed to
|
||||
Appium when starting it from the command line:
|
||||
|
||||
|Parameter|Description|
|
||||
|----|----|
|
||||
|`--relaxed-security`|Setting this flag turns on _all_ insecure features (unless blocked by `--deny-insecure`; see below)|
|
||||
|`--allow-insecure`|Setting this flag to a comma-separated list of feature names or a path to a file containing a feature list (each name on a separate line) will allow _only_ the features listed. For example, `--allow-insecure=adb_shell` will cause _only_ the ADB shell execution feature to be enabled. This is true _unless_ `--relaxed-security` is also used, in which case all features will still be enabled. It makes no sense to combine this flag with `--relaxed-security`.|
|
||||
|`--deny-insecure`|This flag can likewise be set to a comma-separated list of feature names, or a path to a feature file. Any features listed here will be _disabled_, regardless of whether `--relaxed-security` is set and regardless of whether the names are also listed with `--allow-insecure`.|
|
||||
|<div style="width:10em">Parameter</div>|Description|
|
||||
|---------------------------------------|-----------|
|
||||
|`--relaxed-security` |Setting this flag turns on _all_ insecure features (unless blocked by `--deny-insecure`; see below)|
|
||||
|`--allow-insecure` |Setting this flag to a comma-separated list of feature names or a path to a file containing a feature list (each name on a separate line) will allow _only_ the features listed. For example, `--allow-insecure=adb_shell` will cause _only_ the ADB shell execution feature to be enabled. This is true _unless_ `--relaxed-security` is also used, in which case all features will still be enabled. It makes no sense to combine this flag with `--relaxed-security`.|
|
||||
|`--deny-insecure` |This flag can likewise be set to a comma-separated list of feature names, or a path to a feature file. Any features listed here will be _disabled_, regardless of whether `--relaxed-security` is set and regardless of whether the names are also listed with `--allow-insecure`.|
|
||||
|
||||
## Insecure Features
|
||||
|
||||
@@ -37,7 +37,7 @@ Each Appium driver is responsible for its own security, and can create its own f
|
||||
you should read through the documentation for a particular driver to know which feature names it
|
||||
might use. Here is an incomplete list of examples from some of Appium's official drivers:
|
||||
|
||||
|Feature Name|Description|Supported Extension(s)|
|
||||
|<div style="width:12em">Feature Name</div>|Description|Supported Extension(s)|
|
||||
|------------|-----------|-------|
|
||||
|`get_server_logs`|Allows retrieving of Appium server logs via the Webdriver log interface|IOS, XCUITest, Android, UiAutomator2, Espresso|
|
||||
|`adb_shell`|Allows execution of arbitrary shell commands via ADB, using the `mobile: shell` command|Android, UiAutomator2, Espresso|
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
---
|
||||
title: The Settings API
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Session Settings
|
||||
---
|
||||
|
||||
Appium has introduced a set of extension APIs that allow you to adjust parameters for a given
|
||||
session during session execution. Called "Settings", these parameters mirror the role of
|
||||
[Capabilities](./caps.md), but Capabilities cannot be adjusted once a session has started. Settings
|
||||
can be adjusted any number of times during the course of a session.
|
||||
Appium has a set of extension APIs that allow you to adjust parameters for a given session during
|
||||
the session itself. Called "Settings", these parameters are similar to [Capabilities](./caps.md),
|
||||
but while Capabilities _cannot be adjusted_ once a session has started, Settings _can be adjusted any
|
||||
number of times_ during the course of a session.
|
||||
|
||||
There are 3 important points to the concept of Settings:
|
||||
- Settings are mutable; they can be changed during a session using the Settings API
|
||||
- Settings are only relevant during the session in which they are set. They are typically reset for each new session, though depending on the driver, some settings may persist between sessions.
|
||||
- Settings adjust the way the appium server behaves during test automation. They don't refer to settings for the device or app under test
|
||||
|
||||
An example of a setting would be the `ignoreUnimportantViews` setting recognized by the
|
||||
UiAutomator2 driver. The driver can be instructed to ignore lements in the view hierarchy which it
|
||||
deems irrelevant. Adjusting this setting to have a value of `true` can cause tests to run faster.
|
||||
But if you *want* to access elements which would be ignored under this setting, you could always
|
||||
reset it to `false` later in the session.
|
||||
- Settings are mutable; they can be changed during a session using the Settings API
|
||||
- Settings are only relevant during the session in which they are set. They are typically reset for
|
||||
each new session, though depending on the driver, some settings may persist between sessions
|
||||
- Settings only adjust the way the Appium server behaves during test automation. They do not affect
|
||||
the device or app under test
|
||||
|
||||
An example of a setting would be the `ignoreUnimportantViews` setting recognized by the UiAutomator2
|
||||
driver. The driver can be instructed to ignore elements in the view hierarchy which it deems
|
||||
irrelevant. Changing this setting to `true` can cause tests to run faster. But if later in the same
|
||||
session you _want_ to access elements which would be ignored under this setting, you can always
|
||||
change it back to `false`.
|
||||
|
||||
Settings are implemented via the following API endpoints:
|
||||
|
||||
| Command | Method/Route | Params | Description | Returns |
|
||||
|-------------------|-------------------------------------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|
|
||||
| `Update Settings` | `POST /session/:id/appium/settings` | `settings` (`Record<string, any>`) | Update setting values. The `settings` object needs to be a set of keys and values, where keys are the name of the settings and values are whatever value is documented as appropriate for that setting. | `null` |
|
||||
| `Get Settings` | `GET /session/:id/appium/settings` | | Return the current settings. | `Record<string, any>` |
|
||||
| Command | <div style="width:18em">Method/Route</div> | Params | Description | Returns |
|
||||
|-------------------|---------------------------------------------|------------------------------------|------------------------------------|------------------------------------|
|
||||
| `Update Settings` | `POST /session/:id/appium/settings` | `settings` (`Record<string, any>`) | Update the provided setting values | `null` |
|
||||
| `Get Settings` | `GET /session/:id/appium/settings` | | Return the current settings | `settings` (`Record<string, any>`) |
|
||||
|
||||
Which settings are available depends on the driver you are using. Refer to the driver's
|
||||
documentation for a list of supported settings.
|
||||
The `settings` object must be a set of keys and values, where the key is the setting name, and the
|
||||
value is any documented valid value for that setting.
|
||||
|
||||
!!! info
|
||||
|
||||
Settings are driver-specific, so refer to your driver's documentation for a list of supported settings
|
||||
|
||||
## Initializing Settings via Capabilities
|
||||
|
||||
When you want to start an Appium session with a setting in a certain state, you can do so by
|
||||
If you want to start an Appium session with a setting in a non-default state, you can do so by
|
||||
including a capability of the form `appium:settings[<name>]` with the appropriate value. So to turn
|
||||
on the `ignoreUnimportantViews` setting mentioned above from the very beginning of a session, you
|
||||
would construct a set of capabilities that includes the following in its JSON representation:
|
||||
@@ -41,8 +51,8 @@ would construct a set of capabilities that includes the following in its JSON re
|
||||
}
|
||||
```
|
||||
|
||||
Also, since base-driver version 9.4.0, there is a possibility to provide multiple settings
|
||||
in a single `appium:settings` capability value:
|
||||
Also, since Appium 2.1, there is a possibility to provide multiple settings in a single
|
||||
`appium:settings` capability value:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -55,4 +65,4 @@ in a single `appium:settings` capability value:
|
||||
|
||||
Of course, initializing a setting via capabilities doesn't prevent you from changing it later on
|
||||
via the Settings API. To learn more about how to use the Settings API in the context of your
|
||||
specific client library, visit the documentation for that library.
|
||||
specific client library, visit the documentation for that client.
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
---
|
||||
title: Starting the Server with SSL/TLS/SPDY support
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: SSL/TLS/SPDY Support
|
||||
---
|
||||
|
||||
Appium 2.2 introduces the option to start the Appium server with SSL/TLS support.
|
||||
|
||||
## Command Line Arguments
|
||||
In order to enable secure connections to the server, you need to provide the following command
|
||||
line arguments:
|
||||
|
||||
Since version 2.2 of the server there is a possibility to start it with SSL/TLS support. In order to enable secure connections to the server you need to provide the following command line arguments:
|
||||
|
||||
```bashs
|
||||
```bash
|
||||
appium server --ssl-cert-path=/path/to/cert.pem --ssl-key-path=/path/to/key.pem
|
||||
```
|
||||
|
||||
Both arguments must be provided and should contain paths to a valid [X509 PEM](https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions/) certificate and its corresponding private key.
|
||||
Both arguments must be provided and should contain paths to a valid
|
||||
[X509 PEM](https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions/)
|
||||
certificate and its corresponding private key.
|
||||
|
||||
After the server is started use the `https` protocol and a client supporting SSL/TLS or [SPDY](https://en.wikipedia.org/wiki/SPDY) to communicate to it.
|
||||
After the server is started use the `https` protocol and a client supporting SSL/TLS or
|
||||
[SPDY](https://en.wikipedia.org/wiki/SPDY) to communicate to it.
|
||||
|
||||
### Supported Features
|
||||
|
||||
Once a secure server socket is established it supports the following protocols: `['h2', 'spdy/3.1', 'spdy/3', 'spdy/2', 'http/1.1', 'http/1.0']`. See [the SPDY node module documentation](https://www.npmjs.com/package/spdy) to get more details about its features. All insecure client connections will be rejected by the server.
|
||||
Once a secure server socket is established it supports the following protocols:
|
||||
`['h2', 'spdy/3.1', 'spdy/3', 'spdy/2', 'http/1.1', 'http/1.0']`. See
|
||||
[the SPDY node module documentation](https://www.npmjs.com/package/spdy) to get more details about
|
||||
its features. All insecure client connections will be rejected by the server.
|
||||
|
||||
### Self-Signed Certificates
|
||||
|
||||
@@ -26,4 +37,6 @@ Use the following command in order to generate a self-signed certificate/key pai
|
||||
openssl req -nodes -new -x509 -keyout key.pem -out cert.pem -subj "/C=US/ST=State/L=City/O=company/OU=Com/CN=www.testserver.local"
|
||||
```
|
||||
|
||||
Feel free to change the value of `-subj` in the command above with your matching details. The server should work just fine with a self-signed certificate, although you need to take care about a proper client setup, e.g. make sure it does not reject unauthorized certificates.
|
||||
Feel free to change the value of `-subj` in the command above with your matching details. The server
|
||||
should work just fine with a self-signed certificate, although you need to take care about a proper
|
||||
client setup, e.g. make sure it does not reject unauthorized certificates.
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
---
|
||||
title: Appium Documentation
|
||||
hide:
|
||||
- navigation
|
||||
- toc
|
||||
|
||||
title: Welcome
|
||||
---
|
||||
|
||||
# Appium Documentation
|
||||
|
||||
<style>
|
||||
.md-typeset h1 {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<div style="text-align: center">
|
||||
<img src="assets/images/appium-logo-horiz.png" style="max-width: 400px;" />
|
||||
</div>
|
||||
@@ -11,51 +17,20 @@ title: Appium Documentation
|
||||
Welcome to the Appium documentation! Appium is an open-source project and ecosystem of related
|
||||
software, designed to facilitate UI automation of many app platforms, including mobile (iOS,
|
||||
Android, Tizen), browser (Chrome, Firefox, Safari), desktop (macOS, Windows), TV (Roku, tvOS,
|
||||
Android TV, Samsung), and more.
|
||||
Android TV, Samsung), and more!
|
||||
|
||||
If you're new to Appium, it's recommended that you start off with the [Introduction](intro/), then
|
||||
move on to the [Quickstart](quickstart/). And you can always find Appium's code on GitHub at
|
||||
[appium/appium](https://github.com/appium/appium).
|
||||
## Explore the Documentation
|
||||
|
||||
## What is Appium for?
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
Appium is used mostly in the field of software test automation, to help determine whether the
|
||||
functionality of a given app is working as expected. In contrast to other types of software
|
||||
testing, UI automation allows testers to write code that walks through user scenarios in the actual
|
||||
UI of an application, mimicking as closely as possible what happens in the real world while
|
||||
enabling the various benefits of automation, including speed, scale, and consistency.
|
||||
- Check out the [__Introduction__](./intro/index.md) to make sure you understand the key concepts
|
||||
- Go through the [__Quickstart__](./quickstart/index.md) to get set up and run a basic Android test
|
||||
- Visit the [__Ecosystem__](./ecosystem/index.md) page for a list of drivers, clients and plugins you may want to use
|
||||
- Refer to the [__CLI Reference__](./cli/index.md) for using Appium from the command line
|
||||
- See the [__Command Reference__](./commands/index.md) for a list of commands exposed by Appium and plugins
|
||||
- Read the different [__Guides__](./guides/migrating-1-to-2.md) for a variety of instructions, tips and tricks
|
||||
- Check out various third-party [__Resources__](./resources.md) to explore Appium around the web
|
||||
- For creating your own Appium extensions, see the [__Developer__](./developing/index.md) documentation
|
||||
- For contributions to Appium itself, refer to the [__Contributing__](./contributing/index.md) page
|
||||
|
||||
Appium aims to provide a set of tools that support this kind of automation in a standard way across
|
||||
any number of platforms. Most platforms come with tools that allow UI automation at some level, but
|
||||
these are usually platform-specific and require specialized knowledge and specific programming
|
||||
language experience and toolchains. Appium tries to unify all these automation technology under
|
||||
a single stable interface, accessible via most popular programming languages (you can write Appium
|
||||
scripts in Java, Python, Ruby, JS, and more).
|
||||
|
||||
To learn more about how Appium accomplishes this goal, and the various components involved, have
|
||||
a read through our [Introduction](intro/).
|
||||
|
||||
## Learning Appium
|
||||
|
||||
This documentation is a great way to learn more about Appium:
|
||||
|
||||
- Check out the [Introduction](intro/) first to make sure you understand all the concepts involved in Appium.
|
||||
- Go through the [Quickstart](quickstart/) to get set up and run a basic Android test.
|
||||
- Have a look at the various guides and references.
|
||||
- Using Appium for a real project means using an Appium driver for a specific platform, so you'll want to have a look at the [Ecosystem](ecosystem/) page where we keep links to the drivers and plugins you might want to use; you can refer to those projects for specific information about using Appium for a given platform.
|
||||
|
||||
You can also check out a list of third-party [Resources](resources.md) to explore Appium around the
|
||||
web.
|
||||
|
||||
## Contributing to Appium
|
||||
|
||||
Appium is open source, available under an Apache 2.0 license. Appium's copyright is held by the
|
||||
[OpenJS Foundation](https://openjsf.org), and Appium receives contributions from many companies
|
||||
across several software industries, regardless of their competitive status. (3rd-party drivers and
|
||||
plugins are available under the licenses provided by their authors.)
|
||||
|
||||
As such, we welcome contributions! The project moves forward in relation to the investment of
|
||||
contributions of code, documentation, maintenance, and support from companies and volunteers. To
|
||||
learn more about contributing, check out our GitHub repo at
|
||||
[appium/appium](https://github.com/appium/appium) and read through our
|
||||
[Contributing](contributing/) guides.
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
---
|
||||
title: How Does Appium Work?
|
||||
---
|
||||
|
||||
As mentioned on the main page, Appium is an open-source project and ecosystem of related software,
|
||||
designed to facilitate UI automation of many app platforms. With the release of Appium 2, Appium
|
||||
has the following primary goals:[^1]
|
||||
|
||||
- Make platform-specific automation capabilities available under a cross-platform, standard API
|
||||
- Allow easy access to this API from any programming language
|
||||
- Provide tools to enable convenient community development of Appium extensions
|
||||
|
||||
[^1]:
|
||||
To meet these primary goals, we also work with a set of secondary goals or methodology
|
||||
principles, which we also encourage for Appium extension developers:
|
||||
|
||||
- As far as possible, rely on (and contribute to) open source technology
|
||||
- As far as possible, rely on vendor-provided tools for a given platform
|
||||
- As far as possible, rely on automation tools that allow automation of unmodified apps (prefer
|
||||
not to require the user to build in additional SDKs or software that introduce discrepancies
|
||||
between the test version of the app and the production version)
|
||||
- As far as possible, rely on existing standards instead of creating new ones
|
||||
|
||||
So, take any app platform you know about, like iOS or Android. Appium wants for there to be a way
|
||||
for developers and testers to write UI automation code for that platform, according to a single,
|
||||
unified API. Based on Appium's goals, we have a lot of questions to answer to make it all work:
|
||||
|
||||
- Which API should that "single, unified" API be?
|
||||
- How do we map that API to automation behaviour for a specific platform?
|
||||
- How do we make that API accessible via multiple popular programming languages?
|
||||
|
||||
There's another, larger, question lurking in the background here too, given that there are more app
|
||||
platforms out there than just iOS and Android:
|
||||
|
||||
- How do we enable automation for *all* the platforms?
|
||||
|
||||
Exploring Appium's answers to these questions may not be the quickest way to learn what Appium is,
|
||||
but it is certainly a good one! So let's dive in.
|
||||
|
||||
## Appium's choice of API
|
||||
|
||||
Appium is very fortunate to have been preceded by a technology which has been a long-standing
|
||||
pioneer in the field of UI automation, namely [Selenium](https://seleniumhq.org). The goal of the
|
||||
Selenium project has been to support UI automation of web browsers, and in this way we can think of
|
||||
it as occupying a subset of Appium's goals. Along the way, Selenium (and, after they merged,
|
||||
another project called WebDriver) developed a relatively stable API for browser automation.
|
||||
|
||||
Over the years, Selenium worked with various web browser vendors and the [W3C](https://w3c.org)
|
||||
standards group to turn its API into an official web browser standard, called the [WebDriver
|
||||
specification](https://w3c.github.io/webdriver/webdriver-spec.html). All the main browsers now
|
||||
implement automation capabilities inline with the WebDriver spec, without the Selenium team having
|
||||
to maintain any software that performs actual automation; standards for the win!
|
||||
|
||||
Appium's initial goals were to develop an automation standard for mobile apps (iOS and Android). We
|
||||
could have made up something new, but in the spirit of joining forces and keeping standards, well,
|
||||
standard, we decided to adopt the WebDriver spec as Appium's API.[^2] While user interaction on
|
||||
websites and in mobile native apps are not entirely identical (with even greater differences once
|
||||
we start to consider, for example, TV platforms controlled by simple remotes), the fact is that
|
||||
most software UIs are pretty much the same. This means that the WebDriver spec provides automation
|
||||
API primitives (finding elements, interacting with elements, loading pages or screens, etc...) that
|
||||
more or less map to any platform.
|
||||
|
||||
[^2]: Technically, when Appium was first written, we were dealing with something older than the
|
||||
WebDriver spec, called the JSON Wire Protocol. Since then, Appium continued to evolve along with
|
||||
the W3C spec and is fully W3C-compliant.
|
||||
|
||||
Of course, Appium wants to support the cases where user interaction *does* differ from web to
|
||||
mobile or web to TV, and so Appium also makes use of the built-in *extensibility* of the WebDriver
|
||||
spec. The result is that, no matter what platform you want to automate, when you use Appium, you
|
||||
will do so using the standard WebDriver spec, with two caveats:
|
||||
|
||||
- We might not have any way to support a particular WebDriver API command on a given platform, and
|
||||
so some commands might be unsupported (for example, getting or setting cookies is not possible in
|
||||
the world of native mobile app automation).
|
||||
- We might support automation behaviours that go *beyond* what's available in the WebDriver API
|
||||
command list, though any such commands will be valid and spec-compliant extensions to the
|
||||
WebDriver API.
|
||||
|
||||
How do you actually *use* the WebDriver API, particularly in the context of Appium? We'll cover
|
||||
that in the [section below](#universal-programming-language-access) on how Appium provides
|
||||
universal programming language access. All you need to know for now is that the way Appium
|
||||
introduces a universal UI automation interface is by implementing the WebDriver protocol.
|
||||
|
||||
## Platform automation behaviour
|
||||
|
||||
The next question is, how does Appium map this protocol to automation behaviour on a wide range of
|
||||
platforms? The trick is that, strictly speaking, Appium doesn't! It leaves this responsibility up
|
||||
to a kind of software module called an Appium *driver*. There's a whole [Driver
|
||||
Introduction](./drivers.md) which you can read next, so we won't go into huge detail on how they
|
||||
work for now.
|
||||
|
||||
What's important to understand at the moment is that a driver is kind of like a pluggable module
|
||||
for Appium that gives Appium the power to automate a particular platform (or set of platforms,
|
||||
depending on the goal of the driver). At the end of the day, a driver's responsibility is to simply
|
||||
implement an Appium-internal interface representing the WebDriver protocol. How it implements this
|
||||
interface is totally up to the driver, based on its strategy for making automation happen on
|
||||
a specific platform. Typically, and with a lot more complexity and difficulty in the details,
|
||||
a driver does this by relying on platform-specific automation technologies. For example, Apple
|
||||
maintains an iOS automation technology called
|
||||
[XCUITest](https://developer.apple.com/documentation/xctest/user_interface_tests). The Appium
|
||||
driver that supports iOS app automation is called the [XCUITest
|
||||
Driver](https://github.com/appium/appium-xcuitest-driver) because ultimately what it does is
|
||||
convert the WebDriver protocol to XCUITest library calls.
|
||||
|
||||
One of the reasons that drivers are independent, pluggable modules is that they work completely
|
||||
differently from one another. The tools and requirements for building and using drivers for
|
||||
different platforms are completely different. And so Appium lets you use just the drivers that you
|
||||
need for your automation tasks. Choosing drivers and installing them so that you can use them with
|
||||
your Appium instance is so important that Appium has its very own [CLI for managing
|
||||
drivers](../cli/extensions.md).
|
||||
|
||||
So, to answer our original question, the way that Appium provides access to automation capabilities
|
||||
for a given platform is that the Appium team (or anyone else[^3]) writes a *driver* for that
|
||||
platform, implementing as much or little of the WebDriver protocol as desired. The driver can then
|
||||
be installed by anyone using Appium.
|
||||
|
||||
[^3]: You can build and share your own drivers! Check out [Building
|
||||
Drivers](../developing/build-drivers.md) to learn more about how to develop drivers in Node.js
|
||||
that can be used with Appium.
|
||||
|
||||
## Universal programming language access
|
||||
|
||||
But what does it mean, or look like, to *use* Appium, anyway? Since Appium is ultimately a Node.js
|
||||
program, it *could* have looked like importing Appium and its drivers as libraries into your own
|
||||
Node.js programs. But that wouldn't meet Appium's goal of providing automation capabilities to
|
||||
people using any popular programming language.
|
||||
|
||||
Luckily, the fact that Appium rode in on Selenium's coattails meant that we had a solution to this
|
||||
problem from day one. You see, the WebDriver specification is actually an HTTP-based protocol,
|
||||
meaning it is designed to be used over a network rather than within the memory of a single program.
|
||||
|
||||
One of the main benefits of this "client-server" architecture is that it allows the automation
|
||||
implementer (the thing doing the automation, in this case the 'server') to be completely distinct
|
||||
from the automation runner (the thing defining what automation should be done, in what steps,
|
||||
etc..., in this case the 'client'). Basically, all the "hard stuff" (actually figuring out how to
|
||||
make automation happen on a given platform) can be handled in one place by the server, and "thin"
|
||||
client libraries can be written in any programming language which simply encode HTTP requests to
|
||||
the server in language-appropriate way. It's possible, in other words, to bring basic Appium
|
||||
/ WebDriver capabilities to a new programming language relatively easily, assuming high-level HTTP
|
||||
libraries exist, simply by coding up a basic HTTP client in that language.
|
||||
|
||||
There are a couple important takeaways here for you, the Appium user:
|
||||
|
||||
- Appium is an *HTTP server*. It must run as a process on some computer for as long as you want to
|
||||
be able to use it for automation. It must be accessible on the network to whichever computer you
|
||||
want to use to run the automation from (whether that is the same machine or one across the
|
||||
world).
|
||||
- Unless you want to write raw HTTP calls or use cURL, using Appium for automation involves the use
|
||||
of an [Appium Client](clients.md) in the language of your choice. The goal of each of these
|
||||
clients is to encapsulate the WebDriver protocol so that rather than worrying about the protocol
|
||||
itself, you can work with objects and methods that feel idiomatic for your language.
|
||||
- The Appium server and the Appium client do *not* need to be running on the same computer. You
|
||||
simply need to be able to send HTTP requests from the client to the server over some network.
|
||||
This greatly facilitates the use of cloud providers for Appium, since they can host the Appium
|
||||
server and any related drivers and devices, and all you need to do is point your client script to
|
||||
their secure endpoints.
|
||||
|
||||
And of course, none of this is about "testing" per se, purely about the use of Appium and its
|
||||
client libraries for automation purposes. If you want to do automation for the purpose of
|
||||
"testing", you'll likely want to enlist the help of test runners, test frameworks, and the like,
|
||||
none of which need be related to Appium; one of the benefits of Appium's "universal accessibility"
|
||||
is that it plays well with whatever set of tools you find most beneficial for your situation.
|
||||
|
||||
## Appium's huge scope
|
||||
|
||||
Appium's vision (automation of everything under a single API) is huge! Certainly, much bigger than
|
||||
the team of core maintainers for the open source project. So how does Appium hope to achieve this
|
||||
goal? Basically, by empowering the community to develop functionality on top of Appium as
|
||||
a *platform*. This is what we call the Appium "ecosystem".
|
||||
|
||||
The Appium team does officially maintain a few drivers itself (for example, the XCUITest driver
|
||||
that we spoke about earlier). But it cannot hope to have the platform-specific expertise or the
|
||||
capacity to maintain drivers for many different platforms. But what we have done, particularly
|
||||
beginning with Appium 2, is to provide tools to empower the community to join in our vision:
|
||||
|
||||
- Anyone can create a driver simply by creating a Node.js module that conforms to the appropriate
|
||||
conventions and implements any (sub|super)set of the WebDriver protocol. Creating a driver often
|
||||
involves a minimal amount of code because the WebDriver protocol details are abstracted away, and
|
||||
many helper libraries are available---the same libraries that power the Appium team's own
|
||||
drivers.
|
||||
- Sharing drivers with others is easy using the Appium driver CLI. There is no central authority.
|
||||
Anyone can share drivers publicly or privately, for free or for sale. Drivers can be open or
|
||||
closed source (though obviously we appreciate open source!).
|
||||
|
||||
Appium's vision of being a platform for development extends beyond the support of automation for
|
||||
all app platforms. As a popular automation tool, there are many opportunities for integrating
|
||||
Appium with all kinds of other tools and services. In addition, there are many feature ideas for
|
||||
Appium, either as a core server or in its incarnation across various drivers, which the core team
|
||||
will never have time to build. And so, with Appium 2, Appium has released a plugin system that
|
||||
enables anyone to build and share modules that change how Appium works!
|
||||
|
||||
In the same way that drivers are easily shareable and consumable via the Appium driver CLI, plugins
|
||||
can be published and consumed via a parallel [Plugin CLI](../cli/extensions.md). Plugins can do all
|
||||
sorts of things, for example adding the ability for Appium to find and interact with screen regions
|
||||
based on a template image (as in the [`images`
|
||||
plugin](https://github.com/appium/appium/tree/master/packages/images-plugin)). There are very few
|
||||
limitations on what you can do with plugins, so you might also be interested in learning how to
|
||||
[Build Plugins](../developing/build-plugins.md) in Node.js that can be used with Appium.
|
||||
|
||||
So that's Appium: an extensible, universal interface for the UI automation of potentially
|
||||
everything! Read on into some of the specific intro docs for more details, or check out the various
|
||||
guides to dive into some more general concepts and features of Appium.
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Intro to Appium Clients
|
||||
---
|
||||
|
||||
For all the reasons discussed in the [main intro](./index.md), Appium is based on the [W3C
|
||||
For all the reasons discussed in the [main Overview](./appium.md), Appium is based on the [W3C
|
||||
WebDriver specification](https://w3c.github.io/webdriver/webdriver-spec.html). This means that
|
||||
Appium implements a client-server architecture. The server (consisting of Appium itself along with
|
||||
any drivers or plugins you are using for automation) is connected to the devices under test, and
|
||||
@@ -16,7 +19,7 @@ of the application. This document is a conceptual introduction to the client sid
|
||||
|
||||
For more about the server side of the equation (i.e., how does Appium actually control
|
||||
devices?), check out our [Intro to Appium Drivers](./drivers.md). To skip to a list of links to
|
||||
Appium client libraries, check out the [Ecosystem](../ecosystem/index.md) documentation.
|
||||
Appium client libraries, check out the [list of clients](../ecosystem/clients.md).
|
||||
|
||||
What sorts of automation commands are available? That is up to the particular driver and plugins
|
||||
that you are using in any given session. A standard set of commands would include, for example, the
|
||||
@@ -39,7 +42,7 @@ unique session ID generated by the server in a previous call to `Create Session`
|
||||
This information is primarily useful for people developing technology that works with the WebDriver
|
||||
spec. It's not particularly useful for people trying to write Appium or Selenium tests. When you
|
||||
write an Appium test, you want to use a programming language you're familiar with. Luckily, there
|
||||
exist a set of [Appium client libraries](../ecosystem/index.md)[^1] that take care of the
|
||||
exist a set of [Appium client libraries](../ecosystem/clients.md)[^1] that take care of the
|
||||
responsibility of speaking HTTP to the Appium server. Instead, they expose a set of "native"
|
||||
commands for a particular programming language, so that, to the test author, it just feels like
|
||||
you're writing Python, or JavaScript, or Java.
|
||||
@@ -118,7 +121,7 @@ added on top of the Selenium client. All that to say, for a full reference, you
|
||||
both the Appium client documentation as well as the Selenium client documentation.
|
||||
|
||||
That's all you need to know about Appium clients! Head over to the
|
||||
[Ecosystem](../ecosystem/index.md) page to check out the current list of clients.
|
||||
[Clients](../ecosystem/clients.md) page to check out the current list of clients.
|
||||
|
||||
[^1]: These libraries are alternately called "clients", "client libraries", or "client bindings".
|
||||
They all mean the same thing!
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Intro to Appium Drivers
|
||||
---
|
||||
|
||||
As the [main Overview](index.md) makes clear, "drivers" are basically Appium's answer to the
|
||||
As the [main Overview](./appium.md) makes clear, "drivers" are basically Appium's answer to the
|
||||
question, "how do we support automation of multiple, unrelated platforms?" In this doc we'll get
|
||||
into a little more detail about how drivers work. The specific details of how drivers work probably
|
||||
don't matter too much for you, unless you're planning on writing your own driver or contributing to
|
||||
@@ -50,7 +50,7 @@ async setUrl(url) {
|
||||
[^1]: You might notice that `setUrl` doesn't look anything like `Navigate To`, so how did we know
|
||||
to use it rather than some other random string? Well, Appium's WebDriver-protocol-to-method-name
|
||||
mapping is defined in a special file within the `@appium/base-driver` package called
|
||||
[routes.js](https://github.com/appium/appium/blob/2.0/packages/base-driver/lib/protocol/routes.js).
|
||||
[routes.js](https://github.com/appium/appium/blob/master/packages/base-driver/lib/protocol/routes.js).
|
||||
So if you're writing a driver, this is where you would go to figure out what method names to use
|
||||
and what parameters to expect. Or you could look at the source for any of the main Appium
|
||||
drivers!
|
||||
|
||||
@@ -177,6 +177,6 @@ is currently an Impact Project in the foundation.
|
||||
|
||||
## Appium 2.0
|
||||
|
||||
Appium 2.0 was released in 2022, with a new focus on Appium as an ecosystem rather than a singular
|
||||
Appium 2 was released in 2023, with a new focus on Appium as an ecosystem rather than a singular
|
||||
project. Drivers and plugins can be developed and shared by anyone, opening up a world of
|
||||
possibilities for automation-related development for platforms far beyond iOS and Android.
|
||||
|
||||
@@ -1,202 +1,39 @@
|
||||
---
|
||||
title: Intro to Appium
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium in a Nutshell
|
||||
---
|
||||
|
||||
As mentioned on the main page, Appium is an open-source project and ecosystem of related software,
|
||||
designed to facilitate UI automation of many app platforms. With the release of Appium 2.0, Appium
|
||||
has the following primary goals:[^1]
|
||||
As mentioned on the main page, Appium aims to support UI automation of many _different platforms_
|
||||
(mobile, web, desktop, etc.). Not only that, but it also aims to support automation code written in
|
||||
_different languages_ (JS, Java, Python, etc.). Combining all of this functionality in a single
|
||||
program is a very daunting, if not impossible task!
|
||||
|
||||
- Make platform-specific automation capabilities available under a cross-platform, standard API
|
||||
- Allow easy access to this API from any programming language
|
||||
- Provide tools to enable convenient community development of Appium extensions
|
||||
In order to achieve this, Appium is effectively split into four parts:
|
||||
|
||||
[^1]:
|
||||
To meet these primary goals, we also work with a set of secondary goals or methodology
|
||||
principles, which we also encourage for Appium extension developers:
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- As far as possible, rely on (and contribute to) open source technology
|
||||
- As far as possible, rely on vendor-provided tools for a given platform
|
||||
- As far as possible, rely on automation tools that allow automation of unmodified apps (prefer
|
||||
not to require the user to build in additional SDKs or software that introduce discrepancies
|
||||
between the test version of the app and the production version)
|
||||
- As far as possible, rely on existing standards instead of creating new ones
|
||||
- :material-image-filter-center-focus-strong: __Appium Core__ - defines the core APIs
|
||||
- :material-car: __Drivers__ - implement connectivity to specific platforms
|
||||
- :octicons-code-16: __Clients__ - implement Appium's API in specific languages
|
||||
- :fontawesome-solid-plug: __Plugins__ - change or extend Appium's core functionality
|
||||
|
||||
So, take any app platform you know about, like iOS or Android. Appium wants for there to be a way
|
||||
for developers and testers to write UI automation code for that platform, according to a single,
|
||||
unified API. Based on Appium's goals, we have a lot of questions to answer to make it all work:
|
||||
</div>
|
||||
|
||||
- Which API should that "single, unified" API be?
|
||||
- How do we map that API to automation behaviour for a specific platform?
|
||||
- How do we make that API accessible via multiple popular programming languages?
|
||||
Therefore, in order to start automating something with Appium, you need to:
|
||||
|
||||
There's another, larger, question lurking in the background here too, given that there are more app
|
||||
platforms out there than just iOS and Android:
|
||||
- Install Appium itself
|
||||
- Install a driver for your target platform
|
||||
- Install a client library for your target programming language
|
||||
- (Optional) install one or more plugins
|
||||
|
||||
- How do we enable automation for *all* the platforms?
|
||||
These are the basics! If you are ready to jump in, proceed with the [Quickstart](../quickstart/index.md)!
|
||||
|
||||
Exploring Appium's answers to these questions may not be the quickest way to learn what Appium is,
|
||||
but it is certainly a good one! So let's dive in.
|
||||
If you wish to learn more details about how it all works, see these pages for background material:
|
||||
|
||||
## Appium's choice of API
|
||||
- [Appium Core](./appium.md)
|
||||
- [Appium Drivers](./drivers.md)
|
||||
- [Appium Clients](./clients.md)
|
||||
|
||||
Appium is very fortunate to have been preceded by a technology which has been a long-standing
|
||||
pioneer in the field of UI automation, namely [Selenium](https://seleniumhq.org). The goal of the
|
||||
Selenium project has been to support UI automation of web browsers, and in this way we can think of
|
||||
it as occupying a subset of Appium's goals. Along the way, Selenium (and, after they merged,
|
||||
another project called WebDriver) developed a relatively stable API for browser automation.
|
||||
|
||||
Over the years, Selenium worked with various web browser vendors and the [W3C](https://w3c.org)
|
||||
standards group to turn its API into an official web browser standard, called the [WebDriver
|
||||
specification](https://w3c.github.io/webdriver/webdriver-spec.html). All the main browsers now
|
||||
implement automation capabilities inline with the WebDriver spec, without the Selenium team having
|
||||
to maintain any software that performs actual automation; standards for the win!
|
||||
|
||||
Appium's initial goals were to develop an automation standard for mobile apps (iOS and Android). We
|
||||
could have made up something new, but in the spirit of joining forces and keeping standards, well,
|
||||
standard, we decided to adopt the WebDriver spec as Appium's API.[^2] While user interaction on
|
||||
websites and in mobile native apps are not entirely identical (with even greater differences once
|
||||
we start to consider, for example, TV platforms controlled by simple remotes), the fact is that
|
||||
most software UIs are pretty much the same. This means that the WebDriver spec provides automation
|
||||
API primitives (finding elements, interacting with elements, loading pages or screens, etc...) that
|
||||
more or less map to any platform.
|
||||
|
||||
[^2]: Technically, when Appium was first written, we were dealing with something older than the
|
||||
WebDriver spec, called the JSON Wire Protocol. Since then, Appium continued to evolve along with
|
||||
the W3C spec and is fully W3C-compliant.
|
||||
|
||||
Of course, Appium wants to support the cases where user interaction *does* differ from web to
|
||||
mobile or web to TV, and so Appium also makes use of the built-in *extensibility* of the WebDriver
|
||||
spec. The result is that, no matter what platform you want to automate, when you use Appium, you
|
||||
will do so using the standard WebDriver spec, with two caveats:
|
||||
|
||||
- We might not have any way to support a particular WebDriver API command on a given platform, and
|
||||
so some commands might be unsupported (for example, getting or setting cookies is not possible in
|
||||
the world of native mobile app automation).
|
||||
- We might support automation behaviours that go *beyond* what's available in the WebDriver API
|
||||
command list, though any such commands will be valid and spec-compliant extensions to the
|
||||
WebDriver API.
|
||||
|
||||
How do you actually *use* the WebDriver API, particularly in the context of Appium? We'll cover
|
||||
that in the [section below](#universal-programming-language-access) on how Appium provides
|
||||
universal programming language access. All you need to know for now is that the way Appium
|
||||
introduces a universal UI automation interface is by implementing the WebDriver protocol.
|
||||
|
||||
## Platform automation behaviour
|
||||
|
||||
The next question is, how does Appium map this protocol to automation behaviour on a wide range of
|
||||
platforms? The trick is that, strictly speaking, Appium doesn't! It leaves this responsibility up
|
||||
to a kind of software module called an Appium *driver*. There's a whole [Driver
|
||||
Introduction](./drivers.md) which you can read next, so we won't go into huge detail on how they
|
||||
work for now.
|
||||
|
||||
What's important to understand at the moment is that a driver is kind of like a pluggable module
|
||||
for Appium that gives Appium the power to automate a particular platform (or set of platforms,
|
||||
depending on the goal of the driver). At the end of the day, a driver's responsibility is to simply
|
||||
implement an Appium-internal interface representing the WebDriver protocol. How it implements this
|
||||
interface is totally up to the driver, based on its strategy for making automation happen on
|
||||
a specific platform. Typically, and with a lot more complexity and difficulty in the details,
|
||||
a driver does this by relying on platform-specific automation technologies. For example, Apple
|
||||
maintains an iOS automation technology called
|
||||
[XCUITest](https://developer.apple.com/documentation/xctest/user_interface_tests). The Appium
|
||||
driver that supports iOS app automation is called the [XCUITest
|
||||
Driver](https://github.com/appium/appium-xcuitest-driver) because ultimately what it does is
|
||||
convert the WebDriver protocol to XCUITest library calls.
|
||||
|
||||
One of the reasons that drivers are independent, pluggable modules is that they work completely
|
||||
differently from one another. The tools and requirements for building and using drivers for
|
||||
different platforms are completely different. And so Appium lets you use just the drivers that you
|
||||
need for your automation tasks. Choosing drivers and installing them so that you can use them with
|
||||
your Appium instance is so important that Appium has its very own [CLI for managing
|
||||
drivers](../cli/extensions.md).
|
||||
|
||||
So, to answer our original question, the way that Appium provides access to automation capabilities
|
||||
for a given platform is that the Appium team (or anyone else[^3]) writes a *driver* for that
|
||||
platform, implementing as much or little of the WebDriver protocol as desired. The driver can then
|
||||
be installed by anyone using Appium.
|
||||
|
||||
[^3]: You can build and share your own drivers! Check out [Building
|
||||
Drivers](../ecosystem/build-drivers.md) to learn more about how to develop drivers in Node.js
|
||||
that can be used with Appium.
|
||||
|
||||
## Universal programming language access
|
||||
|
||||
But what does it mean, or look like, to *use* Appium, anyway? Since Appium is ultimately a Node.js
|
||||
program, it *could* have looked like importing Appium and its drivers as libraries into your own
|
||||
Node.js programs. But that wouldn't meet Appium's goal of providing automation capabilities to
|
||||
people using any popular programming language.
|
||||
|
||||
Luckily, the fact that Appium rode in on Selenium's coattails meant that we had a solution to this
|
||||
problem from day one. You see, the WebDriver specification is actually an HTTP-based protocol,
|
||||
meaning it is designed to be used over a network rather than within the memory of a single program.
|
||||
|
||||
One of the main benefits of this "client-server" architecture is that it allows the automation
|
||||
implementer (the thing doing the automation, in this case the 'server') to be completely distinct
|
||||
from the automation runner (the thing defining what automation should be done, in what steps,
|
||||
etc..., in this case the 'client'). Basically, all the "hard stuff" (actually figuring out how to
|
||||
make automation happen on a given platform) can be handled in one place by the server, and "thin"
|
||||
client libraries can be written in any programming language which simply encode HTTP requests to
|
||||
the server in language-appropriate way. It's possible, in other words, to bring basic Appium
|
||||
/ WebDriver capabilities to a new programming language relatively easily, assuming high-level HTTP
|
||||
libraries exist, simply by coding up a basic HTTP client in that language.
|
||||
|
||||
There are a couple important takeaways here for you, the Appium user:
|
||||
|
||||
- Appium is an *HTTP server*. It must run as a process on some computer for as long as you want to
|
||||
be able to use it for automation. It must be accessible on the network to whichever computer you
|
||||
want to use to run the automation from (whether that is the same machine or one across the
|
||||
world).
|
||||
- Unless you want to write raw HTTP calls or use cURL, using Appium for automation involves the use
|
||||
of an [Appium Client](clients.md) in the language of your choice. The goal of each of these
|
||||
clients is to encapsulate the WebDriver protocol so that rather than worrying about the protocol
|
||||
itself, you can work with objects and methods that feel idiomatic for your language.
|
||||
- The Appium server and the Appium client do *not* need to be running on the same computer. You
|
||||
simply need to be able to send HTTP requests from the client to the server over some network.
|
||||
This greatly facilitates the use of cloud providers for Appium, since they can host the Appium
|
||||
server and any related drivers and devices, and all you need to do is point your client script to
|
||||
their secure endpoints.
|
||||
|
||||
And of course, none of this is about "testing" per se, purely about the use of Appium and its
|
||||
client libraries for automation purposes. If you want to do automation for the purpose of
|
||||
"testing", you'll likely want to enlist the help of test runners, test frameworks, and the like,
|
||||
none of which need be related to Appium; one of the benefits of Appium's "universal accessibility"
|
||||
is that it plays well with whatever set of tools you find most beneficial for your situation.
|
||||
|
||||
## Appium's huge scope
|
||||
|
||||
Appium's vision (automation of everything under a single API) is huge! Certainly, much bigger than
|
||||
the team of core maintainers for the open source project. So how does Appium hope to achieve this
|
||||
goal? Basically, by empowering the community to develop functionality on top of Appium as
|
||||
a *platform*. This is what we call the Appium "ecosystem".
|
||||
|
||||
The Appium team does officially maintain a few drivers itself (for example, the XCUITest driver
|
||||
that we spoke about earlier). But it cannot hope to have the platform-specific expertise or the
|
||||
capacity to maintain drivers for many different platforms. But what we have done, particularly
|
||||
beginning with Appium 2.0, is to provide tools to empower the community to join in our vision:
|
||||
|
||||
- Anyone can create a driver simply by creating a Node.js module that conforms to the appropriate
|
||||
conventions and implements any (sub|super)set of the WebDriver protocol. Creating a driver often
|
||||
involves a minimal amount of code because the WebDriver protocol details are abstracted away, and
|
||||
many helper libraries are available---the same libraries that power the Appium team's own
|
||||
drivers.
|
||||
- Sharing drivers with others is easy using the Appium driver CLI. There is no central authority.
|
||||
Anyone can share drivers publicly or privately, for free or for sale. Drivers can be open or
|
||||
closed source (though obviously we appreciate open source!).
|
||||
|
||||
Appium's vision of being a platform for development extends beyond the support of automation for
|
||||
all app platforms. As a popular automation tool, there are many opportunities for integrating
|
||||
Appium with all kinds of other tools and services. In addition, there are many feature ideas for
|
||||
Appium, either as a core server or in its incarnation across various drivers, which the core team
|
||||
will never have time to build. And so, with Appium 2.0, Appium has released a plugin system that
|
||||
enables anyone to build and share modules that change how Appium works!
|
||||
|
||||
In the same way that drivers are easily shareable and consumable via the Appium driver CLI, plugins
|
||||
can be published and consumed via a parallel [Plugin CLI](../cli/extensions.md). Plugins can do all
|
||||
sorts of things, for example adding the ability for Appium to find and interact with screen regions
|
||||
based on a template image (as in the [`images`
|
||||
plugin](https://github.com/appium/appium/tree/2.0/packages/images-plugin)). There are very few
|
||||
limitations on what you can do with plugins, so you might also be interested in learning how to
|
||||
[Build Plugins](../ecosystem/build-plugins.md) in Node.js that can be used with Appium.
|
||||
|
||||
So that's Appium: an extensible, universal interface for the UI automation of potentially
|
||||
everything! Read on into some of the specific intro docs for more details, or check out the various
|
||||
guides to dive into some more general concepts and features of Appium.
|
||||
Finally, to learn about the origins of Appium, check out the [Appium Project History](./history.md).
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Appium Requirements
|
||||
---
|
||||
|
||||
The basic requirements for the Appium server are:
|
||||
|
||||
* A macOS, Linux, or Windows operating system
|
||||
* [Node.js](https://nodejs.org) version in the [SemVer](https://semver.org) range `^14.17.0 || ^16.13.0 || >=18.0.0`
|
||||
* [NPM](https://npmjs.com) version >= 8 (NPM is usually bundled with Node.js, but can be upgraded
|
||||
independently)
|
||||
|
||||
By itself, Appium is relatively lightweight and doesn't have significant disk space or RAM
|
||||
requirements. It can even be run in resource-constrained environments like Raspberry Pi, so long as
|
||||
Node.js is available.
|
||||
|
||||
To use Appium to automate a particular platform, please refer to the documentation of the [Appium
|
||||
driver(s)](../ecosystem/index.md#drivers) for that platform for additional dependencies. It is
|
||||
almost universally the case that Appium drivers for a given platform will require the developer
|
||||
toolchain and SDKs for that platform to be available.
|
||||
@@ -1,9 +1,12 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Quickstart Intro
|
||||
---
|
||||
|
||||
Let's get up and running with Appium! To successfully use this quickstart, it's recommended that
|
||||
you first have read the [Introduction](../intro), so that you understand the concepts involved in
|
||||
you first have read the [Introduction](../intro/index.md), so that you understand the concepts involved in
|
||||
running Appium and writing Appium scripts.
|
||||
|
||||
The basic plan for this quickstart is as follows:
|
||||
@@ -11,14 +14,14 @@ The basic plan for this quickstart is as follows:
|
||||
1. Install Appium
|
||||
1. Install an Appium driver and its dependencies (we'll be using the [UiAutomator2
|
||||
driver](https://github.com/appium/appium-uiautomator2-driver) for these examples)
|
||||
1. Install an Appium client library in your language or choice (this guide contains options for
|
||||
JavaScript, Python, and Java, though [Appium clients](../ecosystem/index.md#clients) also exist in other language).
|
||||
1. Install an Appium client library in your language of choice (this guide contains options for
|
||||
JavaScript, Python, Java, Ruby, and .NET).
|
||||
1. Write and run a simple Appium automation script using a sample application
|
||||
|
||||
### Requirements
|
||||
|
||||
Before getting started, make sure your system satisfies the
|
||||
[requirements](../intro/requirements.md) for running the Appium server. Additional requirements
|
||||
[requirements](../quickstart/requirements.md) for running the Appium server. Additional requirements
|
||||
will be discussed in conjunction with installing the UiAutomator2 driver. The guide also assumes
|
||||
you have basic command line proficiency on your platform, for example being able to run commands, set
|
||||
and persist environment variables, etc...
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Install Appium
|
||||
---
|
||||
|
||||
Installing Appium is as easy as running a single NPM command:
|
||||
!!! info
|
||||
|
||||
Before installing, make sure to check the [System Requirements](./requirements.md).
|
||||
|
||||
You can install Appium globally using `npm`:
|
||||
|
||||
```bash
|
||||
npm i --location=global appium
|
||||
npm i -g appium
|
||||
```
|
||||
|
||||
This command installs Appium globally on your system so that you can access it from the command
|
||||
line simply by running the `appium` command. Go ahead and run it now:
|
||||
!!! note
|
||||
|
||||
Other package managers are not currently supported.
|
||||
|
||||
After installation, you should be able to run Appium from the command line:
|
||||
|
||||
```
|
||||
appium
|
||||
@@ -21,5 +31,5 @@ You should see some output that starts with a line like this:
|
||||
[Appium] Welcome to Appium v2.0.0
|
||||
```
|
||||
|
||||
That's it! If you get this kind of output, the Appium server is up and running. Go ahead and quit
|
||||
it (CTRL-C) and move on to the next step, where we'll install a driver for automating Android apps.
|
||||
That's it! If you see this, the Appium server is up and running. Go ahead and quit
|
||||
it (Ctrl-C) and move on to the [next step](./uiauto2-driver.md), where we'll install a driver for automating Android apps.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Next Steps
|
||||
---
|
||||
|
||||
@@ -6,12 +9,13 @@ Now that you've successfully set up your system for Android automation and run a
|
||||
you'll want to continue exploring this documentation. In particular, these are good guides and
|
||||
reference materials especially for beginners:
|
||||
|
||||
- The [Ecosystem](../ecosystem/index.md) page: browse the available drivers, clients, plugins, and tools
|
||||
- [Managing Appium Drivers and Plugins](../guides/managing-exts.md)
|
||||
- [Capabilities](../guides/caps.md)
|
||||
- The list of available [Drivers and Plugins](../ecosystem/index.md)
|
||||
- [Settings](../guides/settings.md)
|
||||
|
||||
You'll also find that the [Appium Inspector](https://github.com/appium/appium-inspector) is an
|
||||
indispensable tool for use in Appium test-writing, as it enables visual inspection of apps and
|
||||
indispensable tool for writing Appium tests, as it enables visual inspection of apps and
|
||||
helps you to discover element locators for use in your test scripts.
|
||||
|
||||
You might also take advantage of one of the many online Appium courses available to you.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: System Requirements
|
||||
---
|
||||
|
||||
The basic requirements for the Appium server are:
|
||||
|
||||
* A macOS, Linux, or Windows operating system
|
||||
* [Node.js](https://nodejs.org) version in the [SemVer](https://semver.org) range `^14.17.0 || ^16.13.0 || >=18.0.0`
|
||||
* [`npm`](https://npmjs.com) version `>=8` (`npm` is usually bundled with Node.js, but can be upgraded
|
||||
independently)
|
||||
|
||||
By itself, Appium is relatively lightweight and doesn't have significant disk space or RAM
|
||||
requirements. It can even be run in resource-constrained environments like Raspberry Pi, so long as
|
||||
Node.js is available.
|
||||
|
||||
### Driver Requirements
|
||||
|
||||
Drivers for automating specific platforms will likely have other requirements. Refer to the
|
||||
documentation of the [Appium driver(s)](../ecosystem/drivers.md) for that platform for additional
|
||||
dependencies. It is almost universally the case that Appium drivers for a given platform will
|
||||
require the developer toolchain and SDKs for that platform to be installed.
|
||||
|
||||
You may find it useful to use the `appium-doctor` tool for verifying if all driver requirements are
|
||||
installed. It can check the prerequisites for Android and iOS drivers.
|
||||
Learn more on its GitHub page: [Appium Doctor](https://github.com/appium/appium/tree/master/packages/doctor)
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
title: Write a Test (dotnet)
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (.NET)
|
||||
---
|
||||
|
||||
The [Appium dotnet Client](https://github.com/appium/dotnet-client/) is
|
||||
The [Appium .NET Client](https://github.com/appium/dotnet-client/) is
|
||||
an official Appium client in C#. This driver is an extension of the Selenium C# client. It has all the functionalities of the regular driver, but add Appium-specific methods on top of this. The driver is available on the public NuGet Gallery as [Appium.WebDriver](https://www.nuget.org/packages/Appium.WebDriver/).
|
||||
|
||||
Now, we get inside the directory and create a new [NUnit](https://nunit.org/) project. We will also add the references to the Appium.Net driver, and other dependencies.
|
||||
@@ -99,4 +102,4 @@ dotnet test
|
||||
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view in the emulator before the app closes again.
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some next steps to explore.
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (Java)
|
||||
---
|
||||
|
||||
@@ -16,3 +19,5 @@ article to learn more about the current driver class implementations.
|
||||
|
||||
Follow the [Usage Examples](https://github.com/appium/java-client#usage-examples) article in order understand
|
||||
how to invoke Java client features from your test framework.
|
||||
|
||||
Once you've managed to successfully run a test, you can read on for some [next steps](./next-steps.md) to explore.
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (JS)
|
||||
---
|
||||
|
||||
@@ -64,5 +67,5 @@ node test.js
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
|
||||
app closes again.
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some next steps to explore.
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (Python)
|
||||
---
|
||||
|
||||
@@ -48,4 +51,4 @@ python test.py
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
|
||||
app closes again.
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some next steps to explore.
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (Ruby)
|
||||
---
|
||||
|
||||
@@ -53,4 +56,4 @@ bundle exec ruby test.rb
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
|
||||
app closes again.
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some next steps to explore.
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
|
||||
@@ -17,39 +17,43 @@ documentation and bookmarking it, because it will be an invaluable reference dow
|
||||
|
||||
## Set up Android automation requirements
|
||||
|
||||
According to the driver, in addition to a working Appium server, we also need to do the following:
|
||||
According to the driver, in addition to a working Appium server, we also need to set up the following:
|
||||
|
||||
- Download [Android SDK platform tools](https://developer.android.com/studio/releases/platform-tools). You will probably want to download [Android Studio](https://developer.android.com/studio) and manage the SDK tools from within it for the easiest experience.
|
||||
- Set an environment variable pointing to the directory on disk where the Android tools are
|
||||
### Android SDK
|
||||
|
||||
- The easiest way to set up the Android SDK requirements is by downloading [Android Studio](https://developer.android.com/studio).
|
||||
We need to use its SDK manager (_Settings -> Appearance & Behavior -> System Settings -> Android SDK_)
|
||||
to download the following items:
|
||||
- Android SDK Platform (select whichever Android platform we want to automate, for example, API level 30)
|
||||
- Android SDK Platform-Tools
|
||||
- If you wish, you can also download these items without Android Studio:
|
||||
- Android SDK Platform can be downloaded using `sdkmanager` included in [Android command-line tools](https://developer.android.com/studio#command-line-tools-only)
|
||||
- [Android SDK Platform-Tools](https://developer.android.com/tools/releases/platform-tools)
|
||||
- Set up the `ANDROID_HOME` environment variable to point to the directory where the Android SDK is
|
||||
installed. You can usually find the path to this directory in the Android Studio SDK manager. It
|
||||
will contain the `platform-tools` and other directories. We need to define and persist the
|
||||
environment variable as `ANDROID_HOME`.
|
||||
- Use the Android SDK manager to download whichever Android platform we want to automate (for
|
||||
example, API level 30)
|
||||
will contain the `platform-tools` and other directories.
|
||||
|
||||
### Java JDK
|
||||
|
||||
- Install the Java JDK (for the most recent Android API levels, JDK 9 is required, otherwise JDK
|
||||
8 is required). It's easiest to use the [OpenJDK packages](https://openjdk.java.net/install/). Make
|
||||
sure you get the JDK and not the JRE.
|
||||
- When the JDK is installed, you'll need to find the path to the JDK home directory as it was
|
||||
installed on your system. This will be the directory that *contains* the `bin`, `include`, and
|
||||
other directories. The path must be persisted as an environment variable named `JAVA_HOME`, so that
|
||||
Appium can find the appropriate Java tooling that is required to work with the Android platform.
|
||||
- Use Android Studio to create and launch an Android Virtual Device (an AVD, otherwise known as an
|
||||
emulator). You may need to download the system images for the API level of the emulator you want to
|
||||
8 is required). You can download this from [Oracle](https://jdk.java.net/) or [Adoptium](https://adoptium.net/en-GB/temurin/releases/).
|
||||
Make sure you get the JDK and not the JRE.
|
||||
- Set up the `JAVA_HOME` environment variable to point to the JDK home directory. It will contain
|
||||
the `bin`, `include`, and other directories.
|
||||
|
||||
### Prepare the Device
|
||||
|
||||
- If using an emulator, use Android Studio to create and launch an Android Virtual Device (AVD).
|
||||
You may need to download the system images for the API level of the emulator you want to
|
||||
create. Using the AVD creation wizard in Android Studio is generally the easiest way to do all of
|
||||
this.
|
||||
|
||||
!!! note
|
||||
|
||||
You can also use a physical Android device, so long as it is configured for debugging and
|
||||
development
|
||||
|
||||
- If using a real device, you should [set it up for development and enable USB Debugging](https://developer.android.com/studio/debug/dev-options).
|
||||
- With the emulator or device connected, you can run `adb devices` (via the binary located at
|
||||
`$ANDROID_HOME/platform-tools/adb`) to verify that your device shows up as connected.
|
||||
|
||||
Once your device shows up as connected in ADB, and you've verified that the environment variables
|
||||
are set up correctly in the terminal context where you are going to run Appium, you should be good
|
||||
to go! If you ran into problems with any of these steps, refer to the driver documentation, or the
|
||||
various Android or Java documentation sites as necessary.
|
||||
Once your device shows up as connected in `adb`, and you've verified that the environment variables
|
||||
are set up correctly, you should be good to go! If you ran into problems with any of these steps,
|
||||
refer to the driver documentation, or the various Android or Java documentation sites as necessary.
|
||||
|
||||
Also, congratulations: whether or not you intended to, you now have the Android developer toolchain
|
||||
set up on your system, so you can get busy making Android apps if you want!
|
||||
@@ -81,10 +85,10 @@ session (in this case, `UiAutomator2`).
|
||||
|
||||
!!! note
|
||||
|
||||
In this quickstart we have used the Extension CLI to install the UiAutomator2 driver, but if you
|
||||
are incorporating Appium into a Node.js project, you might prefer to use NPM to manage Appium
|
||||
and its connected drivers. To learn more about this technique, visit the guide on [managing
|
||||
Appium extensions](../guides/managing-exts.md).
|
||||
In this quickstart we have used the [Extension CLI](../cli/extensions.md) to install the
|
||||
UiAutomator2 driver, but if you are incorporating Appium into a Node.js project, you might
|
||||
prefer to use `npm` to manage Appium and its connected drivers. To learn more about this
|
||||
technique, visit the guide on [managing Appium extensions](../guides/managing-exts.md).
|
||||
|
||||
Now, start the Appium server again (run `appium`), and you should see that the newly-installed
|
||||
driver is listed as available:
|
||||
@@ -95,5 +99,14 @@ driver is listed as available:
|
||||
```
|
||||
|
||||
With the Android setup complete and the UiAutomator2 driver installed, you're ready to write your
|
||||
first test! So pick the language you're most comfortable with under the quickstart menu and give it
|
||||
a shot.
|
||||
first test! Now select your preferred language and give it a shot:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-language-javascript: [__JavaScript__](./test-js.md)
|
||||
- :material-language-java: [__Java__](./test-java.md)
|
||||
- :material-language-python: [__Python__](./test-py.md)
|
||||
- :material-language-ruby: [__Ruby__](./test-rb.md)
|
||||
- :material-dot-net: [__.NET C#__](./test-dotnet.md)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
---
|
||||
hide:
|
||||
- navigation
|
||||
- toc
|
||||
|
||||
title: Additional Resources
|
||||
---
|
||||
|
||||
|
||||
@@ -78,10 +78,10 @@ You can also set server arguments as [Config file](./config.md) properties.
|
||||
### :bangbang: ドライバーのインストール
|
||||
|
||||
<!---
|
||||
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 --location=global appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
||||
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 i -g appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
||||
--->
|
||||
|
||||
Appium 1.xをインストールしたとき、全ての入手可能なドライバーは主となるAppiumサーバーと合わせてインストールされていました。Appium 2.0ではそうではありません。Appium 2.0のインストール(例えば `npm install --location=global appium`)は単にAppiumサーバーのみをインストールし、ドライバーはインストールしません。ドライバーをインストールするためには新しい[Appium拡張コマンドラインインタフェース(Appium extension CLI)](../cli/extensions.md)を使わなければいけません。例えば、最新のXCUITestとUiAutomator2ドライバーをインストールする場合、Appiumをインストールしたのちに次のコマンドを実行する必要があります。
|
||||
Appium 1.xをインストールしたとき、全ての入手可能なドライバーは主となるAppiumサーバーと合わせてインストールされていました。Appium 2.0ではそうではありません。Appium 2.0のインストール(例えば `npm i -g appium`)は単にAppiumサーバーのみをインストールし、ドライバーはインストールしません。ドライバーをインストールするためには新しい[Appium拡張コマンドラインインタフェース(Appium extension CLI)](../cli/extensions.md)を使わなければいけません。例えば、最新のXCUITestとUiAutomator2ドライバーをインストールする場合、Appiumをインストールしたのちに次のコマンドを実行する必要があります。
|
||||
|
||||
```bash
|
||||
appium driver install uiautomator2 # installs the latest driver version
|
||||
@@ -95,14 +95,14 @@ At this point, your drivers are installed and ready. There's a lot more you can
|
||||
これにより、ドライバーはインストールされ、利用可能になります。このCLIはいろいろな機能を提供しているので、CLIのドキュメントを確認してみてください。もしCI上であったり、いくつかのドライバーをAppiumと一緒にインストールしたい場合、以下のようなフラグを利用することで実現可能です。
|
||||
|
||||
```bash
|
||||
npm install --location=global appium --drivers=xcuitest,uiautomator2
|
||||
npm i -g appium --drivers=xcuitest,uiautomator2
|
||||
```
|
||||
|
||||
<!---
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with `npm uninstall --location=global appium`) if you get an installation or startup error.
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with `npm uninstall -g appium`) if you get an installation or startup error.
|
||||
--->
|
||||
|
||||
これはAppiumと2つのドライバーを一つのコマンドでインストールします。もしセットアップで何らかの問題が発生した場合、既存のAppium 1.xを`npm uninstall --location=global appium`で削除してみてください。
|
||||
これはAppiumと2つのドライバーを一つのコマンドでインストールします。もしセットアップで何らかの問題が発生した場合、既存のAppium 1.xを`npm uninstall -g appium`で削除してみてください。
|
||||
|
||||
### :bangbang: Drivers installation path
|
||||
|
||||
@@ -166,7 +166,7 @@ appium driver update xcuitest
|
||||
(For a complete description of the update command, check out the [Extension
|
||||
CLI](../cli/extensions.md) doc)
|
||||
|
||||
To update the Appium server itself, you do the same thing as in the past: `npm install --location=global appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
|
||||
To update the Appium server itself, you do the same thing as in the past: `npm i -g appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
|
||||
|
||||
If you would like to update to a specific version, not the latest, please uninstall the driver and install the desired version using the `install` subcommand instead of `update`.
|
||||
|
||||
@@ -223,7 +223,7 @@ If you use a modern Appium or Selenium client, you should no longer have access
|
||||
|
||||
### :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](../ecosystem/index.md). 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/tree/master/packages/images-plugin).
|
||||
One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](../ecosystem/plugins.md). 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/tree/master/packages/images-plugin).
|
||||
|
||||
If you use these image-related methods, to continue accessing them you will need to do two things.
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ theme:
|
||||
nav:
|
||||
- Welcome: index.md
|
||||
- Introduction:
|
||||
- Intro to Appium:
|
||||
- Overview of Appium: intro/index.md
|
||||
- intro/index.md
|
||||
- Background:
|
||||
- intro/appium.md
|
||||
- intro/drivers.md
|
||||
- intro/clients.md
|
||||
- intro/requirements.md
|
||||
- intro/history.md
|
||||
- intro/history.md
|
||||
- Quickstart:
|
||||
- quickstart/index.md
|
||||
- quickstart/requirements.md
|
||||
- quickstart/install.md
|
||||
- quickstart/uiauto2-driver.md
|
||||
- Write a Test:
|
||||
@@ -26,42 +27,48 @@ nav:
|
||||
- quickstart/test-rb.md
|
||||
- quickstart/test-dotnet.md
|
||||
- quickstart/next-steps.md
|
||||
- Ecosystem:
|
||||
- ecosystem/index.md
|
||||
- ecosystem/drivers.md
|
||||
- ecosystem/clients.md
|
||||
- ecosystem/plugins.md
|
||||
- ecosystem/tools.md
|
||||
- CLI Reference:
|
||||
- cli/index.md
|
||||
- cli/args.md
|
||||
- cli/env-vars.md
|
||||
- cli/extensions.md
|
||||
- Command Reference:
|
||||
- commands/index.md
|
||||
- commands/base-driver.md
|
||||
- commands/execute-driver-plugin.md
|
||||
- commands/images-plugin.md
|
||||
- commands/relaxed-caps-plugin.md
|
||||
- commands/universal-xml-plugin.md
|
||||
- Guides:
|
||||
- guides/migrating-1-to-2.md
|
||||
- guides/managing-exts.md
|
||||
- guides/config.md
|
||||
- guides/security.md
|
||||
- guides/caps.md
|
||||
- guides/context.md
|
||||
- guides/settings.md
|
||||
- guides/execute-methods.md
|
||||
- guides/event-timing.md
|
||||
- guides/log-filters.md
|
||||
- guides/grid.md
|
||||
- guides/caching.md
|
||||
- Developer Reference:
|
||||
- BaseDriver Commands: reference/commands/base-driver.md
|
||||
- FakeDriver Commands: reference/commands/fake-driver.md
|
||||
- Ecosystem:
|
||||
- ecosystem/index.md
|
||||
- Developing Appium Extensions:
|
||||
- ecosystem/build-drivers.md
|
||||
- ecosystem/build-plugins.md
|
||||
- ecosystem/build-docs.md
|
||||
- Migration:
|
||||
- guides/migrating-1-to-2.md
|
||||
- Server/Driver Configuration:
|
||||
- guides/managing-exts.md
|
||||
- guides/config.md
|
||||
- guides/security.md
|
||||
- guides/log-filters.md
|
||||
- guides/grid.md
|
||||
- guides/caching.md
|
||||
- guides/tls.md
|
||||
- Session Configuration:
|
||||
- guides/caps.md
|
||||
- guides/settings.md
|
||||
- guides/execute-methods.md
|
||||
- guides/context.md
|
||||
- guides/event-timing.md
|
||||
- More Resources: resources.md
|
||||
- Developing:
|
||||
- developing/index.md
|
||||
- developing/build-drivers.md
|
||||
- developing/build-plugins.md
|
||||
- developing/build-docs.md
|
||||
- Contributing:
|
||||
- contributing/index.md
|
||||
- contributing/develop.md
|
||||
- contributing/config-system.md
|
||||
- More Appium Resources: resources.md
|
||||
- Issues: https://github.com/appium/appium/issues
|
||||
- Reference:
|
||||
- reference/commands/base-driver.md
|
||||
- reference/commands/execute-driver-plugin.md
|
||||
- reference/commands/fake-driver.md
|
||||
- reference/commands/images-plugin.md
|
||||
- reference/commands/relaxed-caps-plugin.md
|
||||
- reference/commands/universal-xml-plugin.md
|
||||
|
||||
@@ -11,12 +11,11 @@ nav:
|
||||
- 導入:
|
||||
- Appiumについて:
|
||||
- Appiumの全体像: intro/index.md
|
||||
- Command Reference:
|
||||
- ../en/commands/base-driver.md
|
||||
- ../en/commands/execute-driver-plugin.md
|
||||
- ../en/commands/images-plugin.md
|
||||
- ../en/commands/relaxed-caps-plugin.md
|
||||
- ../en/commands/universal-xml-plugin.md
|
||||
- 手引き:
|
||||
- guides/migrating-1-to-2.md
|
||||
- Reference:
|
||||
- ../en/reference/commands/base-driver.md
|
||||
- ../en/reference/commands/execute-driver-plugin.md
|
||||
- ../en/reference/commands/fake-driver.md
|
||||
- ../en/reference/commands/images-plugin.md
|
||||
- ../en/reference/commands/relaxed-caps-plugin.md
|
||||
- ../en/reference/commands/universal-xml-plugin.md
|
||||
|
||||
@@ -24,10 +24,22 @@ nav:
|
||||
- quickstart/test-py.md
|
||||
- quickstart/test-java.md
|
||||
- quickstart/next-steps.md
|
||||
- 生态系统:
|
||||
- ecosystem/index.md
|
||||
- 开发 Appium 扩展:
|
||||
- ecosystem/build-drivers.md
|
||||
- ecosystem/build-plugins.md
|
||||
- ecosystem/build-docs.md
|
||||
- 命令行参考:
|
||||
- cli/index.md
|
||||
- cli/args.md
|
||||
- cli/extensions.md
|
||||
- Command Reference:
|
||||
- ../en/commands/base-driver.md
|
||||
- ../en/commands/execute-driver-plugin.md
|
||||
- ../en/commands/images-plugin.md
|
||||
- ../en/commands/relaxed-caps-plugin.md
|
||||
- ../en/commands/universal-xml-plugin.md
|
||||
- 指南:
|
||||
- guides/migrating-1-to-2.md
|
||||
- guides/managing-exts.md
|
||||
@@ -40,19 +52,5 @@ nav:
|
||||
- guides/event-timing.md
|
||||
- guides/log-filters.md
|
||||
- guides/grid.md
|
||||
- 生态系统:
|
||||
- ecosystem/index.md
|
||||
- 开发 Appium 扩展:
|
||||
- ecosystem/build-drivers.md
|
||||
- ecosystem/build-plugins.md
|
||||
- ecosystem/build-docs.md
|
||||
- 贡献: contributing/index.md
|
||||
- 更多 Appium 资源: resources.md
|
||||
- 问题: https://github.com/appium/appium/issues
|
||||
- Reference:
|
||||
- ../en/reference/commands/base-driver.md
|
||||
- ../en/reference/commands/execute-driver-plugin.md
|
||||
- ../en/reference/commands/fake-driver.md
|
||||
- ../en/reference/commands/images-plugin.md
|
||||
- ../en/reference/commands/relaxed-caps-plugin.md
|
||||
- ../en/reference/commands/universal-xml-plugin.md
|
||||
- 贡献: contributing/index.md
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||
/* eslint-disable promise/prefer-await-to-then */
|
||||
|
||||
const {buildReferenceDocs, deploy, updateNav, buildSite} = require('@appium/docutils');
|
||||
const {deploy, buildSite} = require('@appium/docutils');
|
||||
const {
|
||||
log,
|
||||
LANGS,
|
||||
@@ -36,11 +36,6 @@ async function main() {
|
||||
log.info(`Building Appium docs and committing to ${DOCS_BRANCH}`);
|
||||
|
||||
await copyAssets();
|
||||
await buildReferenceDocs();
|
||||
|
||||
for (const lang of LANGS) {
|
||||
await updateNav({mkdocsYml: path.join(DOCS_DIR, `mkdocs-${lang}.yml`)});
|
||||
}
|
||||
|
||||
const semVersion = semver.parse(version);
|
||||
if (!semVersion) {
|
||||
@@ -60,12 +55,11 @@ async function main() {
|
||||
await deploy({
|
||||
mkdocsYml: configFile,
|
||||
branch,
|
||||
prefix: path.join(basePrefix, lang),
|
||||
deployPrefix: path.join(basePrefix, lang),
|
||||
remote,
|
||||
deployVersion: majMinVer,
|
||||
push,
|
||||
alias: LATEST_ALIAS,
|
||||
rebase: true, // we always want to rebase if branch is out of sync
|
||||
message: `docs(appium): auto-build docs for appium@${majMinVer}, language ${lang}`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ Appium 的大多数capabilities都超出了标准的 W3C capabilities,
|
||||
### :bangbang: 图像分析功能移至插件
|
||||
|
||||
Appium 2.0 的设计目标之一是
|
||||
将非核心功能迁移到名为 [plugins](../ecosystem/index.md)的特殊扩展中.
|
||||
将非核心功能迁移到名为 [plugins](../ecosystem/plugins.md)的特殊扩展中.
|
||||
这允许人们选择使用额外时间来下载或扩展系统设置的功能.
|
||||
Appium的各种图像相关功能 (图像比较, 按图像查找元素等) 已被移动到一个名为 [images](https://github.com/appium/appium/tree/master/packages/images-plugin)的官方支持的插件中.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ WebDriver 规范](https://w3c.github.io/webdriver/webdriver-spec.html).
|
||||
|
||||
有关服务端的更多信息(例如, Appium如何实际控制设备?) ,
|
||||
可以查看我们的[Appium驱动简介](./drivers.md).
|
||||
要跳到Appium客户端的链接列表, 请查看[生态系统](../ecosystem/index.md) 文档
|
||||
要跳到Appium客户端的链接列表, 请查看[生态系统](../ecosystem/clients.md) 文档
|
||||
|
||||
有哪些类型的自动化命令可用?
|
||||
这取决于您在任何给定会话中使用的特定的驱动程序和插件.
|
||||
@@ -43,7 +43,7 @@ WebDriver 规范](https://w3c.github.io/webdriver/webdriver-spec.html).
|
||||
对于试图编写Appium或Selenium测试的人来说,
|
||||
它不是特别有用. 当你编写一个Appium测试时,
|
||||
你想使用你熟悉的编程语言.
|
||||
幸运的是存在一组[Appium客户端库](../ecosystem/index.md)[^1],
|
||||
幸运的是存在一组[Appium客户端库](../ecosystem/clients.md)[^1],
|
||||
用于处理负责向Appium服务器发送HTTP请求.
|
||||
相反, 它们为特定编程语言公开了一组 "原生" 命令,
|
||||
因此, 对于测试作者来说, 感觉就像是在编写Python、JavaScript或Java.
|
||||
@@ -127,6 +127,6 @@ WebDriver 规范](https://w3c.github.io/webdriver/webdriver-spec.html).
|
||||
您可能需要访问Appium客户端文档以及Selenium客户端文档.
|
||||
|
||||
这就是您需要了解的关于Appium客户端的所有信息!
|
||||
转到[生态系统](../ecosystem/index.md) 页面查看当前的客户端列表.
|
||||
转到[生态系统](../ecosystem/clients.md) 页面查看当前的客户端列表.
|
||||
|
||||
[^1]: 这些库又称为 "客户端"、"客户端库" 或 "客户端绑定". 他们是同一种概念!
|
||||
|
||||
@@ -299,7 +299,7 @@ class AppiumDriver extends DriverCore {
|
||||
driver: InnerDriver,
|
||||
version: driverVersion,
|
||||
driverName,
|
||||
} = this.driverConfig.findMatchingDriver(desiredCaps);
|
||||
} = await this.driverConfig.findMatchingDriver(desiredCaps);
|
||||
this.printNewSessionAnnouncement(InnerDriver.name, driverVersion, InnerDriver.baseVersion);
|
||||
|
||||
if (this.args.sessionOverride) {
|
||||
|
||||
@@ -735,9 +735,18 @@ class ExtensionCliCommand {
|
||||
);
|
||||
}
|
||||
|
||||
const scriptPath = extScripts[scriptName];
|
||||
const moduleRoot = this.config.getInstallPath(installSpec);
|
||||
const normalizedScriptPath = path.normalize(path.resolve(moduleRoot, scriptPath));
|
||||
if (!normalizedScriptPath.startsWith(path.normalize(moduleRoot))) {
|
||||
throw this._createFatalError(
|
||||
`The '${scriptPath}' script must be located in the '${moduleRoot}' folder`
|
||||
);
|
||||
}
|
||||
|
||||
if (bufferOutput) {
|
||||
const runner = new SubProcess(process.execPath, [extScripts[scriptName], ...extraArgs], {
|
||||
cwd: this.config.getInstallPath(installSpec),
|
||||
const runner = new SubProcess(process.execPath, [scriptPath, ...extraArgs], {
|
||||
cwd: moduleRoot,
|
||||
});
|
||||
|
||||
const output = new RingBuffer(50);
|
||||
@@ -761,11 +770,7 @@ class ExtensionCliCommand {
|
||||
|
||||
try {
|
||||
await new B((resolve, reject) => {
|
||||
this._runUnbuffered(
|
||||
this.config.getInstallPath(installSpec),
|
||||
extScripts[scriptName],
|
||||
extraArgs
|
||||
)
|
||||
this._runUnbuffered(moduleRoot, scriptPath, extraArgs)
|
||||
.on('error', (err) => {
|
||||
// generally this is of the "I can't find the script" variety.
|
||||
// this is a developer bug: the extension is pointing to a script that is not where the
|
||||
|
||||
@@ -5,6 +5,7 @@ import axios from 'axios';
|
||||
import {exec} from 'teen_process';
|
||||
import semver from 'semver';
|
||||
import findUp from 'find-up';
|
||||
import os from 'node:os';
|
||||
import {getDefaultsForSchema, getAllArgSpecs} from './schema/schema';
|
||||
|
||||
const npmPackage = fs.readPackageJsonFrom(__dirname);
|
||||
@@ -12,7 +13,6 @@ const npmPackage = fs.readPackageJsonFrom(__dirname);
|
||||
const APPIUM_VER = npmPackage.version;
|
||||
const ENGINES = /** @type {Record<string,string>} */ (npmPackage.engines);
|
||||
const MIN_NODE_VERSION = ENGINES.node;
|
||||
const MIN_NPM_VERSION = ENGINES.npm;
|
||||
|
||||
const GIT_META_ROOT = '.git';
|
||||
const GIT_BINARY = `git${system.isWindows() ? '.exe' : ''}`;
|
||||
@@ -29,15 +29,6 @@ function getNodeVersion() {
|
||||
return /** @type {import('semver').SemVer} */ (semver.coerce(process.version));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version of `npm`
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function getNpmVersion() {
|
||||
const {stdout} = await exec(system.isWindows() ? 'npm.cmd' : 'npm', ['--version']);
|
||||
return stdout.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} [useGithubApiFallback]
|
||||
*/
|
||||
@@ -149,28 +140,6 @@ function checkNodeOk() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function checkNpmOk() {
|
||||
const npmVersion = await getNpmVersion();
|
||||
if (!semver.satisfies(npmVersion, MIN_NPM_VERSION)) {
|
||||
throw new Error(
|
||||
`npm version must be at least ${MIN_NPM_VERSION}; current is ${npmVersion}. Run "npm install -g npm" to upgrade.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function warnNodeDeprecations() {
|
||||
/**
|
||||
* Uncomment this section to get node version deprecation warnings
|
||||
* Also add test cases to config-specs.js to cover the cases added
|
||||
**/
|
||||
// const version = getNodeVersion();
|
||||
// if (version.major < 8) {
|
||||
// logger.warn(`Appium support for versions of node < ${version.major} has been ` +
|
||||
// 'deprecated and will be removed in a future version. Please ' +
|
||||
// 'upgrade!');
|
||||
// }
|
||||
}
|
||||
|
||||
async function showBuildInfo() {
|
||||
await updateBuildInfo(true);
|
||||
console.log(JSON.stringify(getBuildInfo())); // eslint-disable-line no-console
|
||||
@@ -311,16 +280,36 @@ function showConfig(nonDefaultPreConfigParsedArgs, configResult, defaults, parse
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} tmpDir
|
||||
* @param {string} root
|
||||
* @param {boolean} [requireWriteable=true]
|
||||
* @param {string} [displayName='folder path']
|
||||
* @throws {Error}
|
||||
*/
|
||||
async function validateTmpDir(tmpDir) {
|
||||
export async function requireDir(root, requireWriteable = true, displayName = 'folder path') {
|
||||
let stat;
|
||||
try {
|
||||
await fs.mkdirp(tmpDir);
|
||||
stat = await fs.stat(root);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`We could not ensure that the temp dir you specified ` +
|
||||
`(${tmpDir}) exists. Please make sure it's writeable.`
|
||||
);
|
||||
if (e.code === 'ENOENT') {
|
||||
try {
|
||||
await fs.mkdir(root, {recursive: true});
|
||||
return;
|
||||
} catch {}
|
||||
}
|
||||
throw new Error(`The ${displayName} '${root}' must exist and be a valid directory`);
|
||||
}
|
||||
if (stat && !stat.isDirectory()) {
|
||||
throw new Error(`The ${displayName} '${root}' must be a valid directory`);
|
||||
}
|
||||
if (requireWriteable) {
|
||||
try {
|
||||
await fs.access(root, fs.constants.W_OK);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`The ${displayName} '${root}' must be ` +
|
||||
`writeable for the current user account '${os.userInfo().username}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,8 +319,6 @@ export {
|
||||
getBuildInfo,
|
||||
checkNodeOk,
|
||||
showBuildInfo,
|
||||
warnNodeDeprecations,
|
||||
validateTmpDir,
|
||||
getNonDefaultServerArgs,
|
||||
getGitRev,
|
||||
APPIUM_VER,
|
||||
|
||||
@@ -135,9 +135,9 @@ export class DriverConfig extends ExtensionConfig {
|
||||
* Given capabilities, find a matching driver within the config. Load its class and return it along with version and driver name.
|
||||
* @template {import('@appium/types').StringRecord} C
|
||||
* @param {C} caps
|
||||
* @returns {MatchedDriver}
|
||||
* @returns {Promise<MatchedDriver>}
|
||||
*/
|
||||
findMatchingDriver({automationName, platformName}) {
|
||||
async findMatchingDriver({automationName, platformName}) {
|
||||
if (!_.isString(platformName)) {
|
||||
throw new Error('You must include a platformName capability');
|
||||
}
|
||||
@@ -158,7 +158,7 @@ export class DriverConfig extends ExtensionConfig {
|
||||
);
|
||||
log.info(`The '${driverName}' driver was installed and matched caps.`);
|
||||
log.info(`Will require it at ${this.getInstallPath(driverName)}`);
|
||||
const driver = this.require(driverName);
|
||||
const driver = await this.requireAsync(driverName);
|
||||
if (!driver) {
|
||||
throw new Error(
|
||||
`Driver '${driverName}' did not export a class with name '${mainClass}'. Contact the author of the driver!`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {util} from '@appium/support';
|
||||
import {util, fs, system} from '@appium/support';
|
||||
import B from 'bluebird';
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
isAllowedSchemaFileExtension,
|
||||
registerSchema,
|
||||
} from '../schema/schema';
|
||||
import { pathToFileURL } from 'url';
|
||||
|
||||
/**
|
||||
* "npm" install type
|
||||
@@ -554,28 +555,45 @@ export class ExtensionConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads extension and returns its main class (constructor)
|
||||
*
|
||||
* @param {ExtName<ExtType>} extName
|
||||
* @returns {ExtClass<ExtType>}
|
||||
* @returns {Promise<[string, string]>}
|
||||
*/
|
||||
require(extName) {
|
||||
async _resolveExtension(extName) {
|
||||
const {mainClass} = this.installedExtensions[extName];
|
||||
const reqPath = this.getInstallPath(extName);
|
||||
/** @type {string} */
|
||||
let reqResolved;
|
||||
const moduleRoot = this.getInstallPath(extName);
|
||||
const packageJsonPath = path.join(moduleRoot, 'package.json');
|
||||
let entryPointPath;
|
||||
try {
|
||||
reqResolved = require.resolve(reqPath);
|
||||
} catch (err) {
|
||||
throw new ReferenceError(`Could not find a ${this.extensionType} installed at ${reqPath}`);
|
||||
entryPointPath = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')).main ?? 'index.js';
|
||||
} catch (e) {
|
||||
throw new ReferenceError(`Could not find a ${this.extensionType} installed at ${moduleRoot}`);
|
||||
}
|
||||
if (entryPointPath) {
|
||||
entryPointPath = path.resolve(moduleRoot, entryPointPath);
|
||||
} else {
|
||||
throw new ReferenceError(`Cannot find a valid ${this.extensionType} main entry point in '${packageJsonPath}'`);
|
||||
}
|
||||
// note: this will only reload the entry point
|
||||
if (process.env.APPIUM_RELOAD_EXTENSIONS && require.cache[reqResolved]) {
|
||||
log.debug(`Removing ${reqResolved} from require cache`);
|
||||
delete require.cache[reqResolved];
|
||||
if (process.env.APPIUM_RELOAD_EXTENSIONS && require.cache[entryPointPath]) {
|
||||
log.debug(`Removing ${entryPointPath} from require cache`);
|
||||
delete require.cache[entryPointPath];
|
||||
}
|
||||
return [entryPointPath, mainClass];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads extension asynchronously and returns its main class (constructor)
|
||||
*
|
||||
* @param {ExtName<ExtType>} extName
|
||||
* @returns {Promise<ExtClass<ExtType>>}
|
||||
*/
|
||||
async requireAsync(extName) {
|
||||
const [reqPath, mainClass] = await this._resolveExtension(extName);
|
||||
log.debug(`Requiring ${this.extensionType} at ${reqPath}`);
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const MainClass = require(reqPath)[mainClass];
|
||||
// https://github.com/nodejs/node/issues/31710
|
||||
const importPath = system.isWindows() ? pathToFileURL(reqPath).href : reqPath;
|
||||
const MainClass = (await import(importPath))[mainClass];
|
||||
if (!MainClass) {
|
||||
throw new ReferenceError(
|
||||
`Could not find a class named "${mainClass}" exported by ${this.extensionType} "${extName}"`
|
||||
|
||||
@@ -3,6 +3,7 @@ import {USE_ALL_PLUGINS} from '../constants';
|
||||
import log from '../logger';
|
||||
import {DriverConfig} from './driver-config';
|
||||
import {Manifest} from './manifest';
|
||||
import {timing} from '@appium/support';
|
||||
import {PluginConfig} from './plugin-config';
|
||||
import B from 'bluebird';
|
||||
|
||||
@@ -27,6 +28,47 @@ export async function loadExtensions(appiumHome) {
|
||||
return {driverConfig, pluginConfig};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {'driver'|'plugin'} TExtType
|
||||
* @param {TExtType} extType
|
||||
* @param {import('./extension-config').ExtensionConfig} config
|
||||
* @param {string[]} extNames
|
||||
* @param {number} asyncImportChunkSize
|
||||
* @returns {Promise<[TExtType extends 'driver' ? DriverClass : PluginClass, string][]>}
|
||||
*/
|
||||
async function importExtensions(extType, config, extNames, asyncImportChunkSize) {
|
||||
/** @type {B[]} */
|
||||
const allPromises = [];
|
||||
/** @type {B[]} */
|
||||
const activePromisesChunk = [];
|
||||
for (const extName of extNames) {
|
||||
_.remove(activePromisesChunk, (p) => p.isFulfilled());
|
||||
if (activePromisesChunk.length >= asyncImportChunkSize) {
|
||||
await B.any(activePromisesChunk);
|
||||
}
|
||||
const promise = B.resolve((async () => {
|
||||
log.info(`Attempting to load ${extType} ${extName}...`);
|
||||
const timer = new timing.Timer().start();
|
||||
try {
|
||||
const extClass = await config.requireAsync(extName);
|
||||
log.debug(`${extClass.name} has been successfully loaded in ${timer.getDuration().asSeconds.toFixed(3)}s`);
|
||||
return extClass;
|
||||
} catch (err) {
|
||||
log.error(
|
||||
`Could not load ${extType} '${extName}', so it will not be available. Error ` +
|
||||
`in loading the ${extType} was: ${err.message}`
|
||||
);
|
||||
log.debug(err.stack);
|
||||
}
|
||||
})());
|
||||
activePromisesChunk.push(promise);
|
||||
allPromises.push(promise);
|
||||
}
|
||||
return /** @type {[TExtType extends 'driver' ? DriverClass : PluginClass, string][]} */ (
|
||||
_.zip(await B.all(allPromises), extNames).filter(([extClass,]) => Boolean(extClass))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find any plugin name which has been installed, and which has been requested for activation by
|
||||
* using the --use-plugins flag, and turn each one into its class, so we can send them as objects
|
||||
@@ -34,10 +76,15 @@ export async function loadExtensions(appiumHome) {
|
||||
* to wrap command execution
|
||||
*
|
||||
* @param {import('./plugin-config').PluginConfig} pluginConfig - a plugin extension config
|
||||
* @param {number} maxParallelImports the maximum amount of plugins to import in parallel
|
||||
* @param {string[]} usePlugins
|
||||
* @returns {PluginNameMap} Mapping of PluginClass to name
|
||||
* @returns {Promise<PluginNameMap>} Mapping of PluginClass to name
|
||||
*/
|
||||
export function getActivePlugins(pluginConfig, usePlugins = []) {
|
||||
export async function getActivePlugins(pluginConfig, maxParallelImports, usePlugins = []) {
|
||||
if (_.isEmpty(usePlugins)) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
/** @type {string[]} */
|
||||
let filteredPluginNames = [];
|
||||
if (usePlugins.length === 1 && usePlugins[0] === USE_ALL_PLUGINS) {
|
||||
@@ -59,24 +106,7 @@ export function getActivePlugins(pluginConfig, usePlugins = []) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Map(
|
||||
_.compact(
|
||||
filteredPluginNames
|
||||
.map((pluginName) => {
|
||||
try {
|
||||
log.info(`Attempting to load plugin ${pluginName}...`);
|
||||
const PluginClass = pluginConfig.require(pluginName);
|
||||
return [PluginClass, pluginName];
|
||||
} catch (err) {
|
||||
log.error(
|
||||
`Could not load plugin '${pluginName}', so it will not be available. Error ` +
|
||||
`in loading the plugin was: ${err.message}`
|
||||
);
|
||||
log.debug(err.stack);
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
return new Map(await importExtensions('plugin', pluginConfig, filteredPluginNames, maxParallelImports));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,29 +115,30 @@ export function getActivePlugins(pluginConfig, usePlugins = []) {
|
||||
* If the --drivers flag was given, this method only loads the given drivers.
|
||||
*
|
||||
* @param {import('./driver-config').DriverConfig} driverConfig - a driver extension config
|
||||
* @param {number} maxParallelImports the maximum amount of plugins to import in parallel
|
||||
* @param {string[]} [useDrivers] - optional list of drivers to load
|
||||
* @returns {DriverNameMap}
|
||||
* @returns {Promise<DriverNameMap>}
|
||||
*/
|
||||
export function getActiveDrivers(driverConfig, useDrivers = []) {
|
||||
return new Map(
|
||||
_.compact(
|
||||
Object.keys(driverConfig.installedExtensions)
|
||||
.filter((driverName) => _.includes(useDrivers, driverName) || useDrivers.length === 0)
|
||||
.map((driverName) => {
|
||||
try {
|
||||
log.info(`Attempting to load driver ${driverName}...`);
|
||||
const DriverClass = driverConfig.require(driverName);
|
||||
return [DriverClass, driverName];
|
||||
} catch (err) {
|
||||
log.error(
|
||||
`Could not load driver '${driverName}', so it will not be available. Error ` +
|
||||
`in loading the driver was: ${err.message}`
|
||||
);
|
||||
log.debug(err.stack);
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
export async function getActiveDrivers(driverConfig, maxParallelImports, useDrivers = []) {
|
||||
/** @type {string[]} */
|
||||
let filteredDriverNames = [];
|
||||
if (_.isEmpty(useDrivers)) {
|
||||
// load all drivers if none are requested
|
||||
filteredDriverNames = _.keys(driverConfig.installedExtensions);
|
||||
} else {
|
||||
// Load drivers in the same order that was used while enumerating them
|
||||
for (const driverName of useDrivers) {
|
||||
if (driverName in driverConfig.installedExtensions) {
|
||||
filteredDriverNames.push(driverName);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Could not load the driver '${driverName}' because it is not installed. ` +
|
||||
`Only the following drivers are available: ${_.keys(driverConfig.installedExtensions)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Map(await importExtensions('driver', driverConfig, filteredDriverNames, maxParallelImports));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+36
-61
@@ -7,7 +7,7 @@ import {
|
||||
server as baseServer,
|
||||
normalizeBasePath,
|
||||
} from '@appium/base-driver';
|
||||
import {logger as logFactory, util, env, fs} from '@appium/support';
|
||||
import {logger as logFactory, util, env} from '@appium/support';
|
||||
import {asyncify} from 'asyncbox';
|
||||
import _ from 'lodash';
|
||||
import {AppiumDriver} from './appium';
|
||||
@@ -20,15 +20,13 @@ import {
|
||||
getNonDefaultServerArgs,
|
||||
showConfig,
|
||||
showBuildInfo,
|
||||
validateTmpDir,
|
||||
warnNodeDeprecations,
|
||||
checkNpmOk,
|
||||
requireDir,
|
||||
} from './config';
|
||||
import {readConfigFile} from './config-file';
|
||||
import {loadExtensions, getActivePlugins, getActiveDrivers} from './extension';
|
||||
import {SERVER_SUBCOMMAND, LONG_STACKTRACE_LIMIT} from './constants';
|
||||
import registerNode from './grid-register';
|
||||
import {getDefaultsForSchema, validate} from './schema/schema';
|
||||
import {getDefaultsForSchema, validate as validateSchema} from './schema/schema';
|
||||
import {
|
||||
inspect,
|
||||
adjustNodePath,
|
||||
@@ -40,7 +38,6 @@ import {
|
||||
V4_BROADCAST_IP,
|
||||
V6_BROADCAST_IP,
|
||||
} from './utils';
|
||||
import os from 'node:os';
|
||||
import net from 'node:net';
|
||||
|
||||
const {resolveAppiumHome} = env;
|
||||
@@ -53,7 +50,6 @@ const {resolveAppiumHome} = env;
|
||||
async function preflightChecks(args, throwInsteadOfExit = false) {
|
||||
try {
|
||||
checkNodeOk();
|
||||
await checkNpmOk();
|
||||
if (args.longStacktrace) {
|
||||
Error.stackTraceLimit = LONG_STACKTRACE_LIMIT;
|
||||
}
|
||||
@@ -61,12 +57,11 @@ async function preflightChecks(args, throwInsteadOfExit = false) {
|
||||
await showBuildInfo();
|
||||
process.exit(0);
|
||||
}
|
||||
warnNodeDeprecations();
|
||||
|
||||
validate(args);
|
||||
validateSchema(args);
|
||||
|
||||
if (args.tmpDir) {
|
||||
await validateTmpDir(args.tmpDir);
|
||||
await requireDir(args.tmpDir, !args.noPermsCheck, 'tmpDir argument value');
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err.message.red);
|
||||
@@ -149,48 +144,16 @@ function getExtraMethodMap(driverClasses, pluginClasses) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares and validates appium home path folder
|
||||
*
|
||||
* @param {string} name The name of the appium home source (needed for error messages)
|
||||
* @param {string} appiumHome The actual value to be verified
|
||||
* @returns {Promise<string>} Same appiumHome value
|
||||
* @throws {Error} If the validation has failed
|
||||
* @param {string?} [appiumHomeFromArgs] - Appium home value retrieved from progrmmatic server args
|
||||
* @returns {string}
|
||||
*/
|
||||
async function prepareAppiumHome(name, appiumHome) {
|
||||
let stat;
|
||||
try {
|
||||
stat = await fs.stat(appiumHome);
|
||||
} catch (e) {
|
||||
let err = e;
|
||||
if (e.code === 'ENOENT') {
|
||||
try {
|
||||
await fs.mkdir(appiumHome, {recursive: true});
|
||||
return appiumHome;
|
||||
} catch (e1) {
|
||||
err = e1;
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
`The path '${appiumHome}' provided in the ${name} must point ` +
|
||||
`to a valid folder writeable for the current user account '${os.userInfo().username}'. ` +
|
||||
`Original error: ${err.message}`,
|
||||
);
|
||||
function determineAppiumHomeSource(appiumHomeFromArgs) {
|
||||
if (!_.isNil(appiumHomeFromArgs)) {
|
||||
return 'appiumHome config value';
|
||||
} else if (process.env.APPIUM_HOME) {
|
||||
return 'APPIUM_HOME environment variable';
|
||||
}
|
||||
if (!stat.isDirectory()) {
|
||||
throw new Error(
|
||||
`The path '${appiumHome}' provided in the ${name} must point to a valid folder`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
await fs.access(appiumHome, fs.constants.W_OK);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`The folder path '${appiumHome}' provided in the ${name} must be ` +
|
||||
`writeable for the current user account '${os.userInfo().username}. ` +
|
||||
`Original error: ${e.message}`,
|
||||
);
|
||||
}
|
||||
return appiumHome;
|
||||
return 'autodetected Appium home path';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,13 +175,10 @@ async function prepareAppiumHome(name, appiumHome) {
|
||||
*/
|
||||
async function init(args) {
|
||||
const appiumHome = args?.appiumHome ?? (await resolveAppiumHome());
|
||||
let appiumHomeSourceName = 'autodetected appium home path';
|
||||
if (!_.isNil(args?.appiumHome)) {
|
||||
appiumHomeSourceName = 'appiumHome config value';
|
||||
} else if (process.env.APPIUM_HOME) {
|
||||
appiumHomeSourceName = 'APPIUM_HOME environment variable';
|
||||
}
|
||||
await prepareAppiumHome(appiumHomeSourceName, appiumHome);
|
||||
const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
|
||||
// We verify the writeability later based on requested server arguments
|
||||
// Here we just need to make sure the path exists and is a folder
|
||||
await requireDir(appiumHome, false, appiumHomeSourceName);
|
||||
|
||||
adjustNodePath();
|
||||
|
||||
@@ -295,6 +255,10 @@ async function init(args) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!serverArgs.noPermsCheck) {
|
||||
await requireDir(appiumHome, true, appiumHomeSourceName);
|
||||
}
|
||||
|
||||
const appiumDriver = new AppiumDriver(
|
||||
/** @type {import('@appium/types').DriverOpts<import('./appium').AppiumDriverConstraints>} */ (
|
||||
serverArgs
|
||||
@@ -309,8 +273,10 @@ async function init(args) {
|
||||
parsedArgs: serverArgs,
|
||||
driverConfig,
|
||||
pluginConfig,
|
||||
appiumHome,
|
||||
});
|
||||
} else {
|
||||
await requireDir(appiumHome, true, appiumHomeSourceName);
|
||||
if (isExtensionCommandArgs(preConfigArgs)) {
|
||||
// if the user has requested the 'driver' CLI, don't run the normal server,
|
||||
// but instead pass control to the driver CLI
|
||||
@@ -340,7 +306,7 @@ function logServerAddress(url) {
|
||||
}
|
||||
|
||||
const interfaces = fetchInterfaces(urlObj.hostname === V4_BROADCAST_IP ? 4 : 6);
|
||||
const toLabel = (/** @type {os.NetworkInterfaceInfo} */ iface) => {
|
||||
const toLabel = (/** @type {import('node:os').NetworkInterfaceInfo} */ iface) => {
|
||||
const href = urlObj.href.replace(urlObj.hostname, iface.address);
|
||||
return iface.internal ? `${href} (only accessible from the same host)` : href;
|
||||
};
|
||||
@@ -370,17 +336,25 @@ async function main(args) {
|
||||
);
|
||||
}
|
||||
|
||||
const {appiumDriver, pluginConfig, driverConfig, parsedArgs} =
|
||||
const {appiumDriver, pluginConfig, driverConfig, parsedArgs, appiumHome} =
|
||||
/** @type {InitResult<ServerCommand>} */ (initResult);
|
||||
|
||||
const pluginClasses = getActivePlugins(pluginConfig, parsedArgs.usePlugins);
|
||||
const pluginClasses = await getActivePlugins(
|
||||
pluginConfig, parsedArgs.pluginsImportChunkSize, parsedArgs.usePlugins
|
||||
);
|
||||
// set the active plugins on the umbrella driver so it can use them for commands
|
||||
appiumDriver.pluginClasses = pluginClasses;
|
||||
|
||||
await logStartupInfo(parsedArgs);
|
||||
|
||||
const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
|
||||
logger.debug(`The ${appiumHomeSourceName}: ${appiumHome}`);
|
||||
|
||||
let routeConfiguringFunction = makeRouter(appiumDriver);
|
||||
|
||||
const driverClasses = getActiveDrivers(driverConfig, parsedArgs.useDrivers);
|
||||
const driverClasses = await getActiveDrivers(
|
||||
driverConfig, parsedArgs.driversImportChunkSize, parsedArgs.useDrivers
|
||||
);
|
||||
const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
|
||||
const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
|
||||
|
||||
@@ -498,6 +472,7 @@ export {main, init, resolveAppiumHome};
|
||||
* @typedef ServerInitData
|
||||
* @property {import('./appium').AppiumDriver} appiumDriver - The Appium driver
|
||||
* @property {import('appium/types').ParsedArgs} parsedArgs - The parsed arguments
|
||||
* @property {string} appiumHome - The full path to the Appium home folder
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "appium",
|
||||
"version": "2.2.3",
|
||||
"version": "2.3.0",
|
||||
"description": "Automation for Apps.",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -60,13 +60,13 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.4.3",
|
||||
"@appium/base-plugin": "^2.2.24",
|
||||
"@appium/docutils": "^0.4.13",
|
||||
"@appium/schema": "^0.4.2",
|
||||
"@appium/support": "^4.1.10",
|
||||
"@appium/types": "^0.14.3",
|
||||
"@sidvind/better-ajv-errors": "2.1.0",
|
||||
"@appium/base-driver": "^9.4.4",
|
||||
"@appium/base-plugin": "^2.2.25",
|
||||
"@appium/docutils": "^1.0.1",
|
||||
"@appium/schema": "^0.5.0",
|
||||
"@appium/support": "^4.1.11",
|
||||
"@appium/types": "^0.15.0",
|
||||
"@sidvind/better-ajv-errors": "2.1.3",
|
||||
"@types/argparse": "2.0.14",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"@types/fancy-log": "2.0.2",
|
||||
@@ -90,8 +90,8 @@
|
||||
"resolve-from": "5.0.0",
|
||||
"semver": "7.5.4",
|
||||
"source-map-support": "0.5.21",
|
||||
"teen_process": "2.0.101",
|
||||
"type-fest": "3.13.1",
|
||||
"teen_process": "2.1.1",
|
||||
"type-fest": "4.8.3",
|
||||
"winston": "3.11.0",
|
||||
"wrap-ansi": "7.0.0",
|
||||
"yaml": "2.3.4"
|
||||
@@ -103,8 +103,5 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "3fa73a1d1a95e3868fbceb005f8b1deb4ac53eaf",
|
||||
"typedoc": {
|
||||
"entryPoint": "./lib/main.js"
|
||||
}
|
||||
"gitHead": "3fa73a1d1a95e3868fbceb005f8b1deb4ac53eaf"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"webdriverio": "^8.11.2"
|
||||
"webdriverio": "8.26.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('FakeDriver via HTTP', function () {
|
||||
);
|
||||
}
|
||||
|
||||
FakeDriver = driverConfig.require('fake');
|
||||
FakeDriver = await driverConfig.requireAsync('fake');
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
|
||||
@@ -44,14 +44,6 @@ describe('when Appium is a dependency of the current project', function () {
|
||||
return YAML.parse(manifest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper fn
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function readHash() {
|
||||
return await fs.readFile(hashPath, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {CliExtensionSubcommand} ExtSubcommand
|
||||
* @type {import('lodash').CurriedFunction1<CliExtArgs<ExtSubcommand> | CliArgs, Promise<unknown>>}
|
||||
@@ -140,17 +132,9 @@ describe('when Appium is a dependency of the current project', function () {
|
||||
manifestParsed.should.have.nested.property('drivers.fake');
|
||||
});
|
||||
|
||||
it('should update the package hash', async function () {
|
||||
(await fs.exists(hashPath)).should.be.true;
|
||||
});
|
||||
|
||||
describe('when a different driver is installed via "appium driver install"', function () {
|
||||
/** @type {string} */
|
||||
let oldHash;
|
||||
|
||||
before(async function () {
|
||||
await runJson([DRIVER_TYPE, LIST]);
|
||||
oldHash = await readHash();
|
||||
await installLocalExtension(appiumHome, DRIVER_TYPE, testDriverPath);
|
||||
});
|
||||
|
||||
@@ -159,11 +143,6 @@ describe('when Appium is a dependency of the current project', function () {
|
||||
expect(newPkg).to.have.nested.property('devDependencies.@appium/test-driver');
|
||||
});
|
||||
|
||||
it('should update the hash', async function () {
|
||||
const newHash = await readHash();
|
||||
newHash.should.not.equal(oldHash);
|
||||
});
|
||||
|
||||
it('should update the manifest with the new driver', async function () {
|
||||
const manifest = await fs.readFile(manifestPath, 'utf8');
|
||||
/** @type {ManifestData} */
|
||||
|
||||
@@ -6,6 +6,7 @@ export default {
|
||||
callbackPort: 4723,
|
||||
debugLogSpacing: false,
|
||||
denyInsecure: [],
|
||||
driversImportChunkSize: 3,
|
||||
keepAliveTimeout: 600,
|
||||
localTimezone: false,
|
||||
loglevel: 'debug',
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
logTimestamp: false,
|
||||
longStacktrace: false,
|
||||
noPermsCheck: false,
|
||||
pluginsImportChunkSize: 7,
|
||||
port: 4723,
|
||||
relaxedSecurityEnabled: false,
|
||||
sessionOverride: false,
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
getNonDefaultServerArgs,
|
||||
showBuildInfo,
|
||||
showConfig,
|
||||
validateTmpDir,
|
||||
warnNodeDeprecations,
|
||||
requireDir,
|
||||
} from '../../lib/config';
|
||||
import {PLUGIN_TYPE} from '../../lib/constants';
|
||||
import logger from '../../lib/logger';
|
||||
import {
|
||||
finalizeSchema,
|
||||
getDefaultsForSchema,
|
||||
@@ -161,28 +159,6 @@ describe('Config', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('warnNodeDeprecations', function () {
|
||||
let spy;
|
||||
before(function () {
|
||||
spy = sandbox.spy(logger, 'warn');
|
||||
});
|
||||
beforeEach(function () {
|
||||
spy.resetHistory();
|
||||
});
|
||||
it('should not log a warning if node is 8+', function () {
|
||||
// @ts-expect-error
|
||||
process.version = 'v8.0.0';
|
||||
warnNodeDeprecations();
|
||||
logger.warn.should.not.be.called;
|
||||
});
|
||||
it('should not log a warning if node is 9+', function () {
|
||||
// @ts-expect-error
|
||||
process.version = 'v9.0.0';
|
||||
warnNodeDeprecations();
|
||||
logger.warn.should.not.be.called;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('server arguments', function () {
|
||||
@@ -238,18 +214,21 @@ describe('Config', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateTmpDir', function () {
|
||||
it('should fail to use a tmp dir with incorrect permissions', function () {
|
||||
validateTmpDir('/private/if_you_run_with_sudo_this_wont_fail').should.be.rejectedWith(
|
||||
/could not ensure/
|
||||
describe('requireDir', function () {
|
||||
it('should fail to use a dir with incorrect permissions', function () {
|
||||
requireDir('/private/if_you_run_with_sudo_this_wont_fail').should.be.rejectedWith(
|
||||
/must exist/
|
||||
);
|
||||
});
|
||||
it('should fail to use an undefined tmp dir', function () {
|
||||
it('should fail to use an undefined dir', function () {
|
||||
// @ts-expect-error
|
||||
validateTmpDir().should.be.rejectedWith(/could not ensure/);
|
||||
requireDir().should.be.rejectedWith(/must exist/);
|
||||
});
|
||||
it('should be able to use a tmp dir with correct permissions', function () {
|
||||
validateTmpDir('/tmp/test_tmp_dir/with/any/number/of/levels').should.not.be.rejected;
|
||||
it('should fail to use an non-writeable dir', function () {
|
||||
requireDir('/private').should.be.rejectedWith(/must be writeable/);
|
||||
});
|
||||
it('should be able to use a dir with correct permissions', function () {
|
||||
requireDir('/tmp/test_tmp_dir/with/any/number/of/levels').should.not.be.rejected;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -300,11 +300,8 @@ describe('ExtensionConfig', function () {
|
||||
});
|
||||
|
||||
describe('when the extension is not actually installed', function () {
|
||||
it('should throw', function () {
|
||||
expect(() => config.require('fake')).to.throw(
|
||||
ReferenceError,
|
||||
/^could not find a driver installed at .+flotsam/i
|
||||
);
|
||||
it('should throw', async function () {
|
||||
await config.requireAsync('fake').should.be.rejectedWith(/cannot find module/i);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -315,11 +312,8 @@ describe('ExtensionConfig', function () {
|
||||
// ()`config.appiumHome` is stubbed already, so we can't just run `getInstallPath` as-is)
|
||||
sandbox.stub(config, 'getInstallPath').returns(FAKE_DRIVER_DIR);
|
||||
});
|
||||
it('should throw', function () {
|
||||
expect(() => config.require('fake')).to.throw(
|
||||
ReferenceError,
|
||||
/could not find a class named "Jetsam" exported by driver "fake"/i
|
||||
);
|
||||
it('should throw', async function () {
|
||||
await config.requireAsync('fake').should.be.rejectedWith(/cannot find module/i);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -333,8 +327,8 @@ describe('ExtensionConfig', function () {
|
||||
.returns(path.join(PROJECT_ROOT, 'packages', 'relaxed-caps-plugin'));
|
||||
});
|
||||
|
||||
it('should return the class', function () {
|
||||
expect(config.require('relaxed-caps')).to.equal(
|
||||
it('should return the class', async function () {
|
||||
expect(await config.requireAsync('relaxed-caps')).to.equal(
|
||||
require('@appium/relaxed-caps-plugin').RelaxedCapsPlugin
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [9.4.4](https://github.com/appium/appium/compare/@appium/base-driver@9.4.3...@appium/base-driver@9.4.4) (2023-12-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** remove `@appium/typedoc-plugin-appium` and all other uses of `typedoc` ([#19465](https://github.com/appium/appium/issues/19465)) ([7528fcf](https://github.com/appium/appium/commit/7528fcf890f79f4017f5e718bb1952bf907ee479))
|
||||
* **images-plugin:** update dependency lru-cache to v10 ([#19490](https://github.com/appium/appium/issues/19490)) ([19c30b4](https://github.com/appium/appium/commit/19c30b490b244f52918f72bdeeb957a999fdbcb9))
|
||||
* **images-plugin:** update dependency lru-cache to v10 ([#19497](https://github.com/appium/appium/issues/19497)) ([4dd95c0](https://github.com/appium/appium/commit/4dd95c096e4e4685c4f464b8251370ea001a562a))
|
||||
* **types:** update dependency type-fest to v4 ([#19104](https://github.com/appium/appium/issues/19104)) ([8bfa1b5](https://github.com/appium/appium/commit/8bfa1b5a4d090b0102dbb914c9b72aea52d96788))
|
||||
|
||||
|
||||
|
||||
## [9.4.3](https://github.com/appium/appium/compare/@appium/base-driver@9.4.2...@appium/base-driver@9.4.3) (2023-12-04)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/base-driver",
|
||||
"version": "9.4.3",
|
||||
"version": "9.4.4",
|
||||
"description": "Base driver class for Appium drivers",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -44,8 +44,8 @@
|
||||
"test:types": "tsd"
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.1.10",
|
||||
"@appium/types": "^0.14.3",
|
||||
"@appium/support": "^4.1.11",
|
||||
"@appium/types": "^0.15.0",
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/async-lock": "1.4.2",
|
||||
"@types/bluebird": "3.5.42",
|
||||
@@ -62,13 +62,13 @@
|
||||
"express": "4.18.2",
|
||||
"http-status-codes": "2.3.0",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "10.0.1",
|
||||
"lru-cache": "10.1.0",
|
||||
"method-override": "3.0.0",
|
||||
"morgan": "1.10.0",
|
||||
"path-to-regexp": "6.2.1",
|
||||
"serve-favicon": "2.5.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"type-fest": "3.13.1",
|
||||
"type-fest": "4.8.3",
|
||||
"validate.js": "0.13.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
@@ -82,9 +82,6 @@
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "8480a85ce2fa466360e0fb1a7f66628331907f02",
|
||||
"typedoc": {
|
||||
"entryPoint": "./lib/index.js"
|
||||
},
|
||||
"tsd": {
|
||||
"directory": "test/types"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.2.25](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.24...@appium/base-plugin@2.2.25) (2023-12-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** remove `@appium/typedoc-plugin-appium` and all other uses of `typedoc` ([#19465](https://github.com/appium/appium/issues/19465)) ([7528fcf](https://github.com/appium/appium/commit/7528fcf890f79f4017f5e718bb1952bf907ee479))
|
||||
|
||||
|
||||
|
||||
## [2.2.24](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.23...@appium/base-plugin@2.2.24) (2023-12-04)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/base-plugin",
|
||||
"version": "2.2.24",
|
||||
"version": "2.2.25",
|
||||
"description": "The base plugin used to create Appium 2.0 plugins",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -40,8 +40,8 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.4.3",
|
||||
"@appium/support": "^4.1.10"
|
||||
"@appium/base-driver": "^9.4.4",
|
||||
"@appium/support": "^4.1.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
@@ -53,8 +53,5 @@
|
||||
"gitHead": "8480a85ce2fa466360e0fb1a7f66628331907f02",
|
||||
"tags": [
|
||||
"appium"
|
||||
],
|
||||
"typedoc": {
|
||||
"entryPoint": "./lib/plugin.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.0.30](https://github.com/appium/appium/compare/@appium/doctor@2.0.29...@appium/doctor@2.0.30) (2023-12-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **support:** update dependency teen_process to v2.0.109 ([85dce4a](https://github.com/appium/appium/commit/85dce4a72b21e017b4661ddf997c096817e5fd7f))
|
||||
* **support:** update dependency teen_process to v2.0.110 ([b602693](https://github.com/appium/appium/commit/b60269371662de4c42ccd7586512c9d685d95d52))
|
||||
* **support:** update dependency teen_process to v2.0.112 ([#19491](https://github.com/appium/appium/issues/19491)) ([d2d8ea7](https://github.com/appium/appium/commit/d2d8ea7a105eb93f59793fbc4d3438a66a191cd8))
|
||||
* **support:** update dependency teen_process to v2.1.1 ([b79ed2b](https://github.com/appium/appium/commit/b79ed2bed5329b904b15fa5b1fbde7885087c9ad))
|
||||
|
||||
|
||||
|
||||
## [2.0.29](https://github.com/appium/appium/compare/@appium/doctor@2.0.28...@appium/doctor@2.0.29) (2023-12-04)
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user