Compare commits

..
1251 changed files with 48190 additions and 126272 deletions
-13
View File
@@ -1,13 +0,0 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
-8
View File
@@ -1,8 +0,0 @@
**/coverage/**
**/node_modules/**
examples/javascript-wd
**/build/**
**/*.min.js
sample-code
**/build-fixtures/**
packages/appium/docs/**/assets/**
-62
View File
@@ -1,62 +0,0 @@
{
"extends": ["@appium/eslint-config-appium-ts"],
"overrides": [
{
"files": "packages/fake-driver/**/*",
"rules": {"require-await": "off"}
},
{"files": "packages/support/**/*", "globals": {"BigInt": "readonly"}},
{
"files": "packages/*/test/**/*",
"rules": {"func-names": "off"}
},
{
"files": [
"packages/appium/support.js",
"packages/appium/driver.js",
"packages/appium/plugin.js"
],
"parserOptions": {
"sourceType": "script"
}
},
{
"files": [
"./test/setup.js",
"./**/scripts/**/*.js",
"./packages/*/index.js",
"./packages/docutils/bin/appium-docs.js"
],
"rules": {
"@typescript-eslint/no-var-requires": "off"
},
"parserOptions": {
"sourceType": "script"
}
},
{
"files": "./packages/*/test/**/*.js",
"rules": {
"@typescript-eslint/no-var-requires": "off",
"no-restricted-properties": [
"error",
{
"object": "sinon",
"property": "spy",
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.spy()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
},
{
"object": "sinon",
"property": "stub",
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.stub()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
},
{
"object": "sinon",
"property": "mock",
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.mock()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
}
]
}
}
]
}
-56
View File
@@ -1,56 +0,0 @@
# Generated by FOSSA CLI (https://github.com/fossas/fossa-cli)
# Visit https://fossa.com to learn more
version: 3
project:
id: appium
name: appium
paths:
exclude:
- ./sample-code
- '**/fixtures/**'
- '**/demo/**'
- '**/example/**'
- '**/examples/**'
targets:
only:
- type: npm
path: .
- type: npm
path: ./packages/appium
- type: npm
path: ./packages/base-driver
- type: npm
path: ./packages/doctor
- type: npm
path: ./packages/eslint-config-appium
- type: npm
path: ./packages/fake-driver
- type: npm
path: ./packages/support
- type: npm
path: ./packages/test-support
- type: npm
path: ./packages/types
- type: npm
path: ./packages/schema
- type: npm
path: ./packages/universal-xmlplugin
- type: npm
path: ./packages/opencv
- type: npm
path: ./packages/images-plugin
- type: npm
path: ./packages/base-plugin
- type: npm
path: ./packages/relaxed-caps-plugin
- type: npm
path: ./packages/fake-plugin
- type: npm
path: ./packages/docutils
revision:
branch: master
-4
View File
@@ -1,4 +0,0 @@
* text=auto eol=lf
# Handle as a text file but merge as binary.
package-lock.json merge=binary
-92
View File
@@ -1,92 +0,0 @@
name: 🐞 Bug Report
description: File a new bug report
title: 'bug: <title>'
labels: [Bug, Needs Triage]
body:
- type: markdown
attributes:
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
- type: checkboxes
attributes:
label: 'Do I have the most recent component updates?'
description: 'Appium 1-related issues are going to be ignored as this version has reached its end of life.'
options:
- label: 'I use the most recent available driver/plugin and server versions'
required: true
- type: checkboxes
attributes:
label: 'Is the component officially supported by the Appium team?'
description: 'Make sure you report an issue for a component which is officially supported/maintained by the Appium team.'
options:
- label: 'I have verified the component repository is present under the Appium organization in GitHub'
required: true
- type: checkboxes
attributes:
label: 'Is there an existing issue for this?'
description: 'Please [search :mag: the issues](https://github.com/appium/appium/issues) to check if this bug has already been reported.'
options:
- label: 'I have searched the existing issues'
required: true
- type: textarea
attributes:
label: 'Current Behavior'
description: 'Describe the problem you are experiencing. **Please do not paste your logs here.** Screenshots are welcome.'
validations:
required: true
- type: textarea
attributes:
label: 'Expected Behavior'
description: 'Describe what you expect to happen instead.'
validations:
required: true
- type: textarea
attributes:
label: 'Minimal Reproducible Example'
description: |
Please provide a the _smallest, complete code snippet_ that Appium's maintainers can run to reproduce the issue ([read more about what this entails](https://stackoverflow.com/help/minimal-reproducible-example)). Failing this, any sort of reproduction steps are better than nothing!
An easy way to get started is to copy [sample code](https://github.com/appium/appium/tree/master/packages/appium/sample-code) and modify it accordingly.
If the result is more than a screenful of text _or_ requires multiple files, please:
- _Attach_ (do not paste) it to this textarea, _or_
- Put it in a [Gist](https://gist.github.com) and paste the link, _or_
- Provide a link to a new or existing public repository exhibiting the issue
validations:
required: true
- type: textarea
attributes:
label: 'Environment'
description: 'Please provide the following information about your environment; feel free to remove any items which are not relevant.'
value: |
- Operating system:
- Appium server version (output of `appium --version`):
- Appium driver(s) and their version(s):
- Appium plugin(s) and their version(s):
- Node.js version (output of `node --version`):
- `npm` version (output of `npm --version`):
- Last component(s) version which did _not_ exhibit the problem:
- Platform and version under test:
- Real device or emulator/simulator:
validations:
required: false
- type: input
attributes:
label: 'Link to Appium Logs'
description: |
Create a [Gist](https://gist.github.com)—which contains your _full_ Appium logs—and link it here. Alternatively, you can attach a logfile to this issue (drag it into the "Further Information" field below).
:warning: _Remember to redact or remove any sensitive information!_
placeholder: 'https://gist.github.com/...'
- type: textarea
attributes:
label: Further Information
description: |
Links? References? Anything that will give us more context about the issue you are encountering!
_Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in._
validations:
required: false
- type: markdown
attributes:
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
-20
View File
@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[Feat]:"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
-28
View File
@@ -1,28 +0,0 @@
## Proposed changes
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
## Types of changes
What types of changes does your code introduce to Appium?
_Put an `x` in the boxes that apply_
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation Update (if none of the other choices apply)
## Checklist
_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._
- [ ] I have read the [CONTRIBUTING](https://github.com/appium/appium/blob/master/CONTRIBUTING.md) doc
- [ ] I have signed the CLA
- [ ] Lint and unit tests pass locally with my changes
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] I have added necessary documentation (if appropriate)
- [ ] Any dependent changes have been merged and published in downstream modules
## Further comments
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
-154
View File
@@ -1,154 +0,0 @@
version: v1
labels:
- label: 'Enhancement'
sync: true
matcher:
commits: '^feat.*?:'
title: '^feat.*?:'
- label: 'Bug'
sync: true
matcher:
commits: '^fix.*?:'
title: '^fix.*?:'
- label: 'Documentation'
sync: true
matcher:
commits: '^docs.*?:'
title: '^docs.*?:'
files: ['packages/docutils/**', 'packages/appium/docs/**', '**/*.md']
- label: 'chore'
sync: true
matcher:
commits: '^chore.*?:'
title: '^chore.*?:'
files: ['.github/**', '.husky/**', '.vscode/**', './.*', './*.js', '**/test/**']
- label: 'SemVer:Breaking'
sync: true
matcher:
commits: '(^(.+?)!:)|(BREAKING CHANGE:)'
- label: 'Dependencies'
sync: true
matcher:
files: ['**/package.json', 'package-lock.json', '**/requirements.txt']
author: 'renovate'
- label: 'appium core'
sync: true
matcher:
files: ['packages/appium/**']
- label: '@appium/base-driver'
sync: true
matcher:
files: ['packages/base-driver/**']
- label: '@appium/eslint-config-appium'
sync: true
matcher:
files: ['packages/eslint-config-appium/**']
- label: '@appium/eslint-config-appium-ts'
sync: true
matcher:
files: ['packages/eslint-config-appium-ts/**']
- label: '@appium/base-plugin'
sync: true
matcher:
files: ['packages/base-plugin/**']
- label: '@appium/doctor'
sync: true
matcher:
files: ['packages/doctor/**']
- label: '@appium/docutils'
sync: true
matcher:
files: ['packages/docutils/**']
- label: '@appium/driver-test-support'
sync: true
matcher:
files: ['packages/driver-test-support/**']
- label: '@appium/execute-driver-plugin'
sync: true
matcher:
files: ['packages/execute-driver-plugin/**']
- label: '@appium/fake-driver'
sync: true
matcher:
files: ['packages/fake-driver/**']
- label: '@appium/fake-plugin'
sync: true
matcher:
files: ['packages/fake-plugin/**']
- label: '@appium/images-plugin'
sync: true
matcher:
files: ['packages/images-plugin/**']
- label: '@appium/opencv'
sync: true
matcher:
files: ['packages/opencv/**']
- label: '@appium/plugin-test-support'
sync: true
matcher:
files: ['packages/plugin-test-support/**']
- label: '@appium/relaxed-caps-plugin'
sync: true
matcher:
files: ['packages/relaxed-caps-plugin/**']
- label: '@appium/schema'
sync: true
matcher:
files: ['packages/schema/**']
- label: '@appium/support'
sync: true
matcher:
files: ['packages/support/**']
- label: '@appium/test-support'
sync: true
matcher:
files: ['packages/test-support/**']
- label: '@appium/tsconfig'
sync: true
matcher:
files: ['packages/tsconfig/**']
- label: '@appium/typedoc-plugin-appium'
sync: true
matcher:
files: ['packages/typedoc-plugin-appium/**']
- label: '@appium/types'
sync: true
matcher:
files: ['packages/types/**']
- label: '@appium/universal-xml-plugin'
sync: true
matcher:
files: ['packages/universal-xml-plugin/**']
- label: '@appium/strongbox'
sync: true
matcher:
files: ['packages/strongbox/**']
-26
View File
@@ -1,26 +0,0 @@
# Configuration for Lock Threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 365
# Skip issues and pull requests created before a given timestamp. Timestamp must
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
skipCreatedBefore: false
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
exemptLabels: []
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: false
# Limit to only `issues` or `pulls`
only: issues
-16
View File
@@ -1,16 +0,0 @@
name: Labeler
on:
pull_request_target:
types: [opened, synchronize]
branches: [master]
permissions: read-all
jobs:
labeler:
permissions:
pull-requests: write
name: Auto-Label PRs
runs-on: ubuntu-latest
steps:
- uses: fuxingloh/multi-labeler@6704db0bcba106d07482efabbc79d3092af74fa2 # v2
-104
View File
@@ -1,104 +0,0 @@
name: Appium Build
on:
push:
# this list of paths could potentially impact the build
paths:
- '**/tsconfig*.json'
- 'packages/base-driver/static/**/*'
- 'packages/*/test/**'
- 'packages/*/bin'
- 'packages/**/*.ts'
- 'packages/**/*.json'
- 'packages/**/*.js'
- 'package*.json'
- 'lerna.json'
- '.npmrc'
- '.mocharc.js'
- '.github/workflows/build.yml' # this file
- '.eslintrc'
- '.eslintignore'
- '!**/sample-code/**'
- '!packages/*/docs/**'
pull_request:
paths:
- '**/tsconfig*.json'
- 'packages/base-driver/static/**/*'
- 'packages/*/test/**'
- 'packages/*/bin'
- 'packages/**/*.ts'
- 'packages/**/*.json'
- 'packages/**/*.js'
- 'package*.json'
- 'lerna.json'
- '.npmrc'
- '.mocharc.js'
- '.github/workflows/build.yml' # this file
- '.eslintrc'
- '.eslintignore'
- '!**/sample-code/**'
- '!packages/*/docs/**'
permissions:
contents: read
jobs:
prepare_matrix:
runs-on: ubuntu-latest
outputs:
versions: ${{ steps.generate-matrix.outputs.versions }}
steps:
- name: Select 3 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"
test:
needs:
- prepare_matrix
name: Tests
strategy:
matrix:
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
os:
- ubuntu-latest
# TODO: Windows is not stable and slow to run
# - windows-latest
# TODO: Enable below envs after all tests have been verified green
# - macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install latest npm (win)
if: ${{ matrix.os == 'windows-latest' }}
# for some reason there's a bug in upgrading npm on win, have to install a specific version first
# https://github.com/actions/setup-node/issues/623
run: |
npm install -g npm@8.3.1
npm install -g npm@latest
- name: Install latest npm (non-win)
if: ${{ matrix.os != 'windows-latest' }}
run: npm install -g npm
- name: Install dependencies
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci --foreground-scripts
- name: Run smoke, unit & E2E tests
run: npm run test:ci
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Install dependencies
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci
- name: ESLint
run: npm run lint:ci
-36
View File
@@ -1,36 +0,0 @@
name: Cache Cleanup
# from https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
echo "Fetching list of cache keys"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-57
View File
@@ -1,57 +0,0 @@
name: Appium Deploy
on:
push:
tags:
- master
workflow_dispatch:
permissions:
contents: read
jobs:
check:
name: Check
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: ${{ matrix.node-version }}
- name: Install Appium
run: |
if [[ "$GITHUB_REF_TYPE" == tag ]]; then
npm i --location=global $GITHUB_REF_NAME
else
npm i --location=global appium
fi
shell: bash
- name: Install drivers and plugins
run: |
if grep -q macos <<< ${{ matrix.os }}; then
appium driver install xcuitest
fi
appium driver install uiautomator2
appium plugin install images
shell: bash
- name: Verify installation
run: |
installed_drivers=$(appium driver list --installed 2>&1)
if grep -q macos <<< ${{ matrix.os }}; then
grep -q xcuitest <<< $installed_drivers
fi
grep -q uiautomator2 <<< $installed_drivers
installed_plugins=$(appium plugin list --installed 2>&1)
grep -q images <<< $installed_plugins
shell: bash
- name: Verify Appium could be executed
run: |
appium --use-plugins=images &
pid=$(echo $!)
sleep 5
ps -p $pid || exit 1
kill -2 $pid
shell: bash
-51
View File
@@ -1,51 +0,0 @@
name: Build Docs
on:
pull_request:
paths:
- '**/typedoc.json'
- '**/tsconfig*.json'
- '**/package*.json'
- '**/*mkdocs*.ya?ml'
- 'packages/docutils/requirements.txt'
- 'packages/*/README.md'
- 'packages/*/docs/**'
- 'packages/*/**/*.ts'
- 'packages/*/**/*.js'
- '.github/workflows/docs.yml' # this file
- '!**/test/**'
- '!**/sample-code/**'
push:
paths:
- '**/typedoc.json'
- '**/tsconfig*.json'
- '**/package*.json'
- '**/*mkdocs*.ya?ml'
- 'packages/docutils/requirements.txt'
- 'packages/*/README.md'
- 'packages/*/docs/**'
- 'packages/*/**/*.ts'
- 'packages/*/**/*.js'
- '.github/workflows/docs.yml' # this file
- '!**/test/**'
- '!**/sample-code/**'
jobs:
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Install dependencies (Node.js)
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci
- name: Install dependencies (Python)
run: pip install -r packages/docutils/requirements.txt
- name: Configure Git User
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: Build Docs
run: npm run docs:preview
-26
View File
@@ -1,26 +0,0 @@
name: License Checks
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
permissions:
contents: read
jobs:
fossa-check:
name: Run FOSSA Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
with:
ref: master
- name: Install dependencies
uses: bahmutov/npm-install@cb39a46f27f14697fec763d60fb23ad347e2befa # tag=v1
- name: Install fossa-cli
run: ./scripts/install-fossa.sh -d
- name: Run FOSSA analysis
run: |
fossa analyze
fossa test
env:
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
-15
View File
@@ -1,15 +0,0 @@
name: Disallow "On Hold" PRs
on:
pull_request_target:
types: [opened, labeled, unlabeled, synchronize]
branches: [master]
jobs:
label-check:
runs-on: ubuntu-latest
steps:
- name: Check for "On Hold" label
uses: egmacke/action-check-label@0eb29f801fb482a95c9bd2dd22834ecc8f4e8af9 # v2
with:
label: On Hold
state: absent
-38
View File
@@ -1,38 +0,0 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Publish docs
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v3
- 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
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies (Node.js)
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci
- name: Install dependencies (Python)
run: pip install -r packages/docutils/requirements.txt
- name: Publish docs
run: |
cd packages/appium
npm run publish:docs
-26
View File
@@ -1,26 +0,0 @@
name: Validate Renovate Configs
on:
push:
paths:
- '.github/workflows/renovate.yml' # this file
- '.renovaterc.json'
- 'renovate/default.json'
pull_request:
paths:
- '.github/workflows/renovate.yml' # this file
- '.renovaterc.json'
- 'renovate/default.json'
permissions:
contents: read
jobs:
renovate:
name: Check Renovate Configs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Validate Renovate Config
uses: rinchsan/renovate-config-validator@1ea1e8514f6a33fdd71c40b0a5fa3512b9e7b936 # tag=v0
with:
pattern: '{.renovaterc.json,renovate/default.json}'
+5 -36
View File
@@ -2,20 +2,19 @@
*.swp
.DS_Store
node_modules
sample-code
*.trace
xcuserdata
*.sublime-*
test/functional/_joined
*.iml
!examples/java/*.iml
*.autosave
.idea/
!examples/java/.idea/
*.log
*.t
artifacts
input
./output
output
lib/devices/android/bootstrap/bin/*
lib/devices/android/bootstrap/local.properties
lib/devices/android/bootstrap/project.properties
@@ -24,41 +23,11 @@ lib/devices/android/bootstrap/target/
.*~
*~
org.eclipse.ltk.core.refactoring.prefs
/selendroid
.appiumconfig*
build/
.idea
lib/devices/ios/uiauto/lib/status.js
lib/devices/ios/uiauto/appium/xpath.js
*DerivedData
__pycache__
# csharp
*.pyc
*.pdb
.vs
old
.tern-project
coverage
docs/mkdocs.yml
examples/javascript-wd/node_modules
examples/php/vendor
examples/php/composer.lock
examples/java/out/
examples/ruby/Gemfile.lock
examples/python/test/results/
examples/python/test/input
examples/python/.pytest_cache/
examples/csharp/test/bin
examples/csharp/test/obj
examples/csharp/test/bin
examples/csharp/packages
appium.zip
.vscode/settings.json
.nyc_output
*.lerna_backup
**/build-fixtures/**
*.tsbuildinfo
packages/*/LICENSE
local_appium_home
*.tgz
typedoc-docs
packages/appium/docs/*/reference
+64
View File
@@ -0,0 +1,64 @@
[submodule "submodules/instruments-without-delay"]
path = submodules/instruments-without-delay
url = https://github.com/facebook/instruments-without-delay.git
[submodule "submodules/ApiDemos"]
path = submodules/ApiDemos
url = https://github.com/appium/android-apidemos.git
[submodule "submodules/appium.io"]
path = submodules/appium.io
url = https://github.com/appium/appium.io.git
[submodule "submodules/selendroid"]
path = submodules/selendroid
url = https://github.com/selendroid/selendroid.git
[submodule "submodules/fruitstrap"]
path = submodules/fruitstrap
url = https://github.com/tborys/fruitstrap.git
[submodule "submodules/io.appium.gappium.sampleapp"]
path = submodules/io.appium.gappium.sampleapp
url = https://github.com/appium/io.appium.gappium.sampleapp.git
[submodule "submodules/udidetect"]
path = submodules/udidetect
url = https://github.com/vaskas/udidetect.git
[submodule "submodules/unlock_apk"]
path = submodules/unlock_apk
url = https://github.com/appium/unlock_apk.git
[submodule "submodules/SafariLauncher"]
path = submodules/SafariLauncher
url = https://github.com/snevesbarros/SafariLauncher.git
[submodule "submodules/libimobiledevice-macosx"]
path = submodules/libimobiledevice-macosx
url = https://github.com/benvium/libimobiledevice-macosx.git
[submodule "submodules/ForceQuitUnresponsiveApps"]
path = submodules/ForceQuitUnresponsiveApps
url = https://github.com/appium/ForceQuitUnresponsiveApps.git
[submodule "submodules/appium-atoms"]
path = submodules/appium-atoms
url = https://github.com/appium/appium-atoms.git
branch = published
[submodule "submodules/appium-instruments"]
path = submodules/appium-instruments
url = https://github.com/appium/appium-instruments.git
branch = published
[submodule "submodules/appium-uiauto"]
path = submodules/appium-uiauto
url = https://github.com/appium/appium-uiauto.git
branch = published
[submodule "submodules/appium-adb"]
path = submodules/appium-adb
url = https://github.com/appium/appium-adb.git
[submodule "submodules/io.appium.android.ime"]
path = submodules/io.appium.android.ime
url = https://github.com/appium/io.appium.android.ime.git
[submodule "submodules/io.appium.settings"]
path = submodules/io.appium.settings
url = https://github.com/appium/io.appium.settings.git
[submodule "submodules/sample-code"]
path = submodules/sample-code
url = https://github.com/appium/sample-code
[submodule "submodules/deviceconsole"]
path = submodules/deviceconsole
url = https://github.com/rpetrich/deviceconsole.git
[submodule "submodules/appium-ci-gulper"]
path = submodules/appium-ci-gulper
url = https://github.com/appium/appium-ci-gulper.git
branch = master
-4
View File
@@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint:commit -- --edit ${1}
-4
View File
@@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint:staged
+13
View File
@@ -0,0 +1,13 @@
{
"excludeFiles": ["submodules/**", "node_modules/**",
"./lib/server/static/**", "./lib/devices/firefoxos/atoms/*.js",
"./sample-code/**", "/Users/baba/Work/appium/ci/standalone-tools/node_modules/**"],
"requireCurlyBraces": ["for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch",
"return", "try", "catch", "function"],
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
}
}
+5
View File
@@ -0,0 +1,5 @@
submodules
node_modules
lib/server/static
lib/devices/firefoxos/atoms
/Users/baba/Work/appium/ci/standalone-tools/node_modules
+11
View File
@@ -0,0 +1,11 @@
{
"laxcomma": true,
"strict": true,
"undef": true,
"unused": true,
"node": true,
"eqeqeq": true,
"trailing": true,
"indent": 2,
"shelljs": false
}
-10
View File
@@ -1,10 +0,0 @@
module.exports = {
'*.(js|ts)': ['eslint --fix', 'prettier --write'],
'appium-config-schema.js': () => [
'npm run --workspace=./packages/schema build',
'git add -A packages/schema/lib/appium-config.schema.json',
'npm run --workspace=./packages/types build',
'git add -A packages/types/lib/appium-config.ts',
],
'!(package|package-lock)*.json': ['prettier --write'],
};
-11
View File
@@ -1,11 +0,0 @@
// @ts-check
'use strict';
module.exports = {
require: [require.resolve('./test/setup.js')],
// forbids use of .only() in CI
forbidOnly: Boolean(process.env.CI),
color: true,
timeout: '5s',
};
+26
View File
@@ -0,0 +1,26 @@
assets/
submodules/
bin/publish.sh
reset.sh
reset.bat
bin/test.sh
sample-code/
test/
lib/devices/android/bootstrap/bin/
lib/devices/android/bootstrap/target/
lib/devices/android/bootstrap/local.properties
lib/devices/android/bootstrap/project.properties
lib/devices/android/bootstrap/.classpath
_vimrc_local.vim
*.swp
*.swo
*~
.*~
.DS_Store
.travis.yml
*.log
*.trace
*.sublime-
*.prefs
.jshintrc
./.npmignore
-4
View File
@@ -1,4 +0,0 @@
# Do not disable package-lock. Disabling package-lock also disables npm-shrinkwrap
package-lock=true
save-exact=true
foreground-scripts=true
-13
View File
@@ -1,13 +0,0 @@
**/node_modules/**
**/build/**
**/fixtures/**
**/*.min.*
**/*.md
package-lock.json
package.json
**/.vscode/**
**/*.html
**/generated/**
# generated
packages/types/lib/appium-config.ts
**/*.hbs
-6
View File
@@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>appium/appium//renovate/default"],
"schedule": ["after 10pm and before 5:00am"],
"timezone": "America/Vancouver"
}
-5
View File
@@ -1,5 +0,0 @@
{
"recommendations": [
"stateful.runme"
]
}
-66
View File
@@ -1,66 +0,0 @@
{
"configurations": [
{
"args": [
"--log-level=debug"
],
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"env": {
"_FORCE_LOGS": "1"
},
"internalConsoleOptions": "openOnSessionStart",
"name": "Run Appium",
"program": "${workspaceFolder}/node_modules/.bin/appium",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"sourceMaps": true,
"type": "node"
},
{
"args": [
"--colors",
"--no-timeout",
"${file}"
],
"autoAttachChildProcesses": true,
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"internalConsoleOptions": "openOnSessionStart",
"name": "Test Current File w/ Mocha",
"program": "${workspaceFolder}/node_modules/.bin/mocha",
"request": "launch",
"runtimeArgs": [
"--require",
"ts-node/register"
],
"skipFiles": [
"<node_internals>/**",
"**/node_modules/mocha/**",
"**/node_modules/lodash/**",
"**/node_modules/ts-node/**"
],
"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"
}
-27
View File
@@ -1,27 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "dev",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$tsc-watch"
],
"label": "npm: dev",
"detail": "npm run dev",
"isBackground": true
},
{
"type": "npm",
"script": "typedoc",
"problemMatcher": [],
"label": "npm: typedoc",
"detail": "typedoc --logLevel Verbose",
"group": "build"
}
]
}
-86
View File
@@ -1,86 +0,0 @@
'use strict';
module.exports = (wallaby) => {
return {
compilers: {
'**/*.js': wallaby.compilers.typeScript({
allowJs: true,
allowSyntheticDefaultImports: true,
resolveJsonModule: true,
isolatedModules: true,
}),
'**/*.ts?(x)': wallaby.compilers.typeScript(),
},
debug: true,
env: {
type: 'node',
},
files: [
'./packages/*/build/**/*',
'./packages/*/lib/**/*.js',
'./packages/*/lib/**/*.ts',
'./packages/*/test/**/*helper*.js',
'./packages/*/test/**/*helper*.ts',
'./packages/*/test/**/*mock*.js',
'./packages/*/test/**/*mock*.ts',
'./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',
},
{
instrument: false,
pattern: './packages/support/test/unit/assets/sample_text.plist',
},
{
instrument: false,
pattern: './packages/base-driver/static/**/*',
},
{
instrument: false,
pattern: './packages/typedoc-plugin-appium/lib/theme/resources/**',
},
{
instrument: false,
pattern: './packages/*/test/**/__snapshots__/**/*',
},
'!./packages/*/test/**/*-specs.js',
'!./packages/*/test/**/*.e2e.spec.js',
'!./packages/*/test/**/*.e2e.spec.ts',
'!**/local_appium_home/**',
],
testFramework: 'mocha',
tests: [
'./packages/*/test/unit/**/*.spec.js',
'./packages/*/test/unit/**/*.spec.ts',
'!**/local_appium_home/**',
],
workers: {
// restart: true,
},
setup(wallaby) {
// copied out of `./test/setup.js`
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinonChai = require('sinon-chai');
// The `chai` global is set if a test needs something special.
// Most tests won't need this.
global.chai = chai.use(chaiAsPromised).use(sinonChai);
// `should()` is only necessary when working with some `null` or `undefined` values.
global.should = chai.should();
const mocha = wallaby.testFramework;
mocha.timeout(10000);
},
runMode: 'onsave',
};
};
-1
View File
@@ -14,7 +14,6 @@ Robin Keller <robinthekeller@gmail.com>
Adam Christian <adam.christian@gmail.com>
Jonathan Lipps <jlipps@gmail.com>
Sebastian Tiedtke <sebastiantiedtke@gmail.com>
Christian Bromann <mail@christian-bromann.com>
Jeremy Avnet <>
Bernard Kobos <bkobos@extensa.pl>
Santiago Suarez Ordoñez <santiycr@gmail.com>
-36
View File
@@ -1,36 +0,0 @@
# Aggregate Changelog
Appium contains many different modules and supports a variety of drivers, plugins and clients, most of which have their own changelogs. Links to these individual changelogs are aggregated here.
## Main Appium Module
* ### [Appium 2.0 Changelog](packages/appium/CHANGELOG.md)
* [Appium 1.x Changelog](https://github.com/appium/appium/blob/1.x/CHANGELOG.md)
## Appium Drivers / Clients / Plugins
* Refer to the [Appium Ecosystem](https://appium.io/docs/en/latest/ecosystem/) page for links to specific driver/client/plugin documentation
* Changelogs for plugins maintained by Appium Team are also linked in the Other Modules section below
## Other Appium Modules
* [base-driver](packages/base-driver/CHANGELOG.md)
* [base-plugin](packages/base-plugin/CHANGELOG.md)
* [doctor](packages/doctor/CHANGELOG.md)
* [docutils](packages/docutils/CHANGELOG.md)
* [driver-test-support](packages/driver-test-support/CHANGELOG.md)
* [eslint-config-appium](packages/eslint-config-appium/CHANGELOG.md)
* [eslint-config-appium-ts](packages/eslint-config-appium-ts/CHANGELOG.md)
* [execute-driver-plugin](packages/execute-driver-plugin/CHANGELOG.md)
* [fake-driver](packages/fake-driver/CHANGELOG.md)
* [fake-plugin](packages/fake-plugin/CHANGELOG.md)
* [images-plugin](packages/images-plugin/CHANGELOG.md)
* [opencv](packages/opencv/CHANGELOG.md)
* [plugin-test-support](packages/plugin-test-support/CHANGELOG.md)
* [relaxed-caps-plugin](packages/relaxed-caps-plugin/CHANGELOG.md)
* [schema](packages/schema/CHANGELOG.md)
* [strongbox](packages/strongbox/CHANGELOG.md)
* [support](packages/support/CHANGELOG.md)
* [test-support](packages/test-support/CHANGELOG.md)
* [tsconfig](packages/tsconfig/CHANGELOG.md)
* [typedoc-plugin-appium](packages/typedoc-plugin-appium/CHANGELOG.md)
* [types](packages/types/CHANGELOG.md)
* [universal-xml-plugin](packages/universal-xml-plugin/CHANGELOG.md)
+1786
View File
File diff suppressed because it is too large Load Diff
-48
View File
@@ -1,48 +0,0 @@
## Code of Conduct
### What is this code of conduct for?
Appium is a piece of technology, but **the core of the Appium community is the people in it**. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, socioeconomic status, religion (or lack thereof), or other marginalized aspect of comunity members. We expect all members of the Appium community to abide by this Code of Conduct whenever interacting in Appium venues (pull requests, GitHub issues, 1-1 or group chat, meetups, conferences, etc...)
### Examples of inappropriate behavior
Because we come from a variety of backgrounds, we don't want to assume that everyone has the same assumptions about what is and isn't appropriate. Here are some examples of inappropriate behavior that are incompatible with our community's ethos:
* Spamming, trolling, intentionally disrupting conversations, or irrelevant solicitation or advertisement
* Making demeaning or discriminatory comments
* Making negative assumptions about someone's background, abilities, or intentions
* Harassing or stalking individuals (online or in person)
* Giving someone unwelcome sexual attention or making unwelcome physical contact (in the case of an IRL event)
* Sharing sexual images or using sexually explicit language
In general: treat others how you would like to be treated, were you in their place. Don't be a jerk. _Do_ ask questions. _Do_ keep conflicts productively focused on technical issues. _Do_ think before you speak; remember that what is perceived as a funny witticism in your group of friends might be hurtful or reinforce hurtful stereotypes in the context of our diverse online community. _Do_ remember that we are all people, not robots, and all equally deserving of sensitivity and respect. (If and when robots join our community, let's treat them with respect too!)
### What will organizers do about inappropriate behavior?
If we notice you doing or saying something inappropriate, an organizer will explain why it's inappropriate and ask you to stop. We won't demonize or vilify you. But please do stop the inappropriate behavior so we can get back to writing and discussing code in a safe environment. If you have philosophical disagreements about what's actually inappropriate, please take them to a separate public or private conversation with an Appium maintainer so we don't turn pull requests into an ethics debate.
If you keep doing unacceptable things, we'll likely ban you, report you to GitHub, or take other appropriate action.
### What if I see or am subject to what feels like inappropriate behavior?
Let us know! Please notify a community organizer as soon as possible. Full contact information is listed in the [Contact Info](#contact-info) section of this document. All communications will be kept strictly confidential, unless otherwise required by law. No issue will be considered too inconsequential or unimportant for us to have a conversation about.
### Contact Info
If you need to report an incident, please contact any of the following organizers directly:
* Isaac Murchie [email](mailto:isaac@saucelabs.com) [twitter](https://twitter.com/imurchie)
* Jonathan Lipps [email](mailto:jlipps@saucelabs.com) [twitter](https://twitter.com/jlipps)
### Credit, License, and Attribution
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
It's inspired among other things by:
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
* [npmjs](https://www.npmjs.com/policies/conduct)
* [Geek Feminism](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy)
* [Ashe Dryden](http://www.ashedryden.com/blog/codes-of-conduct-101-faq)
* [Model View Culture](https://modelviewculture.com/issues/events)
* [Open Source & Feelings](http://osfeels.com/conduct).
+7 -58
View File
@@ -1,63 +1,12 @@
# Contributing to Appium
There are a lot of different ways to contribute to Appium. See below for
everything you can do and the processes to follow for each contribution method.
Note that no matter how you contribute, your participation is governed by our
[Code of Conduct](CONDUCT.md).
Fork the project, make a change, and send a pull request! Please have a look at our
[Style Guide](/docs/en/contributing-to-appium/style-guide.md) before getting to work.
Please make sure the unit and functional tests pass before sending a pull request; for more
information on how to run tests, keep reading!
### Make changes to the Appium code or docs
Make sure you read and follow the setup instructions in the README first.
Fork the project, make a change, and send a pull request! Please have a look at
our [Style Guide](/docs/en/contributing-to-appium/style-guide.md) before
getting to work. Please make sure the unit and functional tests pass before
sending a pull request; for more information on how to run tests, keep reading!
### Running Appium from Source and doing dev on Appium
Make sure you read and follow the setup instructions in the README first. And note
that all participation in the Appium community (including code submissions) is
governed by our [Code of Conduct](CONDUCT.md). Then, have a look at our
[running from source doc](/docs/en/contributing-to-appium/appium-from-source.md) for more
information on how to get set up to run tests and start slinging code.
You will probably also want to have a look at this more in-depth [Developer's
Overview](/docs/en/contributing-to-appium/developers-overview.md) of the Appium
project, how Appium is architected, how to make changes to modules, and so on.
Finally, before we accept your code, you will need to have signed our
[Contributor License
Agreement](https://cla.js.foundation/appium/appium).
### Become an Appium Triager
You can help us manage our issue tracker! All you need is enough familiarity
with Appium to try and reproduce bugs. We triage issues by having conversations
with the issue creator and then either closing the issue or moving it into the
[Bugs](https://github.com/appium/appium/milestones/Bugs) or
[Features](https://github.com/appium/appium/milestones/Features) milestone. We
use these buckets as the backlogs for our upcoming releases.
We use this "algorithm" for triaging issues, which anyone can jump in and follow:
1. If issue is a feature request, discuss amongst Appium devs.
* If we decide to build it, add to the Features milestone.
* If we decide not to build it, just close.
2. If issue is a bug report, attempt to verify
* If it's a duplicate, close with link to bug already reported.
* If it ultimately can't be verified, close until we have enough information to verify (e.g., in most cases we need a full set of Appium logs to help diagnose an issue).
* If the user hasn't provided enough information, keep asking for enough information to verify.
* If it's a verified new bug, add it to the Bugs milestone.
* If we have been waiting for a reply from the user for over 3 weeks, close.
If you're interested in joining our triage rotation, contact
[@jlipps](https://github.com/jlipps) or
[@imurchie](https://github.com/imurchie).
### Help out on our forums
We can always use help on our forums at
[discuss.appium.io](https://discuss.appium.io)! Hop on over and see if there
are any questions that you can answer.
### Submit bug reports or feature requests
Just use the GitHub issue tracker to submit your bug reports and feature
requests. If you are submitting a bug report, please follow the [issue template](https://github.com/appium/appium/issues/new).
This is all detailed in our [running from source doc](/docs/en/contributing-to-appium/appium-from-source.md)
-108
View File
@@ -1,108 +0,0 @@
# Appium Project Governance
The Appium Project wants as much as possible to operate using procedures that
are fair, open, inviting, and ultimately good for the community. For that
reason we find it valuable to codify some of the ways that the Project goes
about its day-to-day business. We want to make sure that no matter who you are,
you have the opportunity to contribute to Appium. We want to make sure that no
one corporation can exert undue influence on the community or hold the Project
hostage. And likewise we want to make sure that corporations which benefit from
Appium are also incentivized to give back.
### The Technical Committee
The project is officially led by a Technical Committee (TC), currently
consisting of:
* [@jlipps](https://github.com/jlipps)
* [@bootstraponline](https://github.com/bootstraponline)
* [@penguinho](https://github.com/penguinho)
* [@dandoveralba](https://github.com/dandoveralba)
* [@mykola-mokhnach](https://github.com/mykola-mokhnach)
* [@imurchie](https://github.com/imurchie)
* [@TikhomirovSergey](https://github.com/TikhomirovSergey)
* [@KazuCocoa](https://github.com/KazuCocoa)
They all represent different companies and different types of contribution to
the Appium Project. The TC is responsible for high-level decisions (like
establishing a feature roadmap, accepting sponsorship, organizing conferences,
etc...), adjudicating conflicts between members of the community, and making
changes to the project's governance processes.
* Membership in the TC is granted by unanimous vote of current TC members.
* TC members can step down at any time.
* No more than 1/3 of TC members may belong to the same company.
* Changes to project governance require unanimous vote of the TC.
### Project Committers
Most of the project maintenance is handled by committers, community members who
have been granted commit access to the Appium organization on GitHub. The
responsibilities of committers include: reviewing and merging pull requests,
walking through changes with developers, weighing in on architectural issues,
and so on.
* Any two TC members can decide to make someone a project committer, providing that person has shown an appropriate understanding of the Appium codebase through prior contributions of code.
* In general any committer can review and merge a PR. In general committers should only merge code they are qualified to review, which might entail pinging another committer who has greater ownership over a specific code area.
* Debates between committers about whether code should be merged should happen in GitHub pull requests.
* Proposals for large changes to the project's code (architectural changes, etc...) should be brought forward as a GitHub issue (with the label `Proposal`), and all committers should be pinged so they can weigh in on the discussion if desired. Substantial changes, whether in proposal stage or in pull request stage should be signed off on by 1 TC member and at least 2 other committers. To assist in the discussion, a small proof of concept can be undertaken on a subset of the Appium ecosystem and raised as a strawman PR, to give flesh to the proposal and make discussion more helpfully concrete.
* In general disputes about code should be resolved by discussion, not votes. If there is substantial disagreement, aim for consensus. If that is not possible, committers can bring the dispute to the TC for a vote, with the outcome determined by a majority.
* Any committer can decide to close a PR or issue if they determine the change doesn't suit the project.
* Appium has a large ecosystem of repositories. Some are 'core' in the sense of being central subpackages with a lot of traffic like `appium/appium` or `appium/appium-ios-driver`. Others are 'peripheral' in the sense of receiving few changes, being maintained by 1 person or no one, etc..., like `appium/ruby_lib` or `appium/appium_thor` For 'core' repos, committers should not merge their own code straightaway. Like all contributors they should open a PR and get a +1 from another committer. For 'peripheral' repos for which they are the sole maintainer or for which they have a good understanding, it is obtuse to insist on another contributor's +1 and this rule should be relaxed in that case. In sum: use good judgment and don't ram code through without a review when you can help it.
The current committers are (in addition to the TC members above):
* [@hugs](https://github.com/hugs)
* [@filmaj](https://github.com/filmaj)
* [@aluedeke](https://github.com/aluedeke)
* [@sebv](https://github.com/sebv)
* [@vgrigoruk](https://github.com/vgrigoruk)
* [@DylanLacey](https://github.com/DylanLacey)
* [@maudineormsby](https://github.com/maudineormsby)
* [@titusfortner](https://github.com/titusfortner)
* [@bayandin](https://github.com/bayandin)
* [@jdeff](https://github.com/jdeff)
* [@moizjv](https://github.com/moizjv)
* [@gempesaw](https://github.com/gempesaw)
* [@Jonahss](https://github.com/Jonahss)
* [@JamieEdge](https://github.com/JamieEdge)
* [@saikrishna321](https://github.com/saikrishna321)
* [@sravanmedarapu](https://github.com/sravanmedarapu)
* [@peepa](https://github.com/peepa)
* [@scottdixon](https://github.com/scottdixon)
* [@drpy](https://github.com/drpy)
* [@Astro03](https://github.com/Astro03)
* [@sbonebrake](https://github.com/sbonebrake)
* [@SrinivasanTarget](https://github.com/SrinivasanTarget)
* [@triager](https://github.com/triager)
* [@ddkjin](https://github.com/ddkjin)
* [@stuartbrussell-intuit](https://github.com/stuartbrussell-intuit)
* [@vmaxim](https://github.com/vmaxim)
* [@Dan-Maor](https://github.com/Dan-Maor)
* [@laolubenson](https://github.com/laolubenson)
* [@Dor-bl](https://github.com/Dor-bl)
* [@boneskull](https://github.com/boneskull)
* [@mwakizaka](https://github.com/mwakizaka)
* [@rerorero](https://github.com/rerorero)
* [@tomriddly](https://github.com/tomriddly)
* [@eglitise](https://github.com/eglitise)
### Contributors
Other, less formal, kinds of contribution are outlined in our
[CONTRIBUTING](/CONTRIBUTING.md) doc.
### Sponsorship
The Appium project welcomes sponsorship of various organizations. Specific
details are not yet available but in general we will accept monetary donations,
contribution of code, contribution of dedicated committers, or donations of
other goods or service (internet hosting, etc...). To begin the conversation,
reach out to one of the TC members.
### Raising Issues Related to Governance
This governance model necessarily leaves many situations unspecified. If
questions arise as to how a given situation should proceed according to the
overall goals of the project, the best thing to do is to open a GitHub issue
and ping the TC members.
+127
View File
@@ -0,0 +1,127 @@
"use strict";
var path = require('path')
, gruntHelpers = require('./grunt-helpers.js')
, authorize = gruntHelpers.authorize
, tail = gruntHelpers.tail
, buildApp = gruntHelpers.buildApp
, buildSafariLauncherApp = gruntHelpers.buildSafariLauncherApp
, signApp = gruntHelpers.signApp
, setupAndroidBootstrap = gruntHelpers.setupAndroidBootstrap
, setupAndroidApp = gruntHelpers.setupAndroidApp
, buildAndroidBootstrap = gruntHelpers.buildAndroidBootstrap
, buildSelendroidServer = gruntHelpers.buildSelendroidServer
, buildAndroidApp = gruntHelpers.buildAndroidApp
, buildSelendroidAndroidApp = gruntHelpers.buildSelendroidAndroidApp
, fixSelendroidAndroidManifest = gruntHelpers.fixSelendroidAndroidManifest
, installAndroidApp = gruntHelpers.installAndroidApp
, generateServerDocs = gruntHelpers.generateServerDocs
, generateAppiumIo = gruntHelpers.generateAppiumIo
, setDeviceConfigVer = gruntHelpers.setDeviceConfigVer
, setBuildTime = gruntHelpers.setBuildTime
, getSampleCode = gruntHelpers.getSampleCode
, setGitRev = gruntHelpers.setGitRev
, getGitRev = require('./lib/helpers').getGitRev;
var GULP_BIN = 'node_modules/.bin/gulp';
module.exports = function (grunt) {
grunt.initConfig({
mochaTest: {
appiumutils: ['test/functional/appium/appiumutils.js']
}
, mochaTestConfig: {
options: {
timeout: 60000,
reporter: 'spec'
}
}
, maxBuffer: 2000 * 1024
, exec: {
'gulp-test-unit': GULP_BIN + ' test-unit --color',
'gulp-jshint': GULP_BIN + ' jshint --color',
'gulp-jscs': GULP_BIN + ' jscs --color',
'gulp-lint': GULP_BIN + ' lint --color'
},
});
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-exec');
grunt.registerTask('jshint', 'exec:gulp-jshint');
grunt.registerTask('jscs', 'exec:gulp-jscs');
grunt.registerTask('lint', 'exec:gulp-lint');
grunt.registerTask('test', 'exec:gulp-test-unit');
grunt.registerTask('unit', 'exec:gulp-test-unit');
grunt.registerTask('default', ['test']);
grunt.registerTask('travis', ['jshint','jscs', 'unit']);
grunt.registerTask('buildApp', "Build the test app", function (appDir, sdk) {
buildApp(appDir, this.async(), sdk);
});
grunt.registerTask('buildSafariLauncherApp', "Build the SafariLauncher app", function (sdk, xcconfig) {
buildSafariLauncherApp(this.async(), sdk, xcconfig);
});
grunt.registerTask('signApp', "Sign the test app", function (certName) {
signApp("TestApp", certName, this.async());
});
grunt.registerTask('authorize', "Authorize developer", function (insecure) {
authorize(grunt, insecure, this.async());
});
grunt.registerTask('log', "Tail appium.log", function () {
tail(grunt, path.resolve(__dirname, "appium.log"), this.async());
});
grunt.registerTask('configAndroidBootstrap', function () {
setupAndroidBootstrap(grunt, this.async());
});
grunt.registerTask('buildAndroidBootstrap', function () {
buildAndroidBootstrap(grunt, this.async());
});
grunt.registerTask('buildSelendroidServer', function () {
buildSelendroidServer(this.async());
});
grunt.registerTask('fixSelendroidAndroidManifest', function () {
var destDir = path.resolve(__dirname, "build", "selendroid");
var dstManifest = path.resolve(destDir, "AndroidManifest.xml");
fixSelendroidAndroidManifest(dstManifest, this.async());
});
grunt.registerTask('configAndroidApp', function (appName) {
setupAndroidApp(grunt, appName, this.async());
});
grunt.registerTask('buildAndroidApp', function (appName) {
buildAndroidApp(grunt, appName, this.async());
});
grunt.registerTask('buildSelendroidAndroidApp', function (appName) {
buildSelendroidAndroidApp(grunt, appName, this.async());
});
grunt.registerTask('installAndroidApp', function (appName) {
installAndroidApp(grunt, appName, this.async());
});
grunt.registerTask('docs', function () {
generateServerDocs(grunt, this.async());
});
grunt.registerTask('generateAppiumIo', function () {
generateAppiumIo(grunt, this.async());
});
grunt.registerTask('setConfigVer', function (device) {
setDeviceConfigVer(grunt, device, this.async());
});
grunt.registerTask('setBuildTime', function () {
setBuildTime(grunt, this.async());
});
grunt.registerTask('getSampleCode', function (hardcore) {
if (typeof hardcore !== "undefined" && hardcore === "hardcore") {
hardcore = true;
}
getSampleCode(grunt, hardcore, this.async());
});
grunt.registerTask('setGitRev', function (rev) {
var done = this.async();
if (typeof rev === "undefined") {
getGitRev(function (err, rev) {
if (err) throw err;
setGitRev(grunt, rev, done);
});
} else {
setGitRev(grunt, rev, done);
}
});
};
-16
View File
@@ -1,16 +0,0 @@
Google Summer of Code Ideas
=====
Appium is excited to participate as a [Google Summer of Code](https://summerofcode.withgoogle.com/) sponsor project. Here's a fun list of ideas that a Summer of Code student participant can use as a foundation for thinking about what to contribute to Appium!
|Idea|Description|
|----|-----------|
|Apple tvOS Support|Our users have been asking for an Appium driver for Apple tvOS apps. Is this possible? We're not entirely sure! Why not be awesome and build it?|
|Test App revamp|Appium uses a number of poorly-designed mobile applications in its own testing. We have to use a variety of apps because we need to test that Appium can automate all the various controls and platform features that mobile vendors provide. Really what we need is one cross-platform app (or one app per platform) that exhibit all and only the features we need to test. This would be a fun project to build some mobile apps used for testing and also demoing Appium at events and in training videos, etc...|
|Tooling and Performance|We haven't instrumented Appium with very many performance metrics, and don't really know if we're missing some low-hanging fruit in terms of performance. Maybe you can help us do that?|
|Babel|We have a lot of repos, and they're all on a really old version of Babel. They all need to stay in sync. How can we make this situation better, and upgrade to the latest and greatest?|
|Unity3d Driver|Historically, Appium hasn't been great at automating games. We don't have any particular support for the frameworks used to create games. Unity is a popular one, for example. What if we could write an Appium driver that talked to an embedded process in a test version of a Unity game, that allowed us to find and interact with 3d elements? It would be amazing! You can also be amazing and lead Appium into this new world.|
|Testing the Internet of Things|Appium's architecture makes it dead simple to integrate drivers for automating new technologies. What about _really_ new technologies like IoT devices? Help to redefine the semantics of the WebDriver protocol for use with IoT, and build a driver for an IoT device to prove it out.|
|Driver for X|Have an idea of something else Appium could automate that it doesn't already? Build a driver for it! This would involve some awesome Node.js code, plus whatever else is needed to integrate with the platform you have in mind.|
Hopefully this gives you some ideas of fun projects that would be substantial and long-lasting contributions to the Appium community.
+1 -189
View File
@@ -1,192 +1,4 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
Copyright 2012-2013 Appium Committers
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+116 -179
View File
@@ -1,212 +1,149 @@
## Appium
[![NPM version](https://badge.fury.io/js/appium.svg)](https://npmjs.org/package/appium)
[![Monthly Downloads](https://img.shields.io/npm/dm/appium.svg)](https://npmjs.org/package/appium)
[![NPM version](https://badge.fury.io/js/appium.png)](https://npmjs.org/package/appium)
[![Dependency Status](https://david-dm.org/appium/appium.svg)](https://david-dm.org/appium/appium)
[![devDependency Status](https://david-dm.org/appium/appium/dev-status.svg)](https://david-dm.org/appium/appium#info=devDependencies)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_shield)
[![Build Status](https://team-appium.ci.cloudbees.com/job/appium-master/badge/icon)](https://team-appium.ci.cloudbees.com/job/appium-master/)
[![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://github.com/vshymanskyy/StandWithUkraine/)
Appium is an open source, cross-platform test automation tool for native, hybrid and mobile web apps, tested on simulators (iOS, FirefoxOS), emulators (Android), and real devices (iOS, Android, FirefoxOS).
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://vshymanskyy.github.io/StandWithUkraine/)
**Note:** we have just recently released Appium 1.0. If you already have a bunch of Appium tests, you might want to check out the [Migrating to 1.0](/docs/en/advanced-concepts/migrating-to-1-0.md) doc!
Appium is an open-source, cross-platform test automation tool for native,
hybrid, mobile web and desktop apps. Initially created to automate iOS and Android mobile
applications Appium has grown to a full-featured platform that provides [WebDriver](https://www.w3.org/TR/webdriver/)-based automation possibilities for the whole set of different mobile and desktop platforms.
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.
### Supported Platforms
:bangbang: The current Appium 2.0 documentation can be found [here](https://appium.io/docs/en/latest/).
* iOS
* Android
* FirefoxOS
: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.
### Requirements
- macOS, Linux or Windows operating system
- Node.js 16+. Any relevant [LTS release](https://nodejs.dev/en/about/releases/) should work just fine.
- NPM (Node Package Manager) 8+
These are only server requirements. Each driver might have its own requirements. Consider checking the corresponding driver tutorial for more details.
### Server
To install Appium 2 server using Node Package Manager (npm) run the following command:
```bash
npm i --location=global appium
```
To update Appium 2 server using Node Package Manager (npm) run the following command:
```bash
npm install --location=global 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.
### Drivers
Appium supports app automation across a variety of platforms, like iOS,
Android, and Windows. Each platform is supported by one or more "drivers",
which know how to automate that particular platform. Since version 2.0
all drivers have been isolated from the Appium server app and can
be managed independently using the [appium driver](https://appiumpro.com/editions/122-installing-appium-20-and-the-driver-and-plugins-cli) command line interface.
In general, the drivers management in Appium 2 is as simple as:
```bash
# To install a new driver from npm
appium driver install --source=npm appium-xcuitest-driver[@<version>]
# To install a driver from a local folder (useful for developers)
appium driver install --source=local /Users/me/sources/appium-xcuitest-driver
# To install a new driver from github (hm, maybe it's time to publish it to NPM?)
appium driver install --source=github --package=appium-xcuitest-driver appium/appium-xcuitest-driver
# To list already installed drivers
appium driver list --installed
# To update a driver (it must be already installed)
appium driver update xcuitest
# To uninstall a driver (it won't last forever, wouldn't it?)
appium driver uninstall xcuitest
```
You can find a 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 at
the current Appium 2.0 documentation.
### Plugins
The concept of plugins is something new that has been added exclusively to Appium2. Plugins allow you to extend server functionality without changing the server code. Plugins could be managed similarly to drivers:
```bash
# To install an officially supported plugin
appium plugin install images
# To install a plugin from a local folder (useful for developers)
appium plugin install --source=local /Users/me/sources/images
# To install a new plugin from npm
appium plugin install --source=npm appium-device-farm
# To list already installed plugins
appium plugin list --installed
# To update a plugins (it must be already installed)
appium plugin update appium-device-farm
# To uninstall a plugin
appium plugin uninstall appium-device-farm
```
The main difference between drivers and plugins is that the latter must be explicitly enabled on server startup after it was installed (drivers are enabled by default after installation):
```bash
appium server --use-plugins=device-farm,images
```
You can find a full list of
[officially-supported](https://appium.io/docs/en/latest/ecosystem/#plugins) and
[third-party](https://appium.io/docs/en/latest/ecosystem/#other-plugins) plugins at
the current Appium 2.0 documentation.
### Server Command Line Interface
In order to start sending commands to Appium over the wire it must be listening
on the URL where your client library expects it to listen.
Use the following commands to run and configure Appium server:
```bash
# Start the server on the default port and host (e.g. http://0.0.0.0:4723/)
appium server
# Start the server on the given port, host and use the base path prefix (the default prefix is /)
appium server -p 9000 -a 127.0.0.1 -pa /wd/hub
# Get the list of all supported command line parameters.
# This list would also include descriptions of driver-specific
# command line arguments for all installed drivers.
# Each driver and plugin must have their command line arguments
# exposed in a special JSON schema declared as a part of the corresponding
# package.json file.
appium server --help
```
Appium supports execution of parallel server processes as well as parallel driver sessions within
single server process. Refer the corresponding driver documentations regarding which mode is optimal
for the particular driver or whether it supports parallel sessions.
See the [platform support doc](/docs/en/appium-setup/platform-support.md) for more detailed information.
### Why Appium?
1. You usually don't have to recompile your app or modify it in any way, due
to the use of standard automation APIs on all platforms.
2. You can write tests with your favorite dev tools using any
[WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html)-compatible
language such as [Java](https://github.com/appium/java-client),
[JavaScript](https://webdriver.io/), [Python](https://github.com/appium/python-client),
[Ruby](https://github.com/appium/ruby_lib), [C#](https://github.com/appium/dotnet-client)
with the Selenium WebDriver API. There are also various third party
client implementations for other languages.
1. You don't have to recompile your app or modify it in any way, due
to use of standard automation APIs on all platforms.
2. You can write tests with your favorite dev tools using any [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol)-compatible
language such as Java, [Objective-C](https://github.com/appium/selenium-objective-c),
JavaScript with Node.js (in [promise, callback](https://github.com/admc/wd) or [generator](https://github.com/jlipps/yiewd) flavors),
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, or Perl
with the Selenium WebDriver API and language-specific client libraries.
3. You can use any testing framework.
4. Some drivers, like xcuitest and uiautomator2 ones have built-in mobile web and
hybrid app support. Within the same script, you can switch seamlessly between native
app automation and webview automation, all using the WebDriver model that's already
the standard for web automation.
5. You can run your automated tests locally and in a cloud. There are multiple
cloud providers that support various Appium drivers (mostly
targeting iOS and Android mobile automation).
6. [Appium Inspector](https://github.com/appium/appium-inspector) allows
visual debugging of automated tests and could be extremely useful for
beginners.
Investing in the
[WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) protocol means
you are betting on a single, free, and open protocol for testing that has become
a web standard. Don't lock yourself into a proprietary stack.
Investing in the [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol) protocol means you are betting on a single, free and open protocol for testing that has become a defacto standard. Don't lock yourself into a proprietary stack.
For example, if you use Apple's XCUITest library without Appium you can only
write tests using Obj-C/Swift, and you can only run tests through Xcode.
Similarly, with Google's UiAutomator or Espresso, you can only write tests in
Java/Kotlin. Appium opens up the possibility of true cross-platform native app
automation, for mobile and beyond. Finally!
If you use Apple's UIAutomation library without Appium you can only write tests
using JavaScript and you can only run tests through the Instruments application.
Similarly, with Google's UiAutomator you can only write tests in Java. Appium
opens up the possibility of true cross-platform native mobile automation. Finally!
If you're new to Appium or want a more comprehensive description of what this is all
about, please read our [Intro to Appium](https://appium.io/docs/en/latest/intro/).
### I don't get it yet...
### Quickstart
If you're new to Appium, or want a fuller description of what this is all about, please read our [Introduction to Appium Concepts](/docs/en/about-appium/intro.md).
Check out our [Quickstart](https://appium.io/docs/en/latest/quickstart/) guide
to get going with Appium.
### Requirements
There is also a sample code that contains [many examples of tests in a variety
of different languages](https://github.com/appium/appium/tree/1.x/sample-code)!
Your environment needs to be setup for the particular mobile platforms that you
want to run tests on. See below for particular platform requirements.
### Documentation
If you want to run Appium via an `npm install`, hack with or contribute to Appium, you will need
[node.js and npm](http://nodejs.org) 0.10 or greater (use [n](https://github.com/visionmedia/n) or
`brew install node` to install Node.js. Make sure you have not installed Node or Appium with `sudo`,
otherwise you'll run into problems). We recommend the latest stable version.
For prettily-rendered docs, please visit [Appium Documentation](https://appium.io).
You can always find the full list of Appium doc pages at [Appium's GitHub
Repo](https://github.com/appium/appium/tree/master/packages/appium/docs) as well.
To verify that all of Appium's dependencies are met you can use `appium-doctor`.
Run `appium-doctor` and supply the `--ios` or `--android` flags to verify that all
of the dependencies are set up correctly. If running from source, you may have to use
`./bin/appium-doctor.js` or `node bin/appium-doctor.js`.
You also need to download the Appium client for your language so you can write tests. The Appium clients are simple extensions to the WebDriver clients. You can see the list of clients and links to download instructions at the [Appium clients list](/docs/en/about-appium/appium-clients.md).
#### iOS Requirements
* Mac OS X 10.7 or higher, 10.9.2 recommended
* XCode &gt;= 4.6.3, 5.1.1 recommended
* Apple Developer Tools (iPhone simulator SDK, command line tools)
* [Ensure you read our documentation on setting yourself up for iOS testing!](/docs/en/appium-setup/running-on-osx.md)
#### Android Requirements
* [Android SDK](http://developer.android.com) API &gt;= 17 (Additional features require 18/19)
* Appium supports Android on OS X, Linux and Windows. Make sure you follow the
directions for setting up your environment properly for testing on different OSes:
* [linux](/docs/en/appium-setup/running-on-linux.md)
* [osx](/docs/en/appium-setup/running-on-osx.md)
* [windows](/docs/en/appium-setup/running-on-windows.md)
#### FirefoxOS Requirements
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
### Quick Start
Kick up an Appium server, and then run a test written in your favorite [WebDriver](https://code.google.com/p/selenium/wiki/JsonWireProtocol)-compatible language!
You can run an Appium server using node.js or using the application, see below.
#### Using Node.js
```center
$ npm install -g appium
$ appium &
```
#### Using the App
* [Download the Appium app](https://github.com/appium/appium/releases)
* Run it!
### Writing Tests for Appium
The main guide for getting started writing and running tests is [the running tests](/docs/en/writing-running-appium/running-tests.md) doc, which includes explanations for iOS, Android, and Android older devices. If you're interested in testing on physical hardware, you might be interested in our [real devices guide](/docs/en/appium-setup/real-devices.md).
Essentially, we support a subset of the [Selenium WebDriver JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol), and extend it so that you can specify mobile-targeted [desired capabilities](/docs/en/writing-running-appium/caps.md) to run your test through Appium.
You find elements by using a subset of WebDriver's element-finding strategies.
See [finding elements](/docs/en/writing-running-appium/finding-elements.md) for detailed information. We also have several extensions to the JSON Wire Protocol for [automating mobile gestures](/docs/en/writing-running-appium/touch-actions.md) like tap, flick, and swipe.
You can also automate web views in hybrid apps! See the [hybrid app guide](/docs/en/advanced-concepts/hybrid.md)
This repository contains [many examples of tests in a variety of different languages](https://github.com/appium/sample-code)!
For the full list of Appium doc pages, visit [this directory](/docs/en/).
### How It Works
Appium drives various native automation frameworks and provides an API based on
Selenium's [WebDriver JSON wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol).
Appium drives Apple's UIAutomation library for iOS support, which is based on
[Dan Cuellar's](http://github.com/penguinho) work on iOS Auto.
Android support uses the UiAutomator framework for newer platforms and
[Selendroid](http://github.com/DominikDary/selendroid) for older Android platforms.
FirefoxOS support leverages [Marionette](https://developer.mozilla.org/en-US/docs/Marionette),
an automation driver that is compatible with WebDriver and is used to automate
Gecko-based platforms.
### Contributing
Please take a look at our [contribution documentation](CONTRIBUTING.md)
for instructions on how to build, test, and run Appium from the source.
for instructions on how to build, test and run Appium from source.
### Project History, Credits & Inspiration
### Project Credits & Inspiration
* [History](https://appium.io/docs/en/latest/intro/history/)
[Credits](/docs/en/contributing-to-appium/credits.md)
### User Forums
### Mailing List
Announcements and debates often take place on the [Discussion Group](https://discuss.appium.io),
be sure to sign up!
Announcements and debates often take place on the [Discussion Group](https://discuss.appium.io), be sure to sign up!
### Troubleshooting
Please find the troubleshooting guide at the corresponding driver repository/documentation.
We put together a [troubleshooting guide](/docs/en/appium-setup/troubleshooting.md).
Please have a look here first if you run into any problems. It contains instructions for checking a lot
of common errors and how to get in touch with the community if you're stumped.
### License
### Using Robots
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_large)
Using Appium with [Tapster](https://github.com/hugs/tapsterbot) and other robots is possible,
check out the [Appium Robots](https://github.com/appium/robots) project!
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env node
"use strict";
var IOSChecker = require('../lib/doctor/ios.js').IOSChecker
, AndroidChecker = require('../lib/doctor/android.js').AndroidChecker
, DevChecker = require('../lib/doctor/dev.js').DevChecker
, common = require("../lib/doctor/common.js")
, eol = require('os').EOL
, async = require('async')
, isMac = process.platform === 'darwin';
// , isWindows = process.platform === 'win32';
var argv = process.argv
, doAndroid = argv.indexOf('--android') > -1
, doIOS = argv.indexOf('--ios') > -1
, doDev = argv.indexOf('--dev') > -1
// , verbose = argv.indexOf('--verbose') > -1
, broadcast = argv.indexOf('--port') > -1
, port = null;
if (broadcast) {
port = argv[argv.indexOf("--port") + 1];
}
if (!doIOS && !doAndroid) {
doIOS = isMac;
doAndroid = true;
}
var log = new common.Log(port);
var runiOSChecks = function (cb) {
if (doIOS) {
if (!isMac) {
log.fail("iOS Checks cannot be run on Windows.");
log.exitDoctor();
}
var iosChecker = new IOSChecker(log);
log.comment("Running iOS Checks");
iosChecker.runAllChecks(function (err) {
if (!err) {
log.pass("iOS Checks were successful." + eol);
cb();
} else {
log.exitDoctor();
}
});
} else {
cb();
}
};
var runAndroidChecks = function (cb) {
if (doAndroid) {
var androidChecker = new AndroidChecker(log);
log.comment("Running Android Checks");
androidChecker.runAllChecks(function (err) {
if (!err) {
log.pass("Android Checks were successful." + eol);
cb();
} else {
log.exitDoctor();
}
});
} else {
cb();
}
};
var runDevChecks = function (cb) {
if (doDev) {
var devChecker = new DevChecker(log);
log.comment("Running Dev Checks");
devChecker.runAllChecks(function (err) {
if (!err) {
log.pass("Dev Checks were successful." + eol);
cb();
} else {
log.exitDoctor();
}
});
} else {
cb();
}
};
if (require.main === module) {
var mainMethod = function () {
async.series([
runiOSChecks,
runAndroidChecks,
runDevChecks
], function (err) {
if (!err) {
log.pass("All Checks were successful");
log.stopBroadcast();
} else {
log.exitDoctor();
}
});
};
if (log.broadcast) {
log.startBroadcast(mainMethod);
} else {
mainMethod();
}
}
Executable
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env node
"use strict";
var net = require('net')
, repl = require('repl')
, logFactory = require('../lib/server/logger.js')
, parser = require('../lib/server/parser.js');
require('colors');
var args = parser().parseArgs();
logFactory.init(args);
var appium = require('../lib/server/main.js');
var startRepl = function () {
var help = function () {
console.log("\nWelcome to the Appium CLI".cyan);
console.log(" - Access the appium object via the object: 'appium'".grey);
console.log(" - appium.run is the function to start the server".grey);
console.log(" - args is the default params data structure".grey);
console.log(" - set args.app then run appium.run(args);\n".grey);
return 'Thanks for asking';
};
help();
var r = repl.start('(appium): ');
r.context.appium = appium;
r.context.parser = parser();
r.context.help = help;
r.context.args = {
app: '/path/to/test/app'
, udid: null
, address: '127.0.0.1'
, port: 4723
};
var connections = 0;
var server = net.createServer(function (socket) {
connections += 1;
socket.setTimeout(5 * 60 * 1000, function () {
socket.destroy();
});
repl.start("(appium): ", socket);
}).listen(process.platform === "win32" ? "\\\\.\\pipe\\node-repl-sock-" + process.pid : "/tmp/node-repl-sock-" + process.pid);
r.on('exit', function () {
server.close();
process.exit();
});
};
if (process.argv[2] && process.argv[2].trim() === "--shell") {
startRepl();
} else {
appium.run(args, function () { /* console.log('Rock and roll.'.grey); */ });
}
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env node
"use strict";
var authorize = require('../grunt-helpers.js').authorize;
var gruntMock = {
fatal: function (msg) {
console.error(msg);
process.exit(0);
},
log: {
writeln: function (msg) {
console.log(msg);
}
}
};
if (require.main === module) {
authorize(gruntMock, false, function (err) {
if (err) throw err;
console.log("Authorization successful");
});
}
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env node
/*
* Small tool, launching and monitoring ios-web-kit-proxy, and relauching
* on predefined errors.
*
* Usage:
* ./bin/ios-webkit-debug-proxy-launcher.js [args]
* args: ios-webkit-debug-proxy args (they will be passed over)
*
* Example:
* ./bin/ios-webkit-debug-proxy-launcher.js -c <UDID>:27753 -d
*
* Note:
* For iOS8.1 try this first:
* brew install --HEAD ideviceinstaller
*/
"use strict";
var spawn = require('child_process').spawn,
_ = require('underscore');
var args = process.argv.slice(2);
var RESTART_ON_MESSAGES = [
'Invalid message _rpc_applicationUpdated',
'Invalid message _rpc_applicationSentListing'];
var PROXY_CMD = 'ios_webkit_debug_proxy';
function startProxy() {
console.log('RUNNING:', PROXY_CMD, args.join(' '));
var proxy = spawn(PROXY_CMD, args);
proxy.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
proxy.stderr.on('data', function (data) {
console.log('stderr: ' + data);
var restartMessage = _(RESTART_ON_MESSAGES).find(function (message) {
return ('' + data).indexOf(message) >= 0;
});
if (restartMessage) {
console.log('Detected error message:', restartMessage);
console.log('Killing proxy!');
proxy.kill('SIGTERM');
process.nextTick(startProxy);
}
});
proxy.on('close', function (code) {
console.log('child process exited with code ' + code);
});
}
startProxy();
Executable
+76
View File
@@ -0,0 +1,76 @@
#!/bin/bash
ACTION='usage'
ALL_PACKAGES=(
'appium-atoms'
'appium-instruments'
'appium-uiauto'
'appium-adb'
)
PACKAGES=()
for i in "$@"
do
case $i in
-l|--link)
ACTION='link'
shift
;;
-u|--unlink)
ACTION='unlink'
shift
;;
-m|--master)
MASTER=true
shift
;;
*)
PACKAGES+=($i)
shift
;;
esac
done
if [[ ${#PACKAGES[*]} == 0 ]]; then
PACKAGES=("${ALL_PACKAGES[@]}")
fi
function npmlink {
git submodule update --init submodules/$1
pushd submodules/$1
if [[ $MASTER ]]; then
git checkout master
fi
npm link
popd
npm link $1
}
if [[ $ACTION == 'usage' ]]; then
echo 'Usage:'
echo ' link all: dev.sh --link [--master]'
echo ' unlink all: dev.sh --unlink'
echo ' link specific packages: dev.sh --link [--master] <pkg1> <pkg2>...'
echo ' unlink specific packages: dev.sh --unlink <pkg1> <pkg2>...'
echo 'Short verion:'
echo ' link all: dev.sh -l [-m]'
echo ' unlink all: dev.sh -u'
echo ' link specific packages: dev.sh -l [-m] <pkg1> <pkg2>...'
echo ' unlink specific packages: dev.sh -u <pkg1> <pkg2>...'
fi
if [[ $ACTION == 'link' ]]; then
for i in "${PACKAGES[@]}"
do
npmlink $i
done
fi
if [[ $ACTION == 'unlink' ]]; then
for i in "${PACKAGES[@]}"
do
npm unlink $i
done
fi
Executable
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
set +e
if [[ "$1" = "" ]]; then
branch="master"
else
branch="$1"
fi
XCODE_PATH=$(xcode-select -print-path)
if test -d $XCODE_PATH/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk; then
echo "Confirmed iOS7.1 SDK available"
else
echo "You don't have iOS 7.1 SDK available. Switch to Xcode 5?"
exit 1
fi
node --version | grep "v0.10" >/dev/null
if [ $? -gt 0 ]; then
echo "You need to publish Appium using Node 0.10.x, not $(node --version)"
exit 1;
else
echo "Node version OK"
fi
git remote | grep "upstream" >/dev/null
if [ $? -gt 0 ]; then
echo "You need to have an 'upstream' remote to pull from / push tags to"
exit 1
else
echo "Git remote OK"
fi
git status | grep -E "nothing to commit.+working directory clean" >/dev/null
if [ $? -gt 0 ]; then
echo "Working directory isn't clean, commit/clean then publish"
exit 1
else
echo "Working directory clean"
fi
git status | grep "Your branch is ahead" >/dev/null
if [ $? -eq 0 ]; then
echo "Your branch isn't in sync with origin"
exit 1
else
echo "In sync with origin"
fi
set -e
echo "Getting latest from upstream:$branch"
git pull upstream $branch
echo "Resetting"
./reset.sh --hardcore --real-safari --chromedriver-install-all --chromedriver-version 2.14
version=$(cat package.json | $(npm bin)/underscore extract version | sed 's/\"//g')
echo "Clearing npm cache"
npm cache clear appium
echo "Publishing on npm"
if [[ "$version" =~ "beta" ]]; then
npm publish --tag beta
else
npm publish
fi
echo "Git tagging"
git tag -a "v$version" -m "tag appium@$version for npm publish"
git push --tags upstream $branch
+15
View File
@@ -0,0 +1,15 @@
param([string]$mochaArgs = "", [switch]$android, [switch]$selendroid)
$all = !($android -or $selendroid)
$appiumMocha="mocha --recursive -t 90000 -R spec $mochaArgs "
if ($android -or $all){
"RUNNING ANDROID TESTS"
"---------------------"
Invoke-Expression ($appiumMocha + "test\functional\android test\functional\common -g '@skip-android-all' -i")
}
if ($selendroid -or $all){
"RUNNING SELENDROID TESTS"
"------------------------"
Invoke-Expression ($appiumMocha + "test\functional\selendroid -g '@skip-selendroid-all' -i")
}
Executable
+171
View File
@@ -0,0 +1,171 @@
#!/bin/sh
set -e
mocha_args=""
ios_only=false
ios6_only=false
ios7_only=false
ios71_only=false
ios8_only=false
ios81_only=false
ios82_only=false
android_only=false
android_chrome=false
selendroid_only=false
gappium_only=false
real_device=false
all_tests=true
xcode_switch=true
xcode_path=""
if command -v xcode-select 2>/dev/null; then
xcode_path="$(xcode-select -print-path | sed s/\\/Contents\\/Developer//g)"
fi
did_switch_xcode=false
for arg in "$@"; do
if [ "$arg" = "--ios" ]; then
ios_only=true
all_tests=false
elif [ "$arg" = "--android" ]; then
android_only=true
all_tests=false
elif [ "$arg" = "--android-chrome" ]; then
android_chrome=true
all_tests=false
elif [ "$arg" = "--selendroid" ]; then
selendroid_only=true
all_tests=false
elif [ "$arg" = "--gappium" ]; then
gappium_only=true
all_tests=false
elif [ "$arg" = "--ios6" ]; then
ios6_only=true
all_tests=false
elif [ "$arg" = "--ios7" ]; then
ios7_only=true
all_tests=false
elif [ "$arg" = "--ios71" ]; then
ios71_only=true
all_tests=false
elif [ "$arg" = "--ios8" ]; then
ios8_only=true
all_tests=false
elif [ "$arg" = "--ios81" ]; then
ios81_only=true
all_tests=false
elif [ "$arg" = "--ios82" ]; then
ios82_only=true
all_tests=false
elif [ "$arg" = "--no-xcode-switch" ]; then
xcode_switch=false
elif [ "$arg" = "--real-device" ]; then
real_device=true
elif [ "$arg" =~ " " ]; then
mocha_args="$mocha_args \"$arg\""
else
mocha_args="$mocha_args $arg"
fi
done
appium_mocha="./node_modules/.bin/mocha --recursive $mocha_args"
run_ios_tests() {
echo "RUNNING IOS $1 TESTS"
echo "---------------------"
if $xcode_switch; then
if test -d /Applications/Xcode-$1.app; then
echo "Found Xcode for iOS $1, switching to it"
sudo xcode-select -switch /Applications/Xcode-$1.app
did_switch_xcode=true
else
echo "Did not find /Applications/Xcode-$1.app, using default"
fi
fi
DEVICE=$2 time $appium_mocha -g $3 -i \
test/functional/common \
test/functional/ios
}
if $ios6_only || $ios_only || $all_tests; then
run_ios_tests "6.1" "ios6" "@skip-ios6|@skip-ios-all"
fi
if $ios7_only || $all_tests; then
run_ios_tests "7.0" "ios7" "@skip-ios7|@skip-ios-all"
fi
if $ios71_only || $all_tests; then
run_ios_tests "7.1" "ios71" "@skip-ios71|@skip-ios7|@skip-ios-all|@skip-ios7up"
fi
if $ios8_only || $all_tests; then
run_ios_tests "8.0" "ios8" "@skip-ios8|@skip-ios-all|@skip-ios7up"
fi
if $ios81_only || $all_tests; then
run_ios_tests "8.1" "ios81" "@skip-ios81|@skip-ios8|@skip-ios-all|@skip-ios7up"
fi
if $ios82_only || $all_tests; then
run_ios_tests "8.2" "ios82" "@skip-ios82|@skip-ios81|@skip-ios8|@skip-ios-all|@skip-ios7up"
fi
if $did_switch_xcode; then
echo "Switching back to default Xcode ($xcode_path)"
sudo xcode-select -switch $xcode_path
fi
if $android_only || $all_tests; then
echo "RUNNING ANDROID TESTS"
echo "---------------------"
if $real_device; then
DEVICE=android REAL_DEVICE=true time $appium_mocha \
-g '@skip-android-all|@android-arm-only|@skip-real-device' -i \
test/functional/common \
test/functional/android
else
DEVICE=android time $appium_mocha \
-g '@skip-android-all|@android-arm-only' -i \
test/functional/common \
test/functional/android
fi
fi
if $android_chrome; then
echo "RUNNING ANDROID CHROME TESTS"
echo "---------------------"
if $real_device; then
DEVICE=android REAL_DEVICE=true time $appium_mocha \
-g '@skip-chrome|@skip-android-all' -i \
test/functional/android/chrome
else
DEVICE=android time $appium_mocha \
-g '@skip-chrome|@skip-android-all' -i \
test/functional/android/chrome
fi
fi
if $selendroid_only || $all_tests; then
echo "RUNNING SELENDROID TESTS"
echo "---------------------"
DEVICE=selendroid time $appium_mocha -g '@skip-selendroid-all' -i \
test/functional/selendroid
fi
if $gappium_only || $all_tests; then
echo "RUNNING GAPPIUM TESTS"
echo "---------------------"
DEVICE=ios81 time $appium_mocha test/functional/gappium
# disabling, ios6 not working yet xcode 6
#DEVICE=ios6 time $appium_mocha test/functional/gappium
echo "Start the android emulator api 19 and press Enter."
read
DEVICE=android time $appium_mocha test/functional/gappium
# disabling gappium test, see https://github.com/selendroid/selendroid/issues/658
#echo "Start the android emulator api 16 and press Enter."
#read
#DEVICE=selendroid time $appium_mocha test/functional/gappium
fi
Executable
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
{ set -e; } 2>/dev/null
{ set -x; } 2>/dev/null
# Loading appium-ci-gulper submodule
export APPIUM_ROOT="$(pwd)"
git submodule update --remote --init submodules/appium-ci-gulper
pushd submodules/appium-ci-gulper
git pull origin master
{ set +x; } 2>/dev/null
# Running appium-ci-gulper submodule
# This sets up node etc...
source ./setup
{ set -x; } 2>/dev/null
-11
View File
@@ -1,11 +0,0 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [0],
'body-max-line-length': [0],
'footer-max-line-length': [0],
'header-max-length': [0],
'subject-case': [0],
'subject-full-stop': [0],
},
};
+9 -4
View File
@@ -1,6 +1,11 @@
# Docs moved
# docs
The old Appium 1.x docs used to be in this directory. Now, they are available only on the [1.x
branch](https://github.com/appium/appium/tree/1.x/docs).
##doc site
Appium 2.x docs are located in [packages/appium/docs](../packages/appium/docs) in this repo.
Formatted doc is [here](http://appium.io/documentation.html?lang=en).
##doc translation
At the moment we are focusing on improving the english documentation. When it
is done we are planning to setup proper i18n l10n processes so that it is
easier for people to help in translating the documentation.
+18
View File
@@ -0,0 +1,18 @@
## List of client libraries with Appium server support
These libraries wrap standard Selenium client libraries to provide all the regular selenium commands dictated by the [JSON Wire protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol), and add extra commands related to controlling mobile devices, such as **multi-touch gestures** and **screen orientation**.
Appium client libraries implement the [Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) (an official draft extension to the standard protocol), and elements of the [W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html) (a transport-agnostic automation spec; this is where the MultiAction API is defined).
The Appium server itself defines custom extensions to the official protocols, giving Appium users helpful access to various device behaviors (such as installing/uninstalling apps during the course of a test session). This is why we need Appium-specific clients, not just the 'vanilla' Selenium clients. Of course, Appium client libraries only **add** functionality (in fact, they simply extend the standard Selenium clients), so they can still be used to run regular Selenium sessions.
Language/Framework | Github Repo and Installation Instructions |
----- | ----- |
Ruby | [https://github.com/appium/ruby_lib](https://github.com/appium/ruby_lib)
Python | [https://github.com/appium/python-client](https://github.com/appium/python-client)
Java | [https://github.com/appium/java-client](https://github.com/appium/java-client)
JavaScript (Node.js) | [https://github.com/admc/wd](https://github.com/admc/wd)
Objective C | [https://github.com/appium/selenium-objective-c](https://github.com/appium/selenium-objective-c)
PHP | [https://github.com/appium/php-client](https://github.com/appium/php-client)
C# (.NET) | [https://github.com/appium/appium-dotnet-driver](https://github.com/appium/appium-dotnet-driver)
RobotFramework | [https://github.com/jollychang/robotframework-appiumlibrary](https://github.com/jollychang/robotframework-appiumlibrary)
+108
View File
@@ -0,0 +1,108 @@
## Introduction to Appium
Appium is an open-source tool for automating native,
mobile web, and hybrid applications on iOS and Android platforms.
**Native apps** are those written using the iOS or Android SDKs. **Mobile web apps** are web apps accessed using a mobile browser (Appium supports
Safari on iOS and Chrome or the built-in 'Browser' app on Android). **Hybrid apps** have a
wrapper around a "webview" -- a native control that enables interaction with
web content. Projects like [Phonegap](http://phonegap.com/),
make it easy to build apps using web technologies that are then bundled into
a native wrapper, creating a hybrid app.
Importantly, Appium is "cross-platform": it allows you to write tests against
multiple platforms (iOS, Android), using the same API. This enables code reuse between iOS and Android testsuites.
For specific information about what it means for Appium to "support" its
platforms, and automation modalities, please see the [platform support doc](/docs/en/appium-setup/platform-support.md).
### Appium Philosophy
Appium was designed to meet mobile automation needs according to a philosophy outlined by the following four tenets:
1. You shouldn't have to recompile your app or modify it in any way in order to automate it.
2. You shouldn't be locked into a specific language or framework to write and run your tests.
3. A mobile automation framework shouldn't reinvent the wheel when it comes to automation APIs.
4. A mobile automation framework should be open source, in spirit and practice as well as in name!
### Appium Design
So how does the structure of the Appium project live out this philosophy? We
meet requirement #1 by using vendor-provided automation frameworks under the
hood. That way, we don't need to compile in any Appium-specific or
third-party code or frameworks to your app. This means **you're testing the same app you're shipping**. The vendor-provided frameworks we use are:
* iOS: Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html)
* Android 4.2+: Google's [UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)
* Android 2.3+: Google's [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). (Instrumentation support is provided by bundling a separate project, [Selendroid](http://selendroid.io))
We meet requirement #2 by wrapping the vendor-provided frameworks in one API,
the [WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.
WebDriver (aka "Selenium WebDriver") specifies a client-server protocol
(known as the [JSON Wire Protocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol)).
Given this client-server architecture, a client written in any language can
be used to send the appropriate HTTP requests to the server. There are
already [clients written in every popular programming language](http://appium.io/downloads). This also
means that you're free to use whatever test runner and test framework you
want; the client libraries are simply HTTP clients and can be mixed into your
code any way you please. In other words, Appium & WebDriver clients are not
technically "test frameworks" -- they are "automation libraries". You can
manage your test environment any way you like!
We meet requirement #3 in the same way: WebDriver has become the de facto
standard for automating web browsers, and is a [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html).
Why do something totally different for mobile? Instead we have [extended the protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
with extra API methods useful for mobile automation.
It should be obvious that requirement #4 is a given -- you're reading this
because [Appium is open source](https://github.com/appium/appium).
### Appium Concepts
**Client/Server Architecture**<br/>
Appium is at its heart a webserver that exposes a REST API. It receives
connections from a client, listens for commands, executes those commands on a
mobile device, and responds with an HTTP response representing the result of
the command execution. The fact that we have a client/server architecture
opens up a lot of possibilities: we can write our test code in any language
that has a http client API, but it is easier to use one of the [Appium client
libraries](http://appium.io/downloads). We can put the server on a different machine than our
tests are running on. We can write test code and rely on a cloud service
like [Sauce Labs](https://saucelabs.com/mobile) to receive and interpret the commands.
**Session**<br/>
Automation is always performed in the context of a session. Clients initiate
a session with a server in ways specific to each library,
but they all end up sending a `POST /session` request to the server,
with a JSON object called the 'desired capabilities' object. At this point
the server will start up the automation session and respond with a session ID
which is used for sending further commands.
**Desired Capabilities**<br/>
Desired capabilities are a set of keys and values (i.e.,
a map or hash) sent to the Appium server to tell the server what kind of
automation session we're interested in starting up. There are also various
capabilities which can modify the behavior of the server during automation.
For example, we might set the `platformName` capability to `iOS` to tell
Appium that we want an iOS session, rather than an Android one. Or we might
set the `safariAllowPopups` capability to `true` in order to ensure that,
during a Safari automation session, we're allowed to use JavaScript to open
up new windows. See the [capabilities doc](/docs/en/writing-running-appium/caps.md) for the complete list of capabilities available for Appium.
**Appium Server**<br/>
Appium is a server written in Node.js. It can be built and installed from source or installed directly from NPM.
**Appium Clients**<br/>
There are client libraries (in Java, Ruby, Python, PHP, JavaScript, and C#)
which support Appium's extensions to the WebDriver protocol. When using Appium,
you want to use these client libraries instead of your regular WebDriver
client. You can view the full list of libraries [here](appium-clients.md).
**[Appium.app](https://github.com/appium/appium-dot-app), [Appium.exe](https://github.com/appium/appium-dot-exe)**<br/>
There exist GUI wrappers around the Appium server that can be downloaded.
These come bundled with everything required to run the Appium server,
so you don't need to worry about Node. They also come with an Inspector,
which enables you to check out the hierarchy of your app. This can come in handy when writing tests.
### Getting Started
Congratulations! You are now armed with enough knowledge to begin using Appium. Why not head to the [getting started doc](/README.md) for more detailed requirements and instructions?
+59
View File
@@ -0,0 +1,59 @@
## Selenium Grid
You are able to register your appium server with a local [Selenium grid](https://code.google.com/p/selenium/wiki/Grid2) ([setup docs](http://docs.seleniumhq.org/docs/07_selenium_grid.jsp)) by using the
`--nodeconfig` server parameter.
```center
> appium --nodeconfig /path/to/nodeconfig.json
# or, if running from source:
> node . --nodeconfig /path/to/nodeconfig.json
```
In the node config file you have to define the `browserName`,
`version` and `platform` and based on these parameters the grid
will re-direct your test to the right device. You will also need to
configure your **host** details and the **selenium grid** details. For
a full list of all parameters and descriptions look
[here](http://code.google.com/p/selenium/source/browse/java/server/src/org/openqa/grid/common/defaults/GridParameters.properties)
Once you start the appium server and it registers with the grid,
you will see your device on the grid console page:
"http://**\<grid-ip-adress\>**:**\<grid-port\>**/grid/console"
### Grid Node Configuration Example json file
```xml
{
"capabilities":
[
{
"browserName": "<e.g._iPhone5_or_iPad4>",
"version":"<version_of_iOS_e.g._7.1>",
"maxInstances": 1,
"platform":"<platform_e.g._MAC_or_ANDROID>"
}
],
"configuration":
{
"cleanUpCycle":2000,
"timeout":30000,
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"url":"http://<host_name_appium_server_or_ip-address_appium_server>:<appium_port>/wd/hub",
"host": <host_name_appium_server_or_ip-address_appium_server>,
"port": <appium_port>,
"maxSession": 1,
"register": true,
"registerCycle": 5000,
"hubPort": <grid_port>,
"hubHost": "<Grid_host_name_or_grid_ip-address>"
}
}
```
Valid platforms are listed [here](http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/Platform.html)
If `url`, `host`, and `port` are not given, the config will be auto updated
to point to localhost:whatever-port-Appium-started-on.
If your Appium server is running on a different machine to your Selenium Grid server, make sure you use an external name/IP address in your `host` & `url` docs; `localhost` and `127.0.0.1` will prevent Selenium Grid from connecting correctly.
+217
View File
@@ -0,0 +1,217 @@
## Automating hybrid apps
One of the core principles of Appium is that you shouldn't have to change
your app to test it. In line with that methodology, it is possible to test
hybrid web apps (e.g., the "UIWebView" elements in an iOS app) the same way
you can with Selenium for web apps. There is a bit of technical complexity
required so that Appium knows whether you want to automate the native aspects
of the app or the web views, but thankfully, we can stay within the
WebDriver protocol for everything.
Here are the steps required to talk to a web view in your Appium test:
1. Navigate to a portion of your app where a web view is active
1. Call [GET session/:sessionId/contexts](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
1. This returns a list of contexts we can access, like 'NATIVE_APP' or 'WEBVIEW_1'
1. Call [POST session/:sessionId/context](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)
with the id of the context you want to access
1. (This puts your Appium session into a mode where all commands are
interpreted as being intended for automating the web view,
rather than the native portion of the app. For example,
if you run getElementByTagName, it will operate on the DOM of the web
view, rather than return UIAElements. Of course,
certain WebDriver methods only make sense in one context or another,
so in the wrong context you will receive an error message).
1. To stop automating in the web view context and go back to automating the
native portion of the app, simply call `context` again with the native
context id to leave the web frame.
```javascript
// javascript
// assuming we have an initialized `driver` object for an app
driver
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
return driver.context(contexts[1]); // choose the webview context
})
// do some web testing
.elementsByCss('.green_button').click()
.context('NATIVE_APP') // leave webview context
// do more native stuff here if we want
.quit() // stop webdrivage
```
```java
// java
// assuming we have a set of capabilities
driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
Set<String> contextNames = driver.getContextHandles();
for (String contextName : contextNames) {
System.out.println(contextNames); //prints out something like NATIVE_APP \n WEBVIEW_1
}
driver.context(contextNames.toArray()[1]); // set context to WEBVIEW_1
//do some web testing
String myText = driver.findElement(By.cssSelector(".green_button")).click();
driver.context("NATIVE_APP");
// do more native testing if we want
driver.quit();
```
```ruby
# ruby
# assuming we have a set of capabilities
@driver = Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => SERVER_URL)
# I switch to the last context because its always the webview in our case, in other cases you may need to specify a context
# View the appium logs while running @driver.contexts to figure out which context is the one you want and find the associated ID
# Then switch to it using @driver.switch_to.context("WEBVIEW_6")
Given(/^I switch to webview$/) do
webview = @driver.contexts.last
@driver.switch_to.context(webview)
end
Given(/^I switch out of webview$/) do
@driver.switch_to.context(@driver.contexts.first)
end
# Now you can use CSS to select an element inside your webview
And(/^I click a webview button $/) do
@driver.find_element(:css, ".green_button").click
end
```
```python
# python
# assuming we have an initialized `driver` object for an app
# switch to webview
webview = driver.contexts.last
driver.switch_to.context(webview)
# do some webby stuff
driver.find_element(:css, ".green_button").click
# switch back to native view
driver.switch_to.context(driver.contexts.first)
# do more native testing if we want
driver.quit()
```
```php
// php
// assuming we have an initialized `driver` object in an AppiumTestCase
public function testThings()
{
$expected_contexts = array(
0 => 'NATIVE_APP',
1 => 'WEBVIEW_1'
);
$contexts = $this->contexts();
$this->assertEquals($expected_contexts, $contexts);
$this->context($contexts[1]);
$context = $this->context();
$this->assertEquals('WEBVIEW_1', $context);
// do webby stuff
$this->context('NATIVE_APP');
// do mobile stuff
}
```
### Automating hybrid Android apps
Appium comes with built-in hybrid support via Chromedriver. Appium also uses
Selendroid under the hood for webview support on devices older than 4.4. (In
that case, you'll want to specify `"automationName": "selendroid"` as a desired
capability).
Make sure
[setWebContentsDebuggingEnabled](http://developer.android.com/reference/android/webkit/WebView.html#setWebContentsDebuggingEnabled(boolean)) is set to true as described in the [remote debugging docs](https://developer.chrome.com/devtools/docs/remote-debugging#configure-webview).
Once you've set your desired capabilities and started an appium session, follow the generalized instructions above.
### Automating hybrid iOS apps
To interact with a web view appium establishes a connection
using a remote debugger. When executing against a
simulator this connection is established directly as the simulator and
the appium server are on the same machine.
Once you've set your desired capabilities and started an appium session, follow the generalized instructions above.
### Execution against a real iOS device
When executing against a real iOS device appium is unable to access the web view directly. Therefore the
connection has to be established through the USB lead. To establish this
connection we use the [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy).
To install the latest tagged version of the ios-webkit-debug-proxy using
brew, run the following commands in the terminal:
``` center
# The first command is only required if you don't have brew installed.
> ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)"
> brew update
> brew install ios-webkit-debug-proxy
```
You can also install the latest proxy by cloning it from git and installing
it yourself:
``` center
# Please be aware that this will install the proxy with the latest code (and not a tagged version).
> git clone https://github.com/google/ios-webkit-debug-proxy.git
> cd ios-webkit-debug-proxy
> ./autogen.sh
> ./configure
> make
> sudo make install
```
If you use a recent device, you may need to install the latest
ideviceinstaller, this is optional:
```
brew install --HEAD ideviceinstaller
```
Once installed you can start the proxy with the following command:
``` center
# Change the udid to be the udid of the attached device and make sure to set the port to 27753
# as that is the port the remote-debugger uses.
> ios_webkit_debug_proxy -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
```
You may also use the ios-webkit-debug-proxy-launcher to launch the
proxy. It monitors the proxy log for errors, and relaunch the proxy
where needed. This is also optional and may help with recent devices:
``` center
# change the udid
> ./bin/ios-webkit-debug-proxy-launcher.js -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
```
**NOTE:** the proxy requires the **"web inspector"** to be turned on to
allow a connection to be established. Turn it on by going to **settings >
safari > advanced**. Please be aware that the web inspector was **added as
part of iOS 6** and was not available previously.
Now you can start an appium test session and follow the generalized instructions above.
@@ -0,0 +1,158 @@
## Migrating your tests from Appium 0.18.x to Appium 1.x
Appium 1.0 has removed a number of deprecated features from the previous versions. This guide will help you know what needs to change in your test suite to take advantage of Appium 1.0.
### New client libraries
The biggest thing you need to worry about is using the new Appium client libraries instead of the vanilla WebDriver clients you are currently using. Visit the [Appium client list](/docs/en/about-appium/appium-clients.md) to find the client for your language. Downloads and instructions for integrating into your code are available on the individual client websites.
Ultimately, you'll be doing something like (to use Python as an example):
```center
from appium import webdriver
```
Instead of:
```center
from selenium import webdriver
```
### New desired capabilities
The following capabilities are no longer used:
* `device`
* `version`
Instead, use these capabilities:
* `platformName` (either "iOS" or "Android")
* `platformVersion` (the mobile OS version you want)
* `deviceName` (the kind of device you want, like "iPhone Simulator")
* `automationName` ("Selendroid" if you want to use Selendroid, otherwise, this can be omitted)
The `app` capability remains the same, but now refers exclusively to non-browser apps. To use browsers like Safari or Chrome, use the standard `browserName` cap. This means that `app` and `browserName` are exclusive.
We have also standardized on camelCase for Appium server caps. That means caps like `app-package` or `app-wait-activity` are now `appPackage` and `appWaitActivity` respectively. Of course, since Android app package and activity are now auto-detected, you should be able to omit them entirely in most cases.
### New locator strategies
We've removed the following locator strategies:
* `name`
* `tag name`
We have now added the `accessibility_id` strategy to do what `name` used to do. The specifics will be relative to your Appium client.
`tag name` has been replaced by `class name`. So to find an element by its UI type, use the class name locator strategy for your client.
Note about `class name` and `xpath` strategies: these now require the fully-qualified class name for your element. This means that if you had an xpath selector that looked like this:
```center
//table/cell/button
```
It would now need to be:
```center
//UIATableView/UIATableCell/UIAButton
```
(And likewise for Android: `button` now needs to be `android.widget.Button`)
We've also added the following locator strategies:
* `-ios uiautomation`
* `-android uiautomator`
Refer to your client for ways to use these new locator strategies.
### XML, not JSON
App source methods, which previously returned JSON, now return XML, so if you have code that relies on parsing the app source, it will need to be updated.
### Hybrid support through context, not window
Hybrid apps were previously supported by switching between "windows" using
* `window_handles`
* `window`
* `switch_to.window`
Now Appium supports the more conceptually consistent concept of "context". To get all of the available contexts, or the particular context the application is is, you use
```python
# python
driver.contexts
current = driver.context
```
```javascript
// javascript
driver.contexts().then(function (contexts) { /*...*/ })
```
```c#
// c#
driver.GetContexts ()
driver.GetContext ()
```
```java
// java
Set<String> contextNames = driver.getContextHandles();
String context = driver.getContext();
```
```php
// php
$contexts = $this->contexts();
$context = $this->context();
```
```ruby
# ruby
contexts = available_contexts
context = current_context
```
And to switch between them, you use
```python
# python
driver.switch_to.context("WEBVIEW")
```
```javascript
// javascript
driver.currentContext().then(function (context) { /*...*/ })
```
```c#
// c#
driver.SetContext ("WEBVIEW");
```
```java
java
driver.context(contextName);
```
```php
// php
$this->context('WEBVIEW');
```
```ruby
# ruby
set_context "WEBVIEW"
```
### No more `execute_script("mobile: xxx")`
All the `mobile: ` methods have been removed, and have been replaced by native methods in the Appium client libraries. This means that a method call like `driver.execute("mobile: lock", [5])` will now look something more like `driver.lock(5)` (where `lock` has been turned into a native client method). Of course, the details on calling these methods will differ by client.
Of particular note, the gesture methods have been replaced by the new TouchAction / MultiAction API which allows for a much more powerful and general way of putting gestural automation together. Refer to your Appium client for usage notes on TouchAction / MultiAction.
And that's it! Happy migrating!
+40
View File
@@ -0,0 +1,40 @@
## Settings
Settings are a new concept introduced by appium. They are currently not a part of the Mobile JSON Wire Protocol, or the Webdriver spec.
Settings are a way to specify the behavior of the appium server.
Settings are:
- Mutable, they can be changed during a session
- Only relevant during the session they are applied. They are reset for each new session.
- Control the way the appium server behaves during test automation. They do not apply to controlling the app or device under test.
An example of a setting would be `ignoreUnimportantViews` for Android. Android can be set to ignore elements in the View Hierarchy which it deems irrelevant. Setting this can cause tests to run faster. A user who *wants* to access the ignored elements however, would want to disable `ignoreUnimportantViews`, and reenable it afterwards.
Another example of a use-case for settings would be telling appium to ignore elements which are not visible.
Settings are implemented via the following API endpoints:
**POST** /session/:sessionId/appium/settings
>Expects a JSON hash of settings, where keys correspond to setting names, and values to the value of the setting.
```
{
settings: {
ignoreUnimportantViews : true
}
}
```
**GET** /session/:sessionId/appium/settings
>Returns a JSON hash of all the currently specified settings.
```
{
ignoreUnimportantViews : true
}
```
### Supported Settings
**"ignoreUnimportantViews"** - Boolean which sets whether Android devices should use `setCompressedLayoutHeirarchy()` which ignores all views which are marked IMPORTANT_FOR_ACCESSIBILITY_NO or IMPORTANT_FOR_ACCESSIBILITY_AUTO (and have been deemed not important by the system), in an attempt to make things less confusing or faster.
@@ -0,0 +1,14 @@
## Intel® Hardware Accelerated Execution Manager
If you find the android emulator a slow and your system runs on an Intel®
cpu, you can check out HAXM. HAXM lets you leverage your hardware for
virtualization, accelerating the emulator.
* To install HAXM open the Android SDK Manager, you will find the package
under Extras.
* You can find all relevant documentation on [Intel's website][1]
* This will require an x86 emulator image
* Use Intel's package to install HAXM; The Android SDK Manager appears to not
do so successfully, depending on the version you might have installed
[1]: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/
+51
View File
@@ -0,0 +1,51 @@
## Android Setup
To get started, you'll need to install node.js (v0.10 or greater). Just
follow the [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager).
Once you've got node.js installed, install the [Android SDK](http://developer.android.com/sdk/index.html).
You will need to run the 'android' tool (included in the SDK, under the 'tools' directory).
Run the 'android' tool and use it to install an API Level 17 or greater.
(If you want to run Appium from source, you will also need [Apache Ant](http://ant.apache.org/) to build the bootstrap jar that Appium uses for running against Android simulators/devices.)
Finally, set `$ANDROID_HOME` to be your Android SDK path. If you unzipped the
Android SDK to /usr/local/adt/, for example, you should add this to your
shell startup:
export ANDROID_HOME="/usr/local/adt/sdk"
Now you're set up to run Appium! If you're running Appium from source, run
`./reset.sh --android` from your Appium checkout to install all the
dependencies.
### Additional Setup for Older Versions of Android
Appium uses, and comes prepackaged with, Selendroid for running Android
versions 2.3 to 4.1. Appium switches to using Selendroid automatically when it
detects older versions, but there is some additional setup required if you're
running from source.
* Make sure you have [Maven 3.1.1](http://maven.apache.org/download.cgi) or
newer installed (`mvn`).
* Run `./reset.sh --selendroid` from your Appium checkout
### Running Appium Android Tests
To run tests on Linux, you will need to have the Android Emulator booted and
running an AVD with API Level 17 or greater. Then run Appium (`appium`) after
installing via NPM, or `node .` in the source directory if running from source.
See the [server documentation](/docs/en/writing-running-appium/server-args.md) for all the command line arguments.
### Notes
* There exists a hardware accelerated emulator for android, it has its own
limitations. For more information you can check out this
[page](/docs/en/appium-setup/android-hax-emulator.md).
* Make sure that `hw.battery=yes` in your AVD's `config.ini`, if you want to
run any of the Appium tests, or use any of the power commands.
* Selendroid requires the following permission for your app:
`<uses-permission android:name="android.**permission.INTERNET"/>`,
please make sure your app has internet permission set when you are using selendroid or older versions of Android i.e. 2.3 to 4.1
+83
View File
@@ -0,0 +1,83 @@
## Deploying an iOS app to a real device
To prepare for your Appium tests to run on a real device, you will need to:
1. Build your app with specific device-targeted parameters
1. Use [fruitstrap](https://github.com/ghughes/fruitstrap), a 3rd-party tool,
to deploy this build to your device
### Xcodebuild with parameters:
A newer xcodebuild now allows settings to be specified. Taken from [developer.apple.com](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html):
```center
xcodebuild [-project projectname] [-target targetname ...]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[buildaction ...] [setting=value ...] [-userdefault=value ...]
```
This is a resource to explore the available [settings](https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-DontLinkElementID_10)
```center
CODE_SIGN_IDENTITY (Code Signing Identity)
Description: Identifier. Specifies the name of a code signing identity.
Example value: iPhone Developer
```
PROVISIONING_PROFILE is missing from the index of available commands,
but may be necessary.
Specify "CODE_SIGN_IDENTITY" & "PROVISIONING_PROFILE" settings in the
xcodebuild command:
```center
xcodebuild -sdk <iphoneos> -target <target_name> -configuration <Debug> CODE_SIGN_IDENTITY="iPhone Developer: Mister Smith" PROVISIONING_PROFILE="XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX"
```
On success, the app will be built to your ```<app_dir>/build/<configuration>-iphoneos/<app_name>.app```
### Deploy using Fruitstrap
Go clone a forked version of fruitstrap as the [ghughes version](https://github.com/ghughes/fruitstrap)
is no longer maintained. Success has been confirmed with the [unprompted fork](https://github.com/unprompted/fruitstrap),
but others are reportedly functional.
Once cloned, run `make fruitstrap`
Now, copy the resulting `fruitstrap` executable to your app's project or a
parent directory.
Execute fruitstrap after a clean build by running (commands available depend
on your fork of fruitstrap):
```center
./fruitstrap -d -b <PATH_TO_APP> -i <Device_UDID>
```
If you are aiming to use continuous integration in this setup,
you may find it useful to want to log the output of fruitstrap to both
command line and log, like so:
```center
./fruitstrap -d -b <PATH_TO_APP> -i <Device_UDID> 2>&1 | tee fruit.out
```
Since fruitstrap will need to be killed before the node server can be
launched, an option is to scan the output of the fruitstrap launch for some
telling sign that the app has completed launching. This may prove useful if
you are doing this via a Rakefile and a ``go_device.sh`` script:
```center
bundle exec rake ci:fruit_deploy_app | while read line ; do
echo "$line" | grep "text to identify successful launch"
if [ $? = 0 ]
then
# Actions
echo "App finished launching: $line"
sleep 5
kill -9 `ps -aef | grep fruitstrap | grep -v grep | awk '{print $2}'`
fi
done
```
Once fruitstrap is killed, node server can be launched and Appium tests can run!
Next: [Running Appium on Real Devices](real-devices.md)
+30
View File
@@ -0,0 +1,30 @@
## Parallel Android Tests
Appium provides a way for users to automate multiple Android sessions on a single machine. All it involves is starting multiple Appium servers with different flags.
The important flags for automating multiple Android sessions are:
- `-p` the main Appium port
- `-U` the device id
- `-bp` the Appium bootstrap port
- `--chromedriver-port` the chromedriver port (if using webviews or chrome)
- `--selendroid-port` the selendroid port (if using selendroid)
More information on these flags can be found [here](../writing-running-appium/caps.md).
If we had two devices with the ID's 43364 and 32456, we would start two different Appium servers with the following commands:
`node . -p 4492 -bp 2251 -U 32456`
`node . -p 4491 -bp 2252 -U 43364`
As long as your Appium and Appium bootstrap ports are between 0 and 65536, all they have to be is different so that two Appium servers aren't trying to listen on the same port. Be sure that your -u flag corresponds with the correct device ID. This is how Appium knows which device to communicate with, so it must be accurate.
If you are using chromedriver or selendroid, set a different port for each server.
### Parallel iOS Tests
Unfortunately, running local parallel iOS tests aren't possible. Unlike Android, only one version of the iOS simulator can be launched at a time, making it run multiple tests at once.
If you do want to run parallel iOS tests, you need to use Sauce. Simply upload your Appium test to Sauce, and it can run as many parallel iOS or Android tests as your account allows. See more about running your tests on Sauce [here](https://docs.saucelabs.com/tutorials/appium/).
+63
View File
@@ -0,0 +1,63 @@
## Appium Platform Support
Appium supports a variety of platforms and testing modalities (native,
hybrid, web, real devices, simulators, etc...). This document is designed to
make explicit the level of support and requirements for each of these.
### iOS Support
See [Running on OS X: iOS](running-on-osx.md) for iOS requirements and setup
instructions.
* Versions: 6.0, 6.1, 7.0, 7.1, 8.0, and 8.1
* Devices: iPhone Simulator, iPad Simulator, and real iPhones and iPads
* Native app support: Yes, with debug version of .app (simulator),
or correctly-signed .ipa (real devices). Underlying support is provided by
Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html)
framework.
* Mobile web support: Yes, via automation of mobile Safari. For real devices,
ios-webkit-remote-debugger is required, and automation of native aspects of
the Safari interface is not possible. See the [mobile web doc](/docs/en/writing-running-appium/mobile-web.md) for instructions.
* Hybrid support: Yes. For real devices, ios-webkit-remote-debugger is
required. See the [hybrid doc](/docs/en/advanced-concepts/hybrid.md) for instructions.
* Support for automating multiple apps in one session: No
* Support for automating multiple devices simultaneously: No
* Support for automating vendor-provided or third-party apps: Only
vendor-provided apps (Preferences, Maps, etc...), and only on the simulator
* Support for automating custom, non-standard UI controls: Minimal. You need to
set accessibility information on the control which enables some basic
automation.
### Android Support
See [Running on OS X: Android](running-on-osx.md),
[Running on Windows](running-on-windows.md), or
[Running on Linux](running-on-linux.md) for Android requirements and setup
instructions.
* Versions: 2.3 and up
* Versions 2.3 through 4.2 are supported via Appium's bundled version of
[Selendroid](http://selendroid.io), which utilizes [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). Selendroid has a different set of commands than the default Appium (though this is rapidly being minimized) and a different support profile. To access this automation backend, use the `automationName` capability with the value `Selendroid`.
* Versions 4.2 and up are supported via Appium's own [UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)
libraries. This is the default automation backend.
* Devices: Android emulators and real Android devices
* Native app support: Yes
* Mobile web support: Yes (but not when using Selendroid backend). Automation
is effected using a bundled [Chromedriver](https://code.google.com/p/selenium/wiki/ChromeDriver)
server as a proxy. With 4.2 and 4.3, automation works on official Chrome
browser or Chromium only. With 4.4+, automation also works on the built-in
"Browser" app. Chrome/Chromium/Browser must already be installed on the
device under test. See the [mobile web doc](/docs/en/writing-running-appium/mobile-web.md) for instructions.
* Hybrid support: Yes. See the [hybrid doc](/docs/en/advanced-concepts/hybrid.md) for instructions.
* With default Appium automation backend: versions 4.4 and up
* With Selendroid automation backend: versions 2.3 and up
* Support for automating multiple apps in one session: Yes (but not when
using the Selendroid backend)
* Support for automating multiple devices simultaneously: Yes,
though Appium must be started using different ports for the server
parameters `--port`, `--bootstrap-port` (or `--selendroid-port`) and/or
`--chromedriver-port`. See the [server args doc](/docs/en/writing-running-appium/server-args.md) for more
information on these parameters.
* Support for automating vendor-provided or third-party apps: Yes (but not
when using the Selendroid backend)
* Support for automating custom, non-standard UI controls: No
+74
View File
@@ -0,0 +1,74 @@
## Appium on real iOS devices
Appium has support for real device testing.
To get started on a real device, you will need the following:
* An [Apple Developer ID](https://developer.apple.com/programs/ios/)
and a valid Developer Account with a configured distribution certificate and
provisioning profile.
* An iPad or iPhone. Make sure this has been set up for development in Xcode. See [this article](https://developer.apple.com/library/ios/recipes/xcode_help-devices_organizer/articles/provision_device_for_development-generic.html) for more information.
* A signed `.ipa` file of your app, or the source code to build one.
* A Mac with [Xcode](https://itunes.apple.com/en/app/xcode/id497799835?mt=12)
and the Xcode Command Line Developer Tools.
### Provisioning Profile
A valid iOS Development Distribution Certificate and Provisioning Profile are
necessary to test on a real device. Your app will also need to be signed. You
can find information about this in the [Apple documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html).
Appium will attempt to install your app using Fruitstrap, but it is often easier
to pre-install your app using Xcode to ensure there are no problems (see the [iOS deploy](ios-deploy.md) doc for more information).
### Running your tests with Appium
Once your device and app are configured, you can run tests on that device by
passing the `-U` or `--udid` flag to the server or the `udid` desired capability,
and the bundle ID (if the app is installed on the device) or the path to the
`.ipa` or `.apk` file via the `--app` flag or the `app` desired capability.
### Server Arguments
For example, if you are prelaunching your app and wish for Appium to force use
a specific UDID, then you may use the below command:
```center
appium -U <udid> --app <path or bundle>
```
This will start Appium and have Appium use the device to test the app.
Refer to the [Appium server arguments](/docs/en/writing-running-appium/server-args.md) page for more detail on
the arguments that you can use.
### Desired Capabilities
You can launch the app on a device by including the following desired
capabilities in your tests:
* `app`
* `udid`
Refer to the [Appium server capabilities](/docs/en/writing-running-appium/caps.md) page for more detail on
the capabilities that you can use.
### Troubleshooting ideas
0. Make sure UDID is correct by checking it in Xcode Organizer or iTunes. It
is a long string (20+ chars).
0. Make sure that you can run your tests against the Simulator.
0. Double check that you can invoke your automation from Instruments.
0. Make sure Instruments is not already running.
### Appium on real Android devices
Hooray! There's nothing extra to know about testing real Android devices: it
works exactly the same as testing on emulators. Make sure that your device
can connect to ADB and has Developer Mode enabled. For testing Chrome on a real
device, you're responsible for ensuring that Chrome of an appropriate version
is installed.
Also, you'll want to make sure that "Verify Apps" in settings is
disabled/unchecked, otherwise it can prevent some of Appium's helper apps from
launching and doing their job correctly.
+12
View File
@@ -0,0 +1,12 @@
## Running Appium on Linux
### Limitations
If you are running Appium on Linux, you cannot use the prebuilt '.app',
which is built for OS X only. Additionally, you will not be able to test iOS
apps because Appium relies on OS X-only libraries to support iOS testing.
### Setup (Android)
Instructions for setting up Android and running tests on Linux are the same as
those on Mac OS X. See the [Android setup docs](/docs/en/appium-setup/android-setup.md).
+65
View File
@@ -0,0 +1,65 @@
## Running Appium on Mac OS X
Appium on OS X supports iOS and Android testing.
### System setup (iOS)
* Appium requires Mac OS X 10.7, but 10.8 or 10.9 is recommended.
* Make sure you have Xcode and the iOS SDK(s) installed. Xcode version 5.1 is
recommended as earlier versions of Xcode are limited in which version of iOS
they can test against. See the next section for more detail.
* You need to authorize use of the iOS Simulator. If you are running Appium
from NPM, you'll do this by running `sudo authorize_ios` (`authorize_ios` is
a binary made available by the Appium npm package). If you're running Appium
from source, simply run `sudo grunt authorize` to do the same thing. If you
are running [Appium.app](https://github.com/appium/appium-dot-app), you can
authorize iOS through the GUI.
* If you're on Xcode 6, you need to launch each simulator you intend to use
with appium in advance, and change the default to actually show the soft
keyboard if you want sendKeys to work. You can do this by clicking on any
textfield and hitting command-K until you notice the soft keyboard show up.
* If you're on Xcode 6, you have a feature in Xcode called Devices
(command-shift-2). You need to make sure that whichever deviceName you choose
to use with Appium in your capabilities, there is only one of those per sdk
version. In other words, if you send in a deviceName cap of "iPhone 5s" and
a platformVersion cap of "8.0", you need to make sure that there is exactly
one device with the name "iPhone 5s" and the 8.0 sdk in your devices list.
Otherwise, Appium won't know which one to use.
* In iOS8, devices each have their own setting which enables or disables
UIAutomation. It lives in a "Developer" view in the Settings app. You need to
verify that UIAutomaion is enabled in this view before the simulator or
device can be automated.
### Testing against multiple iOS SDKs
Xcode version 5.1 allows for automatic testing against iOS versions 6.0 and later.
If using version 5.1, you can ignore the rest of this section.
For Xcode 4.6.3 to 5.0, Apple's `instruments` binary, which Appium uses to launch
the iOS simulator, by default uses the currently-selected Xcode, and the highest
iOS SDK installed with that version of Xcode. This means that if you want to test
iOS 6.1, but have iOS 7.1 installed, Appium will be forced to use the 7.1 Simulator
regardless. The only way around this is to have multiple copies of Xcode
installed with different sets of SDKs. You can then switch to the particular
copy of Xcode that has the versions you want to test with before starting
Appium.
In addition, it's been discovered that testing against iOS 6.1 with Xcode
5 causes increased slowness and instability, so it's recommended that for
testing against iOS 6.1 and below we use Xcode 4.6.3, and for testing against
iOS 7.0 we use Xcode 5. We can do this by, say, having Xcode 5 at
`/Applications/Xcode.app`, and Xcode 4.6 and `/Applications/Xcode-4.6.app`.
Then we use the following command:
sudo xcode-select -switch /Applications/Xcode-4.6.app/Contents/Developer/
To prepare for iOS 6.1 testing. We run it again with a different Xcode:
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/
To go back to iOS 7.1 testing.
### System setup (Android)
Instructions for setting up Android and running tests on Mac OS X are the same as
those on Linux. See the [Android setup docs](/docs/en/appium-setup/android-setup.md).
@@ -0,0 +1,65 @@
## Running Appium on Windows
### Limitations
If you are running Appium on Windows, you can use the
[Appium.exe](https://github.com/appium/appium-dot-exe) client, which will allow
you to quickly launch an Appium server and use the Inspector. You will not be
able to test iOS apps on a locally hosted server, because Appium relies on OS
X-only libraries to support iOS testing. You can however use the `Remote Server`
option to connect to an Appium server running on a Mac.
### Setup
To get started:
1. Install [node.js](http://nodejs.org/download/) (v.0.10 or greater). Use the
installer from nodejs.org.
1. Install the [Android SDK](http://developer.android.com/sdk/index.html).
You will need to run the 'android' tool (included in the SDK, in the `tools` folder) and make sure
you have an API Level 17 or greater API installed. Set `ANDROID_HOME` to be
your Android SDK path and add the `tools` and `platform-tools` folders to your
PATH variable.
1. Install the Java JDK and set `JAVA_HOME` to your JDK folder.
1. Install [Apache Ant](http://ant.apache.org/bindownload.cgi) or use the one
that comes with the Android Windows SDK in the eclipse\plugins folder. Be
sure to add the folder containing Ant to your PATH variable.
1. Install [Apache Maven](http://maven.apache.org/download.cgi) and set the
M2HOME and M2 environment variables. Set `M2HOME` to the directory maven is
installed in, and set `M2` to `%M2HOME\bin`. Add the path you used for `M2` to
your PATH.
1. Install [Git](http://git-scm.com/download/win) Be sure to install Git for
windows to run in the regular command prompt.
1. Install [cURL](http://curl.haxx.se/download.html).
Now that you've downloaded everything, if you're running from source, run the
following .bat file in the folder where you cloned appium:
```center
reset.bat
```
### Running Appium
To run tests on Windows, you will need to have the Android Emulator booted or
an Android Device connected that is running an AVD with API Level 17 or
greater. Then run Appium on the command line (via the `appium` command), or if
you're running from source, inside the folder where you installed appium, using
node.js:
```center
node .
```
See the [server documentation](/docs/en/writing-running-appium/server-args.md) for all the command line
arguments.
### Notes
* On windows run appium.app as administrator or when running from source you need to run cmd as administrator.
* You must supply the `--no-reset` or `--full-reset` flags for
Android to work on Windows.
* There exists a hardware accelerated emulator for Android, it has it's own
limitations. For more information you can check out this
[page](/docs/en/appium-setup/android-hax-emulator.md).
* Make sure that `hw.battery=yes` in your AVD's `config.ini`.
+130
View File
@@ -0,0 +1,130 @@
## Troubleshooting Appium
Here's what to do if you're experiencing problems, before you submit a ticket
to github or write to the [appium-discuss discussion group](https://discuss.appium.io).
### General
* Make sure you've followed the getting started steps in the [README](/README.md)
* Make sure your system is set up appropriately (i.e., XCode is updated,
Android SDK is installed and `ANDROID_HOME` is set.
* Make sure the paths to your applications are correct
* On windows run appium.app as administrator or when running from source you need to run cmd as administrator.
### If you're running Appium.app
* Update the app and restart. If you get a message saying the app can't be updated,
re-download it from [appium.io](http://appium.io).
### If you're running Appium from source
* `git pull` to make sure you're running the latest code
* Run the appropriate flavor of `reset.sh` based on what you're trying to
automate:
|command | explanation |
|-------------------------|-------------|
|./reset.sh | # all |
|./reset.sh --ios | # ios-only |
|./reset.sh --android | # android-only |
|./reset.sh --selendroid | # selendroid-only |
* You might also want to run `reset.sh` with the `--dev` flag if you want the
test apps downloaded and built as well.
* You can also use `appium-doctor` to automatically verify that all
dependencies are met. If running from source, you may have to use
`bin/appium-doctor.js` or `node bin/appium-doctor.js`.
* If you get this error after upgrading to Android SDK 22:
`{ANDROID_HOME}/tools/ant/uibuild.xml:155: SDK does not have any Build Tools installed.`
In the Android SDK 22, the platform and build tools are split up into their
own items in the SDK manager. Make sure you install the build-tools and platform-tools.
### Android
* Make sure the Android emulator is up and running.
* It's sometimes useful to run `adb kill-server && adb devices`. This can
reset the connection to the Android device.
* Make sure you set ANDROID_HOME pointing to the Android SDK directory
### IOS
* Make sure Instruments.app is not open
* If you're running the simulator, make sure your actual device is not
plugged in
* Make sure the accessibility helper is turned off in your Settings app
* Make sure the app is compiled for the version of the simulator that's being
run
* Make sure the app is compiled for the simulator (or real device) as
appropriate (e.g., in debug mode for the simulator), or you might get
a `posix spawn` error.
* If you've ever run Appium with sudo, you might need to `sudo rm
/tmp/instruments_sock` and try again as not-sudo.
* If this is the first time you've run Appium, make sure to authorize the use
of Instruments. Usually a box will pop up that you enter your password into
. If you're running Appium from source, you can simply run `sudo grunt authorize`
from the main repo to avoid getting this popup. If you're running from npm,
run `sudo authorize_ios` instead. You need to do this every time you install
a new version of Xcode, as well.
* If you see `iOS Simulator failed to install the application.` and the
paths are correct, try restarting the computer.
### Webview/Hybrid/Safari app support
* Make Sure you enable the 'Web Inspector' on the real device.
* Make Sure you enable the Safari - Advance Preferences- Developer menu for
simulators.
* Make sure you are properly switching contexts using the `context` appium commands provided by your client library.
* If you getting this error: select_port() failed, when trying to open the
proxy, see this [discussion](https://groups.google.com/forum/#!topic/appium-discuss/tw2GaSN8WX0)
### FirefoxOS
* Make sure the Boot-to-Gecko simulator is up and running.
* Make sure the simulator screen is alive and unlocked (might require restarting B2G).
### Let the community know
Once you've tried the above steps and your issue still isn't resolved,
here's what you can do:
If you're having trouble getting Appium working and the error messages Appium
provides are not clear, join the [discussion group](https://discuss.appium.io)
and send a message. Please include the following:
* How you're running Appium (Appium.app, npm, source)
* What operating system you are using
* What device and version you are testing against (i.e. Android 4.4, or iOS 7.1)
* Whether you are running against a real device or a simulator/emulator
* The client-side and server-side errors you're getting (i.e.,
"In Python this is the exception I get in my test script,
and here's a link to a paste of the Appium server output)
* Per above, it's very important to include a paste of the Appium server
output when it's run in verbose mode so that we can diagnose what's going on.
If you've found what you believe is a bug, go straight to the [issue tracker](https://github.com/appium/appium/issues)
and submit an issue describing the bug and a repro case.
### Known Issues
* If you've installed Node from the Node website, it requires that you use sudo
for `npm`. This is not ideal. Try to get node with
[n](https://github.com/visionmedia/n) or `brew install node` instead!
* Webview support works on real iOS devices with a proxy, see [discussion](https://groups.google.com/d/msg/appium-discuss/u1ropm4OEbY/uJ3y422a5_kJ).
* Sometimes iOS UI elements become invalidated milliseconds after they are
found. This results in an error that looks like `(null) cannot be tapped`.
Sometimes the only solution is to put the finding-and-clicking code in a retry
block.
* Appium may have difficulties finding the `node` executable if you've
installed Node and npm via MacPorts. You must make sure that the MacPorts bin
folder (`/opt/local/bin` by default) is added to `PATH` somewhere in your
`~/.profile`, `~/.bash_profile` or `~/.bashrc`.
### Specific Errors
|Action|Error|Resolution|
|------|-----|----------|
|Running reset.sh|xcodebuild: error: SDK "iphonesimulator6.1" cannot be located|Install the iPhone 6.1 SDK _or_ build the test apps with a separate SDK, e.g., `grunt buildApp:UICatalog:iphonesimulator5.1`|
|Running reset.sh|Warning: Task "setGitRev" not found. Use --force to continue.|Update the submodules with `git submodule update --init` and run `reset.sh` again|
|Running reset.sh|`[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project selendroid-server: Compilation failure [ERROR] Failure executing javac, but could not parse the error: [ERROR] [ERROR] [ERROR] The system is out of resources. [ERROR] Consult the following stack trace for details. [ERROR] java.lang.StackOverflowError `|`export MAVEN_OPTS="-Xms1024m -Xmx2048m -Xss2048k"`|
|Running ios test|`[INST STDERR] posix spawn failure; aborting launch`|Your app is not compiled correctly for the simulator or device.|
|Running mobile safari test|`error: Could not prepare mobile safari with version '7.1'`|You probably need to run the authorize script again to make the iOS SDK files writeable. E.g., `sudo authorize_ios`|
@@ -0,0 +1,208 @@
## Running Appium from Source
So you want to run Appium from source and help fix bugs and add features?
Great! Just fork the project, make a change, and send a pull request! Please
have a look at our [Style Guide](style-guide.md) before getting to work.
Please make sure the unit and functional tests pass before sending a pull
request; for more information on how to run tests, keep reading!
Make sure you read and follow the setup instructions in the README first.
### Setting up Appium from Source
An Appium setup involves the Appium server, which sends messages back and forth
between your test code and devices/emulators, and a test script, written in
whatever language binding exists that is compatible with Appium. Run an
instance of an Appium server, and then run your test.
The quick way to get started:
```center
$ git clone https://github.com/appium/appium.git
$ cd appium
$ ./reset.sh
$ sudo ./bin/authorize-ios.js # for ios only
$ node .
```
### Hacking on Appium
Make sure you have ant, maven, adb installed and added to system PATH, also you
would need the android-16 sdk (for Selendroid) and android-19 sdk installed.
From your local repo's command prompt, install the following packages using the
following commands (if you didn't install `node` using homebrew, you might have
to run npm with sudo privileges):
```center
npm install -g mocha
npm install -g grunt-cli
node bin/appium-doctor.js --dev
./reset.sh --dev
```
The first two commands install test and build tools (`sudo` may not be
necessary if you installed node.js via Homebrew). The third command verifies
that all of the dependencies are set up correctly (since dependencies for
building Appium are different from those for simply running Appium) and fourth
command installs all app dependencies and builds supporting binaries and test
apps. `reset.sh` is also the recommended command to run after pulling changes
from master. Running `reset.sh` with the `--dev` flag also installs git hooks
that make sure code quality is preserved before committing. At this point,
you're able to start the Appium server:
```center
node .
```
See [the server documentation](/docs/en/writing-running-appium/server-args.md)
for a full list of arguments.
Like the power of automating dev tasks? Check out the [Appium Grunt tasks](/docs/en/contributing-to-appium/grunt.md)
available to help with building apps, installing apps, generating docs, etc.
#### Hacking with Appium for iOS
To avoid a security dialog that may appear when launching your iOS apps you'll
have to modify your `/etc/authorization` file in one of two ways:
1. Manually modify the element following `<allow-root>` under `<key>system.privilege.taskport</key>`
in your `/etc/authorization` file to `<true/>`.
2. Run the following grunt command which automatically modifies your
`/etc/authorization` file for you:
```center
sudo ./bin/authorize-ios.js
```
At this point, run:
```center
./reset.sh --ios --dev
```
Now your Appium instance is ready to go. Run `node .` to kick up the Appium server.
#### Hacking with Appium for Android
Bootstrap running for Android by running:
```center
./reset.sh --android --dev
```
If you want to use [Selendroid](http://github.com/DominikDary/selendroid) for
support on older Android platforms like 2.3, then run:
```center
./reset.sh --selendroid --dev
```
Make sure you have one and only one Android emulator or device running, e.g.
by running this command in another process (assuming the `emulator` command is
on your path):
```center
emulator -avd <MyAvdName>
```
Now you are ready to run the Appium server via `node .`.
#### Making sure you're up to date
Since Appium uses dev versions of some packages, it often becomes necessary to
install new `npm` packages or update various things. There's a handy shell script
to do all this for all platforms (the `--dev` flag gets dev npm dependencies
and test applications used in the Appium test suite). You will also need to do
this when Appium bumps its version up:
```center
./reset.sh --dev
```
Or you can run reset for individual platforms only:
```center
./reset.sh --ios --dev
./reset.sh --android --dev
./reset.sh --selendroid --dev
```
### Running Tests
First, check out our documentation on [running tests in
general](/docs/en/writing-running-appium/running-tests.md) Make sure your
system is set up properly for the platforms you desire to test on.
Once your system is set up and your code is up to date, you can run unit tests
with:
```center
grunt unit
```
You can run functional tests for all supported platforms (after ensuring that
Appium is running in another window with `node .`) with:
```center
bin/test.sh
```
Or you can run particular platform tests with `test.sh`:
```center
bin/test.sh --android
bin/test.sh --ios
bin/test.sh --ios7
bin/test.sh --ios71
```
Before committing code, please run `grunt` to execute some basic tests and
check your changes against code quality standards. Note that this should happen
automatically if you ran `reset.sh --dev`, which sets up the git pre-commit
hooks.
```center
grunt lint
> Running "newer:jshint" (newer) task
>
> Running "newer:jshint:files" (newer) task
> No newer files to process.
>
> Running "newer:jshint:test" (newer) task
> No newer files to process.
>
> Running "newer:jshint:examples" (newer) task
> No newer files to process.
>
> Running "jscs:files" (jscs) task
> >> 303 files without code style errors.
```
#### Running individual tests
If you have an Appium server listening, you can run individual test files using
Mocha, for example:
```center
DEVICE=ios71 mocha -t 60000 -R spec test/functional/ios/testapp/simple.js
```
Or individual tests (e.g., a test with the word "alert" in the name):
```center
DEVICE=ios6 mocha -t 60000 -R spec --grep "alert" test/functional/ios/uicatalog
```
For windows you have to use `set DEVICE=android` in cmd to run above tests, for
example:
```center
set DEVICE=android
mocha -t 60000 -R spec test/functional/android/apidemos/alerts-specs.js
```
NOTE: For Android, you will need an emulator/device with screen size of 4.0"
(480x800). Some tests might fail on a different screen size.
`DEVICE` must be set to a valid value: `ios71`, `ios6`, `android`, `selendroid`
+15
View File
@@ -0,0 +1,15 @@
## Credits
### These are the projects that inspired us, or are depended upon to make Appium awesome.
* [Apple UIAutomation](http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html)
* [GhostDriver](https://github.com/detro/ghostdriver)
* [IOS Auto](https://github.com/penguinho/applecart)
* [IOS Driver](https://github.com/ios-driver/ios-driver)
* [Mechanic.js](https://github.com/jaykz52/mechanic)
* [node-webkit](https://github.com/rogerwang/node-webkit)
* [Remote Debug](https://github.com/leftlogic/remote-debug)
* [Selenium Project](http://code.google.com/p/selenium/)
* [ios-webkit-debug-proxy](https://github.com/google/ios-webkit-debug-proxy)
* [instruments-without-delay](https://github.com/facebook/instruments-without-delay)
* [deviceconsole](https://github.com/rpetrich/deviceconsole)
+32
View File
@@ -0,0 +1,32 @@
## Appium grunt commands
[Grunt](http://gruntjs.com) is like make for Node.js! We use it to automate all
kinds of appium dev tasks. Here's what you can do:
|Task|Description|
|----|-----------|
|grunt lint|Run JSLint|
|grunt test|Run the unit tests|
|grunt unit|Run the unit tests|
|grunt getSampleCode|Download sample code and apps. Accepts `:hardcore` parameter|
|grunt buildApp:&lt;AppName&gt;:&lt;SDK&gt;|Build an iOS app for the iPhone Simulator. Expects there to be a .app at `sample-code/apps/<AppName>/build/Release-iphonesimulator/<AppName>.app`. Default SDK is 'iphonesimulator7.1'|
|grunt signApp:&lt;certName&gt;|Signs the test app with an absolute path to an iOS dev certificate|
|grunt authorize|Authorize your simulator to run without prompting|
|grunt log|Tail appium.log (useful when running tests)|
|grunt configAndroidBootstrap|Configure the android bootstrap jar so it can be built with ant|
|grunt buildAndroidBootstrap|Build the android bootstrap jar with ant|
|grunt buildSelendroidServer|Build the selendroid server|
|grunt configAndroidApp:&lt;AppName&gt;|Configure an android test app so it can be built with ant. Expects an android project at `sample-code/apps/<AppName>`|
|grunt buildAndroidApp:&lt;AppName&gt;|Build an android app using ant. Expects the app to be at `sample-code/apps/<AppName>`|
|grunt installAndroidApp:&lt;AppName&gt;|Installs an android app to the currently running emulator or device|
|grunt docs|Generate docs|
|grunt generateAppiumIo|Take Appium's README.md and turn it into HTML for getting-started.html of appium.io|
|grunt setConfigVer:&lt;device&gt;|Say that &lt;device&gt; is configured for the version of Appium listed in package.json|
### Miscellaneous notes
By default, `grunt buildApp` builds apps using the iPhone 7.1 simulator SDK.
You can overwrite the simulator by passing another SDK to grunt (to figure out
which SDKs you have available, try running `xcodebuild -showsdks`):
> grunt buildApp:UICatalog:iphonesimulator6.1
@@ -0,0 +1,57 @@
## How to write docs
`##` is used to write a h2 header. Each document must start with a h2 header.
This is to support appium.io docs genration.Don't use the `---` underline method of creating headers.
Don't use h1 `#` or `===` for heading as it is not supported for table of contents (folder name is used as h1).
### Subheaders
`###` is used to write subheaders.
### Regular headers
`####` is used for headers that don't appear in the table of contents.
Don't use h5 `#####`, or h6 `######`.
### Line breaks
Don't use line breaks such as `--` or `---`. This will confuse Slate.
### Linking
Link to the readme:
`[readme](../../README.md)`
Link to contributing:
`[contributing](../../CONTRIBUTING.md)`
Link to another document
`[link text](filename.md)`
To link inside a document, use the `#` from the Slate URL.
`[go direct to json](filename.md#json-wire-protocol-server-extensions)`
Note that hash links will break when the heading changes so linking to
the start of the doc is preferable (`other.md` instead of `other.md#something`).
### Compatibility with appium.io
#### Center aligning code in appium.io
Appium.io documentation uses [slate](https://github.com/tripit/slate) for documentation.
If code snippet in documentation is not language specific or if you want code snippet to stay
along with text in center in appium.io documentation, use center as language in fenced code block.
Example:
```center
code snippet goes here.
```
#### Publishing
To publish documentation on appium.io see [api-docs](https://github.com/appium/api-docs) and [appium.io](https://github.com/appium/appium.io).
@@ -0,0 +1,279 @@
## Style guide for contributors
Thanks for your contribution to Appium! Here are the principles we use when
writing javascript. Please conform to these so we can merge your pull request
without going back and forth about style. The main principle is: *make your
code look like the surrounding code*.
### Rebasing
Commits in a pull request should consist of [logical changes](https://github.com/appium/appium/pull/920#issuecomment-21588553).
If there are multiple authors, make sure each author has their own commit.
It's not a good idea to modify author information. Merge commits should be
rebased out of pull requests.
### Linting
All code (except for code in `bootstrap.js` which uses proprietary Apple
methods) must pass JSLint. To check your code, you can simply run `grunt
lint` from the Appium repo dir. If you've created a new .js file,
please make sure it is covered by the wildcards in `grunt.js` or that it is
added specifically.
It's easy to have your code linted as you type, which makes the whole process
much smoother. We like [jshint](http://www.jshint.com),
which has integrations with a lot of source code editors. The file `
.jshintrc` is checked into the repo, and its contents are:
```json
{
"laxcomma": true,
"strict": true,
"undef": true,
"unused": true,
"node": true,
"eqeqeq": true,
"trailing": true,
"indent": 2
}
```
Since jshint does not enforce code style anymore, we also use
[jscs](https://github.com/mdevils/node-jscs), for which it also exists some
source editor integrations. The configuration file is:
```json
{
"excludeFiles": ["submodules/**", "node_modules/**",
"./lib/server/static/**", "./lib/devices/firefoxos/atoms/*.js",
"./test/harmony/**/*.js", "./sample-code/examples/node/**/*-yiewd.js",
"./sample-code/apps/**", "./sample-code/examples/php/vendor/**"],
"requireCurlyBraces": ["for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch",
"return", "try", "catch", "function"],
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
}
}
```
These configuration files define the warnings you will see in your favorite
editor. See [this page for jshint](http://www.jshint.com/platforms/) and
[this page for jscs](https://github.com/mdevils/node-jscs#friendly-packages) to
get the list of editors and platforms supported and how setup your editor for
automatic linting.
### Style notes
* Use two spaces for indentation, *no tabs*
* Use single spaces around operators
```javascript
var x = 1;
```
not
```javascript
var x=1;
```
* Spaces after commas and colons in lists, objects, function calls, etc...
```javascript
var x = myFunc("lol", {foo: bar, baz: boo});
```
not
```javascript
var x = myFunc("lol",{foo:bar,baz:boo});
```
* Always end statements with semicolons
* Comma-first
```javascript
var x = {
foo: 'bar'
, baz: 'boo'
, wuz: 'foz'
};
```
* Brackets for `function`, `if`, etc... go on same line, `else` gets sandwiched
```javascript
if (foo === bar) {
// do something
} else {
// do something else
}
```
* Space after `if`, `for`, and `function`:
```javascript
if (foo === bar) {
```
```javascript
for (var i = 0; i < 10; i ++) {
```
```javascript
var lol = function (foo) {
```
not
```javascript
if(foo === bar) {
```
```javascript
for(var i = 0; i < 10; i ++) {
```
```javascript
var lol = function(foo) {
```
* Avoid bracketless `if` for one-liners:
```javascript
if (foo === bar) {
foo++;
}
```
not
```javascript
if (foo === bar)
foo++;
```
except in the case of short-circuiting to a callback in the event of an error
```javascript
if (err) return cb(err);
```
* Use `===`, not `==`, and `!==`, not `!=` for no surprises
* Line length shouldn't be longer than 79 characters
* Break up long strings like this:
```javascript
myFunc("This is a really long string that's longer " +
"than 79 characters so I broke it up, woo");
```
* Comments should line up with code
```javascript
if (foo === 5) {
myFunc(foo);
// foo++;
}
```
not
```javascript
if (foo === 5) {
myFunc(foo);
//foo++;
}
```
* Subclassing by extending prototypes
```javascript
var _ = require('underscore');
var SuperClass = function () {
this.init();
};
SuperClass.prototype.init = function () {
// initialize
};
// Create a subclass
var SubClass = function () {
this.init();
};
_.extend(SubClass.prototype, SuperClass.prototype);
```
* Callbacks are always last in function definitions
```javascript
var foo = function (arg1, arg2, cb) {
...
};
```
* Define functions as variables
```javascript
var myFunc = function (a, b, c) {};
```
not
```javascript
function myFunc (a, b, c) {}
```
* Variable names should be camelCased:
```javascript
var myVariable = 42;
```
not
```javascript
var my_variable = 42;
```
* Check for undefined
```javascript
typeof myVariable === "undefined"
```
not
```javascript
myVariable === undefined
```
* Define a variable with a default value
```javascript
var x = y || z;
```
not
```javascript
var x = y ? y : z;
```
### Test Style:
Keep on the same line if it makes sense semantically and length is not an issue:
Examples:
```javascript
driver.elementByTagName('el1').should.become("123")
.nodeify(done);
driver
.elementsByTagName('el1').should.eventually.have.length(0)
.nodeify(done);
```
Alternatively use extra indents to improve readability:
```javascript
h.driver
.elementById('comments')
.clear()
.click()
.keys("hello world")
.getValue()
.should.become("hello world")
.elementById('comments')
.getValue().should.become("hello world")
.nodeify(done);
h.driver
.execute("'nan'--")
.should.be.rejectedWith("status: 13")
.nodeify(done);
```
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
## Appium server capabilities
<expand_table>
|Capability|Description|Values|
|----|-----------|-------|
|`automationName`|Which automation engine to use|`Appium` (default) or `Selendroid`|
|`platformName`|Which mobile OS platform to use|`iOS`, `Android`, or `FirefoxOS`|
|`platformVersion`|Mobile OS version|e.g., `7.1`, `4.4`|
|`deviceName`|The kind of mobile device or emulator to use|`iPhone Simulator`, `iPad Simulator`, `iPhone Retina 4-inch`, `Android Emulator`, `Galaxy S4`, etc.... On iOS, this should be one of the valid devices returned by instruments with `instruments -s devices`. On Android this capability is currently ignored.|
|`app`|The absolute local path _or_ remote http URL to an `.ipa` or `.apk` file, or a `.zip` containing one of these. Appium will attempt to install this app binary on the appropriate device first. Note that this capability is not required for Android if you specify `appPackage` and `appActivity` capabilities (see below). Incompatible with `browserName`.|`/abs/path/to/my.apk` or `http://myapp.com/app.ipa`|
|`browserName`|Name of mobile web browser to automate. Should be an empty string if automating an app instead.|'Safari' for iOS and 'Chrome', 'Chromium', or 'Browser' for Android|
|`newCommandTimeout`|How long (in seconds) Appium will wait for a new command from the client before assuming the client quit and ending the session|e.g. `60`|
|`autoLaunch`|Whether to have Appium install and launch the app automatically. Default `true`|`true`, `false`|
|`language`| (Sim/Emu-only) Language to set for the simulator / emulator |e.g. `fr`|
|`locale`| (Sim/Emu-only) Locale to set for the simulator / emulator |e.g. `fr_CA`|
|`udid`| Unique device identifier of the connected physical device|e.g. `1ae203187fc012g`|
|`orientation`| (Sim/Emu-only) start in a certain orientation|`LANDSCAPE` or `PORTRAIT`|
|`autoWebview`| Move directly into Webview context. Default `false`|`true`, `false`|
|`noReset`|Don't reset app state before this session. Default `false`|`true`, `false`|
|`fullReset`|(iOS) Delete the entire simulator folder. (Android) Reset app state by uninstalling app instead of clearing app data. On Android, this will also remove the app after the session is complete. Default `false`|`true`, `false`|
### Android Only
<expand_table>
|Capability|Description|Values|
|----|-----------|-------|
|`appActivity`| Activity name for the Android activity you want to launch from your package. This often needs to be preceded by a `.` (e.g., `.MainActivity` instead of `MainActivity`)|`MainActivity`, `.Settings`|
|`appPackage`| Java package of the Android app you want to run|`com.example.android.myApp`, `com.android.settings`|
|`appWaitActivity`| Activity name for the Android activity you want to wait for|`SplashActivity`|
|`appWaitPackage`| Java package of the Android app you want to wait for|`com.example.android.myApp`, `com.android.settings`|
|`deviceReadyTimeout`| Timeout in seconds while waiting for device to become ready|`5`|
|`androidCoverage`| Fully qualified instrumentation class. Passed to -w in adb shell am instrument -e coverage true -w | `com.my.Pkg/com.my.Pkg.instrumentation.MyInstrumentation`|
|`enablePerformanceLogging`| (Chrome and webview only) Enable Chromedriver's performance logging (default `false`)| `true`, `false`|
|`androidDeviceReadyTimeout`|Timeout in seconds used to wait for a device to become ready after booting|e.g., `30`|
|`androidDeviceSocket`|Devtools socket name. Needed only when tested app is a Chromium embedding browser. The socket is open by the browser and Chromedriver connects to it as a devtools client.|e.g., `chrome_devtools_remote`|
|`avd`| Name of avd to launch|e.g., `api19`|
|`avdLaunchTimeout`| How long to wait in milliseconds for an avd to launch and connect to ADB (default `120000`)| `300000`|
|`avdReadyTimeout`| How long to wait in milliseconds for an avd to finish its boot animations (default `120000`)| `300000`|
|`avdArgs`| Additional emulator arguments used when launching an avd|e.g., `-netfast`|
|`useKeystore`| Use a custom keystore to sign apks, default `false`|`true` or `false`|
|`keystorePath`| Path to custom keystore, default ~/.android/debug.keystore|e.g., `/path/to.keystore`|
|`keystorePassword`| Password for custom keystore|e.g., `foo`|
|`keyAlias`| Alias for key |e.g., `androiddebugkey`|
|`keyPassword`| Password for key |e.g., `foo`|
|`chromedriverExecutable`| The absolute local path to webdriver executable (if Chromium embedder provides its own webdriver, it should be used instead of original chromedriver bundled with Appium) |`/abs/path/to/webdriver`|
|`autoWebviewTimeout`| Amount of time to wait for Webview context to become active, in ms. Defaults to `2000`| e.g. `4`|
|`intentAction`| Intent action which will be used to start activity (default `android.intent.action.MAIN`)| e.g.`android.intent.action.MAIN`, `android.intent.action.VIEW`|
|`intentCategory`| Intent category which will be used to start activity (default `android.intent.category.LAUNCHER`)| e.g. `android.intent.category.LAUNCHER`, `android.intent.category.APP_CONTACTS`
|`intentFlags`| Flags that will be used to start activity (default `0x10200000`)| e.g. `0x10200000`
|`optionalIntentArguments`| Additional intent arguments that will be used to start activity. See [Intent arguments](http://developer.android.com/tools/help/adb.html#IntentSpec) | e.g. `--esn <EXTRA_KEY>`, `--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE>`, etc.
|`stopAppOnReset`| Stops the process of the app under test, before starting the app using adb. If the app under test is created by another anchor app, setting this false, allows the process of the anchor app to be still alive, during the start of the test app using adb, default `true`| `true` or `false`|
|`unicodeKeyboard`| Enable Unicode input, default `false`| `true` or `false`|
|`resetKeyboard`| Reset keyboard to its original state, after running Unicode tests with `unicodeKeyboard` capability. Ignored if used alone. Default `false`| `true` or `false`|
|`noSign`| Skip checking and signing of app with debug keys, will work only with UiAutomator and not with selendroid, default `false`| `true` or `false`|
|`ignoreUnimportantViews`| Calls the `setCompressedLayoutHierarchy()` uiautomator function. This capability can speed up test execution, since Accessibility commands will run faster ignoring some elements. The ignored elements will not be findable, which is why this capability has also been implemented as a toggle-able *setting* as well as a capability. Defaults to `false` | `true` or `false`
### iOS Only
<expand_table>
|Capability|Description|Values|
|----|-----------|-------|
|`calendarFormat`| (Sim-only) Calendar format to set for the iOS Simulator|e.g. `gregorian`|
|`bundleId`| Bundle ID of the app under test. Useful for starting an app on a real device or for using other caps which require the bundle ID during test startup. To run a test on a real device using the bundle ID, you may omit the 'app' capability, but you must provide 'udid'.|e.g. `io.appium.TestApp`|
|`udid`| Unique device identifier of the connected physical device|e.g. `1ae203187fc012g`|
|`launchTimeout`| Amount of time in ms to wait for instruments before assuming it hung and failing the session|e.g. `20000`|
|`locationServicesEnabled`| (Sim-only) Force location services to be either on or off. Default is to keep current sim setting.|`true` or `false`|
|`locationServicesAuthorized`| (Sim-only) Set location services to be authorized or not authorized for app via plist, so that location services alert doesn't pop up. Default is to keep current sim setting. Note that if you use this setting you MUST also use the `bundleId` capability to send in your app's bundle ID.|`true` or `false`|
|`autoAcceptAlerts`| Accept iOS privacy access permission alerts (e.g., location, contacts, photos) automatically if they pop up. Default is false.|`true` or `false`|
|`autoDismissAlerts`| Dismiss iOS privacy access permission alerts (e.g., location, contacts, photos) automatically if they pop up. Default is false.|`true` or `false`|
|`nativeInstrumentsLib`| Use native intruments lib (ie disable instruments-without-delay).|`true` or `false`|
|`nativeWebTap`| (Sim-only) Enable "real", non-javascript-based web taps in Safari. Default: `false`. Warning: depending on viewport size/ratio this might not accurately tap an element|`true` or `false`|
|`safariAllowPopups`| (Sim-only) Allow javascript to open new windows in Safari. Default keeps current sim setting|`true` or `false`|
|`safariIgnoreFraudWarning`| (Sim-only) Prevent Safari from showing a fraudulent website warning. Default keeps current sim setting.|`true` or `false`|
|`safariOpenLinksInBackground`| (Sim-only) Whether Safari should allow links to open in new windows. Default keeps current sim setting.|`true` or `false`|
|`keepKeyChains`| (Sim-only) Whether to keep keychains (Library/Keychains) when appium session is started/finished|`true` or `false`|
|`localizableStringsDir`| Where to look for localizable strings. Default `en.lproj`|`en.lproj`|
|`processArguments`| Arguments to pass to the AUT using instruments|e.g., `-myflag`|
|`interKeyDelay`| The delay, in ms, between keystrokes sent to an element when typing.|e.g., `100`|
|`showIOSLog`| Whether to show any logs captured from a device in the appium logs. Default `false`|`true` or `false`|
|`sendKeyStrategy`| strategy to use to type test into a test field. Simulator default: `oneByOne`. Real device default: `grouped` |`oneByOne`, `grouped` or `setValue`|
|`screenshotWaitTimeout`| Max timeout in sec to wait for a screenshot to be generated. default: 10 |e.g., `5`|
|`waitForAppScript`| The ios automation script used to determined if the app has been launched, by default the system wait for the page source not to be empty. The result must be a boolean |e.g. `true;`, `target.elements().length > 0;`, `$.delay(5000); true;` |
@@ -0,0 +1,50 @@
## Finding and interacting with elements
Appium supports a subset of the WebDriver locator strategies:
* find by "class" (i.e., ui component type)
* find by "xpath" (i.e., an abstract representation of a path to an element,
with certain constraints)
Appium additionally supports some of the [Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) locator strategies
* `-ios uiautomation`: a string corresponding to a recursive element search
using the [UIAutomation library](ios_predicate.md) (iOS-only)
* `-android uiautomator`: a string corresponding to a recursive element
search using the [UiAutomator Api](uiautomator_uiselector.md) (Android-only)
* `accessibility id`: a string corresponding to a recursive element search
using the Id/Name that the native Accessibility options utilize.
### Issues
There's a known issue with table cell elements becoming invalidated before
there's time to interact with them. We're working on a fix
### Using The Appium Inspector To Locate Elements
Appium provides you with a neat tool that allows you to find the the elements
you're looking for without leaving the Appium app. With the Appium Inspector
(the i symbol next to the start test button) you can find any element and
it's name by either clicking the element on the preview page provided,
or locating it in the UI navigator.
### Overview
The Appium inspector has a simple layout, complete with a UI navigator,
a preview, and record and refresh buttons, and interaction tools.
![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Overview.png)
### Example
After launching the Appium Inspector (you can do this by clicking the small
"i" button in the top right of the app) you can locate any element in the
preview. In this test, I'm looking for the id of the "show alert" button.
![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Step1.png)
To find the id of this button, I click the "show alert" button in the
inspector preview. The Appium inspector then highlights the element in the UI
navigator, showing me both the id and element type of the button I clicked.
![Step 1](https://raw.github.com/appium/appium/master/assets/InspectorImages/Step2.png)
@@ -0,0 +1,240 @@
## iOS Predicate
It is worth looking at *'-ios uiautomation'* search strategy with **Predicates**.
[UIAutomation JavaScript API](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html) has following methods which can are very useful.
```center
(UIAElement) UIAElementArray.firstWithPredicate(PredicateString predicateString)
(UIAElementArray) UIAElementArray.withPredicate(PredicateString predicateString)
```
Native JS search strategy (powered by Apple) provides much more flexibility and is like Xpath.
**[Predicates](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/predicates.html)** can be used to restrict an elements set to select only those ones for which some condition is true.
For example:
```java
// java
appiumDriver.findElementsByIosUIAutomation("collectionViews()[0].cells().withPredicate(\"ANY staticTexts.isVisible == TRUE\")")
```
\- will select only those ```UIACollectionCell``` elements that have visible ```UIAStaticText``` child elements, and themselves are childs of 1st ```UIACollectionView``` element that should be located under the main app window. Here ```staticTexts()``` and ```isVisible()``` are methods available in ```UIAElementArray``` and ```UIAElement``` classes respectively. **Note that ```UIAElementArray``` numbering begins with ```0``` unlike Xpath where indexes counting starts from ```1```**
Here's a list of available Predicates (mostly taken from [Predicates Programming Guide](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/predicates.html))
### Basic Comparisons
= , ==
- The left-hand expression is equal to the right-hand expression:
```center
tableViews()[1].cells().firstWithPredicate("label == 'Olivia' ")
same in Xpath: /UIATableView[2]/UIATableCell[@label = 'Olivia'][1]
```
\>= , =\>
- The left-hand expression is greater than or equal to the right-hand expression.
<= , =<
- The left-hand expression is less than or equal to the right-hand expression.
\>
- The left-hand expression is greater than the right-hand expression.
<
- The left-hand expression is less than the right-hand expression.
!= , <\>
- The left-hand expression is not equal to the right-hand expression.
BETWEEN
- The left-hand expression is between, or equal to either of, the values specified in the right-hand side. The right-hand side is a two value array (an array is required to specify order) giving upper and lower bounds. For example, ```1 BETWEEN { 0 , 33 }```, or ```$INPUT BETWEEN { $LOWER, $UPPER }```.
In Objective-C, you could create a BETWEEN predicate as shown in the following example:
```center
NSPredicate *betweenPredicate =
[NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
```
This creates a predicate that matches ```( ( 1 <= attributeValue ) && ( attributeValue <= 10 ) )```
### Boolean Value Predicates
TRUEPREDICATE
- A predicate that always evaluates to ```TRUE``` .
FALSEPREDICATE
- A predicate that always evaluates to ```FALSE```.
### Basic Compound Predicates
AND , &&
- Logical AND.
OR , ||
- Logical OR.
NOT , !
- Logical NOT.
### String Comparisons
String comparisons are by default case and diacritic sensitive. You can modify an operator using the key characters ```c``` and ```d``` within square braces to specify case and diacritic insensitivity respectively, for example ```firstName BEGINSWITH[cd] $FIRST_NAME```
BEGINSWITH
- The left-hand expression begins with the right-hand expression.
```center
scrollViews()[3].buttons().firstWithPredicate("name BEGINSWITH 'results toggle' ")
same in Xpath: /UIAScrollView[4]/UIAButton[starts-with(@name, 'results toggle')][1]
```
CONTAINS
- The left-hand expression contains the right-hand expression.
```center
tableViews()[1].cells().withPredicate("ANY collectionViews[0].buttons.name CONTAINS 'opera'")
same in Xpath: /UIATableView[2]/UIATableCell[UIACollectionView[1]/UIAButton[contains(@name, 'opera')]]
```
ENDSWITH
- The left-hand expression ends with the right-hand expression.
LIKE
- The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters. In Mac OS X v10.4, wildcard characters do not match newline characters.
```center
tableViews()[0].cells().firstWithPredicate("name LIKE '*Total: $*' ")
same in Xpath: /UIATableView[1]/UIATableCell[matches(@name, '.*Total: \$.*')][1]
```
MATCHES
- The left hand expression equals the right hand expression using a regex -style comparison according to ICU v3 (for more details see the ICU User Guide for [Regular Expressions](http://userguide.icu-project.org/strings/regexp)).
```center
tableViews().firstWithPredicate("value MATCHES '.*of 7' ")
same in Xpath: /UIATableView[matches(@value, '.*of 7')][1]
```
### Aggregate Operations
ANY , SOME
- Specifies any of the elements in the following expression. For example ```ANY children.age < 18``` .
```center
tableViews()[0].cells().firstWithPredicate("SOME staticTexts.name = 'red'").staticTexts().withName('red')
same in Xpath: /UIATableView[1]/UIATableCell[UIAStaticText/@name = 'red'][1]/UIAStaticText[@name = 'red']
```
ALL
- Specifies all of the elements in the following expression. For example ```ALL children.age < 18``` .
NONE
- Specifies none of the elements in the following expression. For example, ```NONE children.age < 18``` . This is logically equivalent to ```NOT (ANY ...)``` .
IN
- Equivalent to an SQL IN operation, the left-hand side must appear in the collection specified by the right-hand side. For example, ```name IN { 'Ben', 'Melissa', 'Matthew' }``` . The collection may be an array, a set, or a dictionary—in the case of a dictionary, its values are used.
array[index]
- Specifies the element at the specified index in the array.
array[FIRST]
- Specifies the first element in the array.
array[LAST]
- Specifies the last element in the array.
array[SIZE]
- Specifies the size of the array
```center
elements()[0].tableViews()[0].cells().withPredicate("staticTexts[SIZE] > 2")
same in Xpath: /*[1]/UIATableView[1]/UIATableCell[count(UIAStaticText) > 2]
```
### Identifiers
**C style identifier**
- Any C style identifier that is not a reserved word.
**\#symbol**
- Used to escape a reserved word into a user identifier.
**[\\]{octaldigit}{3}**
- Used to escape an octal number ( ```\``` followed by 3 octal digits).
**[\\][xX]{hexdigit}{2}**
- Used to escape a hex number ( ```\x``` or ```\X``` followed by 2 hex digits).
**[\\][uU]{hexdigit}{4}**
- Used to escape a Unicode number ( ```\u``` or ```\U``` followed by 4 hex digits).
### Literals
Single and double quotes produce the same result, but they do not terminate each other. For example, ```"abc"``` and ```'abc'``` are identical, whereas ```"a'b'c"``` is equivalent to a space-separated concatenation of ```a, 'b', c```.
FALSE , NO
- Logical false.
TRUE , YES
- Logical true.
NULL , NIL
- A null value.
SELF
- Represents the object being evaluated.
"text"
- A character string.
'text'
- A character string.
**Comma-separated literal array**
- For example, ```{ 'comma', 'separated', 'literal', 'array' }``` .
**Standard integer and fixed-point notations**
- For example, ```1 , 27 , 2.71828 , 19.75``` .
**Floating-point notation with exponentiation**
- For example, ```9.2e-5``` .
0x
- Prefix used to denote a hexadecimal digit sequence.
0o
- Prefix used to denote an octal digit sequence.
0b
- Prefix used to denote a binary digit sequence.
### Reserved Words
The following words are reserved:
`AND, OR, IN, NOT, ALL, ANY, SOME, NONE, LIKE, CASEINSENSITIVE, CI, MATCHES, CONTAINS, BEGINSWITH, ENDSWITH, BETWEEN, NULL, NIL, SELF, TRUE, YES, FALSE, NO, FIRST, LAST, SIZE, ANYKEY, SUBQUERY, CAST, TRUEPREDICATE, FALSEPREDICATE`
### Appium predicate helpers
Appium has [helpers for predicate search](https://github.com/appium/appium-uiauto/blob/3052dace828db2ab3d722281fb7853cbcbc3252f/uiauto/appium/app.js#L68) in app.js:
- `getFirstWithPredicate`
- `getFirstWithPredicateWeighted`
- `getAllWithPredicate`
- `getNameContains`
Here's a Ruby example:
```ruby
# Ruby example
text = 'Various uses'
predicate = "name contains[c] '#{text}' || label contains[c] '#{text}' || value contains[c] '#{text}'"
element = execute_script(%Q(au.mainApp().getFirstWithPredicate("#{predicate}");))
puts element.name # Buttons, Various uses of UIButton
```
@@ -0,0 +1,248 @@
## Automating mobile web apps
If you're interested in automating your web app in Mobile Safari on iOS or
Chrome on Android, Appium can help you. Basically, you write a normal WebDriver
test, and use Appium as the Selenium server with a special set of desired
capabilities.
### Mobile Safari on Simulator
First of all, make sure developer mode is turned on in your Safari
preferences so that the remote debugger port is open.
If you are using the simulator or a real device, you MUST run Safari before
attempting to use Appium.
Then, use desired capabilities like these to run your test in mobile Safari:
```javascript
// javascript
{
platformName: 'iOS'
, platformVersion: '7.1'
, browserName: 'Safari'
, deviceName: 'iPhone Simulator'
}
```
```python
# python
{
'platformName': 'iOS',
'platformVersion': '7.1',
'browserName': 'Safari',
'deviceName': 'iPhone Simulator'
}
```
```php
// php
public static $browsers = array(
array(
'desiredCapabilities' => array(
'platformName' => 'iOS',
'platformVersion' => '7.1',
'browserName' => 'Safari',
'deviceName' => 'iPhone Simulator'
)
)
);
```
```java
// java
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.1");
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Safari");
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator");
```
### Mobile Safari on a Real iOS Device
To be able to run your tests against mobile Safari we use the [SafariLauncher
App](https://github.com/snevesbarros/SafariLauncher) to launch Safari. Once
Safari has been launched the Remote Debugger automatically connects using
the [ios-webkit-debug-proxy](https://github.com/google/ios-webkit-debug-proxy).
**NOTE:** There is currently [a bug](https://github.com/google/ios-webkit-debug-proxy/issues/38)
in the ios-webkit-debug-proxy. You have to trust the machine before you can
run the ios-webkit-debug-proxy
against your iOS device.
### Setup
Before you can run your tests against Safari on a real device you will need to:
* Have the **ios-webkit-debug-proxy** installed, running and listening on port 27753 (see the
[hybrid docs](hybrid.md) for instructions)
* Turn on **web inspector** on iOS device (**settings > safari >
advanced**, only for iOS 6.0 and up)
* Create a **provisioning profile** that can be used to deploy the SafariLauncherApp.
To create a profile for the launcher go into the **Apple Developers Member Center** and:
* **Step 1:** Create a **new App Id** and select the WildCard App ID option and set it to "*"
* **Step 2:** Create a **new Development Profile** and for App Id select the one created in step 1.
* **Step 3:** Select your **certificate(s) and device(s)** and click next.
* **Step 4:** Set the profile name and **generate the profile**.
* **Step 5:** Download the profile and open it with a text editor.
* **Step 6:** Search for the **UUID** and the string for it is your **identity code**.
Now that you have a profile open a terminal and run the following commands:
```center
$ git clone https://github.com/appium/appium.git
$ cd appium
# Option 1: You dont define any parameters and it will set the code signing identity to 'iPhone Developer'
$ ./reset.sh --ios --real-safari
# Option 2: You define the code signing identity and allow xcode to select the profile identity code (if it can).
$ ./reset.sh --ios --real-safari --code-sign '<code signing idendity>'
# Option 3: You define both the code signing identity and profile identity code.
$ ./reset.sh --ios --real-safari --code-sign '<code signing idendity>' --profile '<retrieved profile identity code>'
# Once successfully configured and with the safari launcher built, start the server as per usual
$ node /lib/server/main.js -U <UDID>
```
### Running your test
To configure you test to run against safari simply set the **"browserName"** to be **"Safari"**.
### Java Example
```java
// java
//setup the web driver and launch the webview app.
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Safari");
URL url = new URL("http://127.0.0.1:4723/wd/hub");
AppiumDriver driver = new AppiumDriver(url, desiredCapabilities);
// Navigate to the page and interact with the elements on the guinea-pig page using id.
driver.get("http://saucelabs.com/test/guinea-pig");
WebElement div = driver.findElement(By.id("i_am_an_id"));
Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value
driver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id.
//close the app.
driver.quit();
```
### Python Example
```python
# python
# setup the web driver and launch the webview app.
capabilities = { 'browserName': 'Safari' }
driver = webdriver.Remote('http://localhost:4723/wd/hub', capabilities)
# Navigate to the page and interact with the elements on the guinea-pig page using id.
driver.get('http://saucelabs.com/test/guinea-pig');
div = driver.find_element_by_id('i_am_an_id')
# check the text retrieved matches expected value
assertEqual('I am a div', div.text)
# populate the comments field by id
driver.find_element_by_id('comments').send_keys('My comment')
# close the driver
driver.quit()
```
```php
// php
class ContextTests extends PHPUnit_Extensions_AppiumTestCase
{
public static $browsers = array(
array(
'desiredCapabilities' => array(
'platformName' => 'iOS',
'platformVersion' => '7.1',
'browserName' => 'Safari',
'deviceName' => 'iPhone Simulator'
)
)
);
public function testThings()
{
$this->get('http://saucelabs.com/test/guinea-pig');
$div = $this->byId('i_am_an_id');
$this->assertEquals('I am a div', $div->text());
$this->byId('comments')->sendKeys('My comment');
}
}
```
### Mobile Chrome on Emulator or Real Device
Pre-requisites:
* Make sure Chrome (an app with the package `com.android.chrome`) is installed on your device or emulator. Getting Chrome for the x86 version of the emulator is not currently possible without building Chromium, so you may want to run an ARM emulator and then copy a Chrome APK from a real device to get Chrome on an emulator.
* If downloaded from [NPM](https://www.npmjs.org/package/appium), or running from the [.app](https://github.com/appium/appium-dot-app), nothing needs to be done. If running from source, the `reset` script will download ChromeDriver and put it in `build`. A particular version can be specified by passing the `--chromedriver-version` option (e.g., `./reset.sh --android --chromedriver-version 2.8`), otherwise the most recent one will be retrieved.
Then, use desired capabilities like these to run your test in Chrome:
```javascript
// javascript
{
platformName: 'Android'
, platformVersion: '4.4'
, deviceName: 'Android Emulator'
, browserName: 'Chrome'
};
```
```python
# python
{
'platformName': 'Android',
'platformVersion': '4.4',
'deviceName': 'Android Emulator',
'browserName': 'Chrome'
}
```
```php
// php
public static $browsers = array(
array(
'desiredCapabilities' => array(
'platformName' => 'Android',
'platformVersion' => '4.4',
'browserName' => 'Chrome',
'deviceName' => 'Android Emulator'
)
)
);
```
```java
// java
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome");
```
Note that on 4.4+ devices, you can also use the 'Browser' `browserName` cap to automate the built-in browser. On all devices you can use the 'Chromium' `browserName` cap to automate a build of Chromium.
#### Troubleshooting chromedriver
As of Chrome version 33, a rooted device is no longer required. If running tests on older versions of Chrome, devices needed to be rooted as ChromeDriver required write access to the /data/local directory
to set Chrome's command line arguments.
If testing on Chrome app prior to version 33, ensure adb shell has read/write access to /data/local directory on the device:
```center
$ adb shell su -c chmod 777 /data/local
```
For more chromedriver specific documentation see [ChromeDriver documentation](https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android).

Some files were not shown because too many files have changed in this diff Show More