mirror of
https://github.com/appium/appium.git
synced 2026-11-10 03:44:40 +08:00
Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
209e378ccf | ||
|
|
9662914c66 | ||
|
|
44e2ed5262 | ||
|
|
8e9cf69fac | ||
|
|
9ee9664f20 | ||
|
|
ec97159c29 | ||
|
|
e7eb407fdd | ||
|
|
6941558bf7 | ||
|
|
db501a5ff6 | ||
|
|
78dcd85935 | ||
|
|
24e8c965f1 | ||
|
|
373379f2e4 | ||
|
|
fd611f7428 | ||
|
|
6ee51a8bd8 | ||
|
|
76adbe365d | ||
|
|
2366944e69 | ||
|
|
f9646dd185 | ||
|
|
ca9109f1bd | ||
|
|
5a9538fb98 | ||
|
|
67affb6d8d | ||
|
|
208be83202 |
@@ -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
|
||||
-54
@@ -1,54 +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/eslint-config-appium-ts
|
||||
- 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
|
||||
@@ -1,4 +0,0 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# Handle as a text file but merge as binary.
|
||||
package-lock.json merge=binary
|
||||
@@ -1,111 +0,0 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Create a new bug report.
|
||||
title: '🐞 bug: <title>'
|
||||
labels: [Bug, Needs Triage]
|
||||
body:
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _Make sure you are reporting an issue. For general questions, please use [http://discuss.appium.io](http://discuss.appium.io)._'
|
||||
|
||||
- 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: input
|
||||
attributes:
|
||||
label: Appium Version
|
||||
description: What Appium server version are you running?
|
||||
placeholder: Output of `appium --version`
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Appium Host Type
|
||||
description: |
|
||||
How is your Appium server being hosted? For options other than "Command Line", please add more details under "Further Information".
|
||||
options:
|
||||
- Command Line
|
||||
- Virtual Machine/Docker
|
||||
- Cloud Provider (e.g. BrowserStack/Sauce Labs)
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Are you using Appium components not maintained by the Appium team?
|
||||
description: Refer to the [Appium Ecosystem](http://appium.io/docs/en/latest/ecosystem/) page for officially-supported components.
|
||||
placeholder: Please provide the names of any third-party components.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is this issue reproducible using the latest components?
|
||||
description: |
|
||||
You can retrieve the latest server/driver/plugin version number by running `npm info <package-name> version`. If you are not up to date, please try to reproduce your issue after updating all affected components.
|
||||
options:
|
||||
- label: I confirm the issue is still reproducible with the latest component versions
|
||||
|
||||
- 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: input
|
||||
attributes:
|
||||
label: Appium Log
|
||||
description: |
|
||||
Please create a [Gist](https://gist.github.com) with your _full_ Appium server log and link it here. Alternatively, you can directly attach your logfile in the "Further Information" field below.
|
||||
|
||||
:warning: _Remember to redact or remove any sensitive information!_
|
||||
placeholder: 'https://gist.github.com/...'
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment Details
|
||||
description: |
|
||||
Please provide additional information about your environment; feel free to remove any items which are not relevant.
|
||||
|
||||
:warning: _Remember to redact or remove any sensitive information!_
|
||||
value: |
|
||||
- Debug details (`appium --show-debug-info`):
|
||||
- Last component version(s) which did _not_ exhibit the problem:
|
||||
- Platform and version of device under test:
|
||||
- Real device or emulator/simulator:
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Minimal Reproducible Example
|
||||
description: |
|
||||
Please provide [the smallest, complete code snippet](https://stackoverflow.com/help/minimal-reproducible-example) that Appium's maintainers can run to reproduce the issue. 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. Failing this, any sort of reproduction steps are better than nothing!
|
||||
|
||||
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: Further Information
|
||||
description: If needed, please provide additional information about your issue (attachments, links, references, etc.).
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _Make sure you are reporting an issue. For general questions, please use [http://discuss.appium.io](http://discuss.appium.io)._'
|
||||
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: ❓ Question
|
||||
url: https://discuss.appium.io/
|
||||
about: Please use the Appium forum for any questions.
|
||||
@@ -1,33 +0,0 @@
|
||||
name: 💡 Feature Request
|
||||
description: Suggest an idea for this project.
|
||||
title: "💡 feat: <title>"
|
||||
labels: [Enhancement]
|
||||
body:
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem?
|
||||
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...].
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the solution you'd like.
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe alternatives you've considered.
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
validations:
|
||||
required: false
|
||||
@@ -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 Guide](https://appium.io/docs/en/latest/contributing/)
|
||||
- [ ] 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 the 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...
|
||||
@@ -1,41 +0,0 @@
|
||||
name: Setup Node, Install, Build
|
||||
|
||||
description: |
|
||||
Common setup for Appium CI jobs: checkout, setup Node, install deps, optional build, optional V8 cache clear.
|
||||
|
||||
inputs:
|
||||
node-version:
|
||||
description: Node.js version to setup
|
||||
required: true
|
||||
install-command:
|
||||
description: npm install command
|
||||
required: false
|
||||
default: npm ci --foreground-scripts
|
||||
run-build:
|
||||
description: Whether to run npm run build
|
||||
required: false
|
||||
default: 'true'
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Use Node.js ${{ inputs.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
cache: npm
|
||||
- name: SocketDev Security Check
|
||||
uses: SocketDev/action@v1
|
||||
with:
|
||||
mode: firewall-free
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
# Replace npm with sfw npm in the install command
|
||||
install_cmd="${{ inputs.install-command }}"
|
||||
install_cmd="${install_cmd//npm /sfw npm }"
|
||||
$install_cmd
|
||||
- name: Build packages
|
||||
if: ${{ inputs.run-build == 'true' }}
|
||||
shell: bash
|
||||
run: npm run build
|
||||
@@ -1,149 +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/base-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/base-plugin/**']
|
||||
|
||||
- label: '@appium/storage-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/storage-plugin/**']
|
||||
|
||||
- label: '@appium/docutils'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/docutils/**']
|
||||
|
||||
- label: '@appium/driver-test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/driver-test-support/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium-ts'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium-ts/**']
|
||||
|
||||
- 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/logger'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/logger/**']
|
||||
|
||||
- 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/strongbox'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/strongbox/**']
|
||||
|
||||
- label: '@appium/test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/test-support/**']
|
||||
|
||||
- label: '@appium/tsconfig'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/tsconfig/**']
|
||||
|
||||
- label: '@appium/types'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/types/**']
|
||||
|
||||
- label: '@appium/universal-xml-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/universal-xml-plugin/**']
|
||||
@@ -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
|
||||
@@ -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@v5
|
||||
@@ -1,199 +0,0 @@
|
||||
name: Appium Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# 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:
|
||||
branches:
|
||||
- master
|
||||
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/**'
|
||||
|
||||
env:
|
||||
CI: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
prepare_matrix:
|
||||
uses: appium/appium-workflows/.github/workflows/node-lts-matrix.yml@main
|
||||
|
||||
prepare_e2e_packages:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
packages: ${{ steps.discover-packages.outputs.packages }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Discover packages with e2e tests
|
||||
id: discover-packages
|
||||
run: |
|
||||
packages=()
|
||||
for package_dir in packages/*/; do
|
||||
package_json="${package_dir}package.json"
|
||||
if [[ -f "$package_json" ]]; then
|
||||
# Check if package.json has test:e2e script and it's not a no-op
|
||||
has_e2e=$(node -e "
|
||||
try {
|
||||
const pkg = require('./$package_json');
|
||||
const script = pkg.scripts && pkg.scripts['test:e2e'];
|
||||
if (script && !script.includes('echo') && !script.includes('No e2e tests')) {
|
||||
console.log('true');
|
||||
}
|
||||
} catch(e) {
|
||||
// Ignore errors
|
||||
}
|
||||
")
|
||||
if [[ "$has_e2e" == "true" ]]; then
|
||||
# Use the directory path without packages/ prefix (remove trailing slash)
|
||||
package_name="${package_dir%/}"
|
||||
package_name="${package_name#packages/}"
|
||||
packages+=("$package_name")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
# Convert array to JSON array for GitHub Actions matrix
|
||||
if [[ ${#packages[@]} -eq 0 ]]; then
|
||||
echo "No packages with e2e tests found"
|
||||
packages_json="[]"
|
||||
else
|
||||
# Use jq to create a compact single-line JSON array
|
||||
packages_json=$(printf '%s\n' "${packages[@]}" | jq -R '.' | jq -s '.' | jq -c '.')
|
||||
fi
|
||||
echo "packages=$packages_json" >> $GITHUB_OUTPUT
|
||||
echo "Found packages with e2e tests:"
|
||||
echo "$packages_json" | jq -r '.[]' | sed 's/^/ - /'
|
||||
|
||||
test-smoke:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Smoke Tests
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
install-command: npm ci --foreground-scripts
|
||||
run-build: 'true'
|
||||
- name: Run smoke tests
|
||||
run: npm run test:smoke
|
||||
|
||||
test-unit:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Unit Tests
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
install-command: npm ci --foreground-scripts
|
||||
run-build: 'true'
|
||||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
|
||||
test-types:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Type Tests
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
install-command: npm ci --foreground-scripts
|
||||
run-build: 'true'
|
||||
- name: Run type tests
|
||||
run: npm run test:types
|
||||
|
||||
test-e2e:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
- prepare_e2e_packages
|
||||
name: E2E Tests - ${{ matrix.package_dir }} (Node ${{ matrix.node-version }})
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
package_dir: ${{ fromJSON(needs.prepare_e2e_packages.outputs.packages) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
install-command: npm ci --foreground-scripts
|
||||
run-build: 'true'
|
||||
- name: Run E2E tests for ${{ matrix.package_dir }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
cd "packages/${{ matrix.package_dir }}"
|
||||
npm run test:e2e
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup and install (no build)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'false'
|
||||
- name: ESLint
|
||||
run: npm run lint:ci
|
||||
@@ -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@v6
|
||||
|
||||
- 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 }}
|
||||
@@ -1,44 +0,0 @@
|
||||
# Collects translation statistics from Crowdin for the last calendar month
|
||||
# and posts them to Slack grouped by project, language, and translator
|
||||
|
||||
name: Crowdin Translation Statistics
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Run on the first day of each month at 9:00 AM UTC
|
||||
- cron: 0 9 1 * *
|
||||
|
||||
jobs:
|
||||
collect-stats:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- project_id_var: CROWDIN_DOCS_PROJECT_ID
|
||||
project_name: appium-documentation
|
||||
- project_id_var: CROWDIN_INSPECTOR_PROJECT_ID
|
||||
project_name: appium-inspector
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Collect Crowdin Stats for ${{ matrix.project_name }}
|
||||
id: crowdin-stats
|
||||
run: node ./scripts/crowdin-stats.mjs > crowdin-stats-${{ matrix.project_name }}.json
|
||||
env:
|
||||
CROWDIN_PROJECT_ID: ${{ vars[matrix.project_id_var] }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_DOCS_TOKEN }}
|
||||
- name: Post to Slack for ${{ matrix.project_name }}
|
||||
uses: slackapi/slack-github-action@v3.0.3
|
||||
with:
|
||||
errors: true
|
||||
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
webhook-type: incoming-webhook
|
||||
payload-file-path: crowdin-stats-${{ matrix.project_name }}.json
|
||||
@@ -1,38 +0,0 @@
|
||||
# Retrieves non-English translations from Crowdin and creates a PR with new changes
|
||||
|
||||
name: Sync Crowdin Docs Translations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 0 0 * * *
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Crowdin Sync
|
||||
run: npm run crowdin-sync-docs-translations
|
||||
env:
|
||||
# appium-documentation
|
||||
CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_DOCS_PROJECT_ID }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_DOCS_TOKEN }}
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v8.1.1
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
commit-message: 'docs(appium): Update documentation translations'
|
||||
title: 'docs(appium): Update documentation translations'
|
||||
branch: crowdin-sync-${{ github.run_id }}
|
||||
body: 'Automated Update of Documentation Translations: https://crowdin.com/project/appium-documentation'
|
||||
@@ -1,31 +0,0 @@
|
||||
# Updates Crowdin with any changes in document files in English
|
||||
|
||||
name: Update Crowdin English Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'packages/appium/docs/en/**.md'
|
||||
- 'packages/appium/docs/mkdocs-en.yml'
|
||||
- '.github/workflows/crowdin-update-docs-resources.yml' # this file
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Crowdin Update
|
||||
run: npm run crowdin-update-docs
|
||||
env:
|
||||
# appium-documentation
|
||||
CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_DOCS_PROJECT_ID }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_DOCS_TOKEN }}
|
||||
@@ -1,68 +0,0 @@
|
||||
name: Appium Deploy
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prepare_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
versions: ${{ steps.generate-matrix.outputs.lts }}
|
||||
steps:
|
||||
- name: Select all current LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
uses: msimerson/node-lts-versions@v2
|
||||
|
||||
check:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Check
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
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
|
||||
@@ -1,53 +0,0 @@
|
||||
name: Build Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/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:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/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@v6
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@v1.12.1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: PIP_BREAK_SYSTEM_PACKAGES=1 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
|
||||
@@ -1,31 +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
|
||||
env:
|
||||
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: master
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1.12.1
|
||||
- name: Install fossa-cli
|
||||
run: |
|
||||
curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
|
||||
- name: Run FOSSA analysis
|
||||
run: |
|
||||
if [ -n "$FOSSA_API_KEY" ]; then
|
||||
fossa analyze
|
||||
fossa test
|
||||
else
|
||||
echo "License checks did not run. FOSSA_API_KEY is not defined for this fork."
|
||||
fi
|
||||
@@ -1,37 +0,0 @@
|
||||
# Collects GitHub contribution statistics from the Appium organization for the last calendar month
|
||||
# and posts it to Slack
|
||||
|
||||
name: GitHub Contribution Statistics
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Run on the first day of each month at 09:00 AM UTC
|
||||
- cron: 0 9 1 * *
|
||||
|
||||
jobs:
|
||||
collect-contrib-stats:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Collect GitHub Contribution Stats
|
||||
id: github-stats
|
||||
run: node ./scripts/github-contrib-stats.mjs > github-contrib-stats.json
|
||||
env:
|
||||
# GITHUB_TOKEN is optional - if not provided, uses unauthenticated requests (rate limited)
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Post to Slack
|
||||
uses: slackapi/slack-github-action@v3.0.3
|
||||
with:
|
||||
errors: true
|
||||
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
webhook-type: incoming-webhook
|
||||
payload-file-path: github-contrib-stats.json
|
||||
@@ -1,137 +0,0 @@
|
||||
name: Appium Server Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Dry run (no publishing or tagging)'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master' && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git user
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
|
||||
- name: Run Lerna publish
|
||||
env:
|
||||
# for lerna createRelease
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Running lerna publish in dry-run mode"
|
||||
printf "n\n" | npx lerna version --exact --no-git-tag-version --no-push
|
||||
else
|
||||
echo "Running lerna publish for real"
|
||||
set +e
|
||||
release_output="$(npm run release -- --yes 2>&1)"
|
||||
release_exit_code=$?
|
||||
set -e
|
||||
printf '%s\n' "$release_output"
|
||||
|
||||
if [ $release_exit_code -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$release_output" == *"fatal: tag '"*"' already exists"* ]]; then
|
||||
existing_tag="$(printf '%s\n' "$release_output" | sed -n "s/.*fatal: tag '\\([^']*\\)' already exists.*/\\1/p" | head -n 1)"
|
||||
if [ -z "$existing_tag" ]; then
|
||||
echo "Detected existing tag failure, but could not parse tag name"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
|
||||
echo "Detected existing tag failure for ${existing_tag}; attempting scoped publish recovery from tagged commit"
|
||||
git fetch --tags --force origin
|
||||
tagged_commit="$(git rev-list -n 1 "$existing_tag")"
|
||||
if [ -z "$tagged_commit" ]; then
|
||||
echo "Tag ${existing_tag} was not found after fetching tags"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
|
||||
git checkout "$tagged_commit"
|
||||
missing=()
|
||||
for pkg_json in packages/*/package.json; do
|
||||
if [ ! -f "$pkg_json" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$(jq -r '.private // false' "$pkg_json")" = "true" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
pkg_name="$(jq -r '.name // empty' "$pkg_json")"
|
||||
pkg_version="$(jq -r '.version // empty' "$pkg_json")"
|
||||
if [ -z "$pkg_name" ] || [ -z "$pkg_version" ]; then
|
||||
echo "Skipping malformed package manifest: $pkg_json"
|
||||
continue
|
||||
fi
|
||||
|
||||
pkg_spec="${pkg_name}@${pkg_version}"
|
||||
if ! npm view "$pkg_spec" version >/dev/null 2>&1; then
|
||||
missing+=("$pkg_spec")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing[@]} -gt 0 ]; then
|
||||
echo "Missing package versions on npm before scoped recovery:"
|
||||
printf ' - %s\n' "${missing[@]}"
|
||||
echo "Publishing missing packages one-by-one with scope"
|
||||
for pkg_spec in "${missing[@]}"; do
|
||||
pkg_name="${pkg_spec%@*}"
|
||||
echo "Publishing ${pkg_name}"
|
||||
set +e
|
||||
npx lerna publish from-package --yes --scope "$pkg_name"
|
||||
scoped_exit_code=$?
|
||||
set -e
|
||||
if [ $scoped_exit_code -ne 0 ]; then
|
||||
echo "Scoped publish exited non-zero for ${pkg_name}; will verify on npm"
|
||||
fi
|
||||
done
|
||||
|
||||
final_missing=()
|
||||
for pkg_spec in "${missing[@]}"; do
|
||||
if ! npm view "$pkg_spec" version >/dev/null 2>&1; then
|
||||
final_missing+=("$pkg_spec")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#final_missing[@]} -gt 0 ]; then
|
||||
echo "Recovery incomplete after scoped retries. Still missing:"
|
||||
printf ' - %s\n' "${final_missing[@]}"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "All publishable workspace package versions are present on npm; treating recovery as successful."
|
||||
else
|
||||
echo "Release failed and no known recovery condition matched"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
fi
|
||||
@@ -1,41 +0,0 @@
|
||||
# This job only publishes new releases on GitHub and updates the changelog, without publishing to NPM.
|
||||
# It can be used if the standard release workflow failed and *only* published to NPM.
|
||||
|
||||
name: Appium Server Version (Without NPM Publish)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
version:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master' && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git user
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
|
||||
- name: Run Lerna version
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx lerna version --exact --yes
|
||||
@@ -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@v4
|
||||
with:
|
||||
label: On Hold
|
||||
state: absent
|
||||
@@ -1,10 +0,0 @@
|
||||
name: Conventional Commits
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
uses: appium/appium-workflows/.github/workflows/pr-title.yml@main
|
||||
with:
|
||||
config-preset: angular
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Publish docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_run:
|
||||
workflows: ["Appium Server Release"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
- name: Install dependencies (Python)
|
||||
run: npm run install-docs-deps
|
||||
- name: Fetch gh-pages
|
||||
run: |
|
||||
git fetch origin gh-pages:gh-pages || true
|
||||
- name: Publish docs
|
||||
run: |
|
||||
npm run docs:publish
|
||||
@@ -1,30 +0,0 @@
|
||||
name: Validate Renovate Configs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/renovate.yml' # this file
|
||||
- '.renovaterc.json'
|
||||
- 'renovate/default.json'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
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@v6
|
||||
- name: Validate Renovate Config
|
||||
uses: rinchsan/renovate-config-validator@v0.2.1
|
||||
with:
|
||||
pattern: '{.renovaterc.json,renovate/default.json}'
|
||||
+5
-44
@@ -1,21 +1,17 @@
|
||||
.irb-history
|
||||
*.swp
|
||||
.DS_Store
|
||||
npm*.log
|
||||
node_modules
|
||||
sample-code
|
||||
*.trace
|
||||
xcuserdata
|
||||
*.sublime-*
|
||||
test/functional/_joined
|
||||
*.iml
|
||||
!examples/java/*.iml
|
||||
*.autosave
|
||||
.idea/
|
||||
!examples/java/.idea/
|
||||
*.log
|
||||
*.t
|
||||
artifacts
|
||||
input
|
||||
./output
|
||||
lib/devices/android/bootstrap/bin/*
|
||||
lib/devices/android/bootstrap/local.properties
|
||||
lib/devices/android/bootstrap/project.properties
|
||||
@@ -24,45 +20,10 @@ 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__
|
||||
certificate.cert
|
||||
certificate.key
|
||||
|
||||
# csharp
|
||||
*.pyc
|
||||
*.pdb
|
||||
.vs
|
||||
|
||||
#vscode
|
||||
.history
|
||||
|
||||
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
|
||||
\!packages/*/LICENSE
|
||||
local_appium_home
|
||||
*.tgz
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
[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
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"laxcomma": true,
|
||||
"strict": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"node": true,
|
||||
"eqeqeq": true,
|
||||
"trailing": true,
|
||||
"indent": 2
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
require: ['ts-node/register'],
|
||||
// forbids use of .only() in CI
|
||||
forbidOnly: Boolean(process.env.CI),
|
||||
color: true,
|
||||
timeout: '5s',
|
||||
};
|
||||
+26
@@ -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
|
||||
@@ -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
|
||||
@@ -1,15 +0,0 @@
|
||||
**/node_modules/**
|
||||
**/build/**
|
||||
**/fixtures/**
|
||||
**/*.min.*
|
||||
**/*.md
|
||||
package-lock.json
|
||||
package.json
|
||||
**/.vscode/**
|
||||
**/*.html
|
||||
**/generated/**
|
||||
# generated
|
||||
packages/types/lib/appium-config.ts
|
||||
**/*.hbs
|
||||
|
||||
/.nx/workspace-data
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["github>appium/appium//renovate/default"],
|
||||
"schedule": [
|
||||
"after 10pm",
|
||||
"before 5:00am"
|
||||
],
|
||||
"timezone": "America/Vancouver"
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
language: objective-c
|
||||
xcode_sdk: 7.1
|
||||
notifications:
|
||||
email: true
|
||||
slack:
|
||||
secure: E1at9Fi4d2eLagKInwGOfvvcSr8rrVti+N3HzvlcL9UcYavwzfAstMX/nXoHTl8LR5/Dh4Sdja2+NeJp2uVNwlK7aVKk5egQ8q6qAEmcXlWgjqyyTusB1lgiaOQnbOuqsntg/3X5sP8nz5+V3sggelPnOrVwNCCkVXXSff2SHhE=
|
||||
rvm:
|
||||
- 2.1.1
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "/with\\-ci$/"
|
||||
git:
|
||||
submodules: false
|
||||
env:
|
||||
global:
|
||||
- SAUCE_REST_ROOT=https://saucelabs.com/rest/v1
|
||||
- APPIUM_HOST=ondemand.saucelabs.com
|
||||
- APPIUM_PORT=80
|
||||
- SAUCE_USERNAME=appium
|
||||
- IOS_CONCURRENCY=30
|
||||
- ANDROID_CONCURRENCY=30
|
||||
- SELENDROID_CONCURRENCY=10
|
||||
- GAPPIUM_CONCURRENCY=10
|
||||
- secure: GXGFbQptLEsKlaWnpOL2EB9hqQ4XBT6tqg7REt5j1h1jYBsfHQHSgSLt1jpzOF5kooXVbw2K7IrZyNVBXEUHR00Hp6O72FBOd+SSj8uPCJBLjAOaJWs0ZtujqGHwHpe6gadFfn0L7q0ffoV5OJVeNHHcuw4f9BaA78fTFNfm1jE=
|
||||
- HTTP_RETRIES=5
|
||||
- HTTP_RETRY_DELAY=5000
|
||||
- DEBUG_CONNECTION=1
|
||||
- MOCHA_INIT_TIMEOUT=600000
|
||||
- LAUNCH_TIMEOUT='{"global":90000,"afterSimLaunch":30000}'
|
||||
matrix:
|
||||
- CI_CONFIG=unit
|
||||
# - CI_CONFIG=android
|
||||
# - CI_CONFIG=ios
|
||||
# - CI_CONFIG=gappium
|
||||
# - CI_CONFIG=selendroid
|
||||
before_script:
|
||||
- gem install --no-rdoc --no-ri appium_doc_lint
|
||||
- "./ci/installers/install-node.sh"
|
||||
- 'echo Node.js version: `node -v`'
|
||||
- npm install -g jshint grunt-cli mocha
|
||||
- npm install
|
||||
- "./ci/installers/install-sauce-connect.sh"
|
||||
- "./ci/before-script-extra.sh"
|
||||
- "ulimit -n 8000"
|
||||
# disabling sauce-connect until travis ichef issue is sorted
|
||||
# - "./ci/start-sauce-connect.sh"
|
||||
script:
|
||||
- "./ci/script.sh"
|
||||
- bash -c 'while true; do ping ondemand.saucelabs.com &> /dev/null; sleep 10; done' &
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"stateful.runme"
|
||||
]
|
||||
}
|
||||
Vendored
-50
@@ -1,50 +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"
|
||||
}
|
||||
],
|
||||
"version": "0.2.0"
|
||||
}
|
||||
Vendored
-19
@@ -1,19 +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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# Aggregate Changelog
|
||||
|
||||
The Appium monorepo 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 Changelog](packages/appium/CHANGELOG.md)
|
||||
* [Appium 1.x Changelog](https://github.com/appium/appium/blob/1.x/CHANGELOG.md)
|
||||
|
||||
## Drivers / Clients
|
||||
Refer to the [Appium Ecosystem](https://appium.io/docs/en/latest/ecosystem/) page for links
|
||||
to driver/client documentation
|
||||
|
||||
## Plugins
|
||||
* [execute-driver-plugin](packages/execute-driver-plugin/CHANGELOG.md)
|
||||
* [images-plugin](packages/images-plugin/CHANGELOG.md)
|
||||
* [relaxed-caps-plugin](packages/relaxed-caps-plugin/CHANGELOG.md)
|
||||
* [storage-plugin](packages/storage-plugin/CHANGELOG.md)
|
||||
* [universal-xml-plugin](packages/universal-xml-plugin/CHANGELOG.md)
|
||||
|
||||
## Other Modules
|
||||
* [base-driver](packages/base-driver/CHANGELOG.md)
|
||||
* [base-plugin](packages/base-plugin/CHANGELOG.md)
|
||||
* [docutils](packages/docutils/CHANGELOG.md)
|
||||
* [driver-test-support](packages/driver-test-support/CHANGELOG.md)
|
||||
* [eslint-config-appium-ts](packages/eslint-config-appium-ts/CHANGELOG.md)
|
||||
* [fake-driver](packages/fake-driver/CHANGELOG.md)
|
||||
* [fake-plugin](packages/fake-plugin/CHANGELOG.md)
|
||||
* [logger](packages/logger/CHANGELOG.md)
|
||||
* [opencv](packages/opencv/CHANGELOG.md)
|
||||
* [plugin-test-support](packages/plugin-test-support/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)
|
||||
* [types](packages/types/CHANGELOG.md)
|
||||
|
||||
## Removed Modules
|
||||
The changelog links used for these modules lead to the last version of their changelog file.
|
||||
* [doctor](https://github.com/appium/appium/blob/8daf5e123ac14c8325acf504fb33eb28e1a3dd78/packages/doctor/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/20805))
|
||||
* [eslint-config-appium](https://github.com/appium/appium/blob/4b3a8c2197a587ec5a2606b662e4e7667a7852cb/packages/eslint-config-appium/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/20856))
|
||||
* [gulp-plugins](https://github.com/appium/appium/blob/0823f0b60e40395cd1dc3b72cfa3c0092bc81302/packages/gulp-plugins/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/17943))
|
||||
* [typedoc-plugin-appium](https://github.com/appium/appium/blob/d6204b6902074210943d7bbbf72d139b9b170a20/packages/typedoc-plugin-appium/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/19465))
|
||||
+1599
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
# Contributing to Appium
|
||||
|
||||
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 sure you read and follow the setup instructions in the README first.
|
||||
|
||||
### Running Appium from Source and doing dev on Appium
|
||||
|
||||
This is all detailed in our [running from source doc](/docs/en/contributing-to-appium/appium-from-source.md)
|
||||
-189
@@ -1,189 +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)
|
||||
* [@mykola-mokhnach](https://github.com/mykola-mokhnach)
|
||||
* [@eglitise](https://github.com/eglitise)
|
||||
* [@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 (or 2, whichever is higher) 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 (along with their primary areas(s) of ownership or maintenance):
|
||||
|
||||
* [@dan-maor](https://github.com/Dan-Maor) - XCUITest driver and iOS internals
|
||||
* [@dor-bl](https://github.com/Dor-bl) - DotNet client
|
||||
* [@Delta456](https://github.com/Delta456) - appium-mcp, iOS support libraries
|
||||
* [@eglitise](https://github.com/eglitise) - Appium server, Inspector
|
||||
* [@harsha509](https://github.com/harsha509) - appium-ios-tuntap
|
||||
* [@jlipps](https://github.com/jlipps) - Appium server, Inspector
|
||||
* [@kazucocoa](https://github.com/KazuCocoa) - all Appium projects
|
||||
* [@laolubenson](https://github.com/laolubenson) - DotNet client
|
||||
* [@mwakizaka](https://github.com/mwakizaka) - XCUITest driver
|
||||
* [@mykola-mokhnach](https://github.com/mykola-mokhnach) - all Appium projects
|
||||
* [@navin772](https://github.com/navin772) - appium-mcp, iOS support libraries
|
||||
* [@rerorero](https://github.com/rerorero) - XCUITest/UIA2 driver
|
||||
* [@saikrishna321](https://github.com/saikrishna321) - Java client
|
||||
* [@srinivasantarget](https://github.com/SrinivasanTarget) - Java client
|
||||
* [@tomriddly](https://github.com/tomriddly) - appium-ios-device
|
||||
* [@valfirst](https://github.com/valfirst) - Java client
|
||||
|
||||
|
||||
See [Emeritus Contributors](#emeritus-contributors) below for a list of people who formerly made
|
||||
significant contributions to the project but are no longer actively committing.
|
||||
|
||||
### Other Contributors
|
||||
|
||||
Other, less formal, kinds of contribution are outlined in our [Contributing Guide](https://appium.io/docs/en/latest/contributing/).
|
||||
We also very much appreciate those who spend their valuable time assisting with the [Appium forums](https://discuss.appium.io).
|
||||
Current high-level forum contributors and mods include:
|
||||
|
||||
* [aleksei](https://discuss.appium.io/u/aleksei/summary)
|
||||
* [wreed](https://discuss.appium.io/u/wreed/summary)
|
||||
|
||||
### Sponsorship
|
||||
|
||||
The Appium project welcomes the sponsorship of individuals and organizations. There are two types
|
||||
of sponsorship: those related to contributions of Appium maintenance and leadership, and those
|
||||
related to contributions of funds. Both are extremely important to the ongoing health of the
|
||||
project. Financial sponsorship is mediated through our [OpenCollective page](https://opencollective.com/appium).
|
||||
Sponsorship tiers and benefits are described below:
|
||||
|
||||
- **Development Partners**: The primary need of any open source project is for sustained maintenance and contributorship. Companies that officially sponsor such development with dedicated employee time are recognized as Development Partners, and receive the same benefits as the highest tier of financial sponsorship. To be considered a Development Partner, a company must devote at least 50% of a full-time employee's time to Appium maintenance. This means that the contributors designated by the company must have been appointed as "committers" in good standing of one or more core Appium repositories. (See above for a description of how to become a committer).
|
||||
- **Strategic Partners**: Representing the highest tier of ongoing financial support for the project, Strategic Partners are what make our compensation scheme for contributors possible, and we thank them for their significant investment into the project! More than financial contribution, Strategic Partners help elevate Appium's position in the industry through marketing and evangelism efforts, and partner with the Appium team to help make Appium better. Along with the Development Partners, Strategic Partners have their logos displayed prominently on our website, and have the ability to link to their Appium-related products in a few relevant places in our documentation.
|
||||
- **Gold, Silver, and Bronze Sponsors**: these sponsorship levels correspond to different amounts of recurring financial contribution that generously support our contributor compensation scheme. Sponsors at these levels also have the opportunity to display their logo on our website.
|
||||
- **Backers**: individuals who benefit from the Appium project can also donate on a one-time or recurring basis, at any amount, and will be recognized as Backers for their contribution!
|
||||
|
||||
To become a sponsor at one of these levels, follow the process indicated at the [OpenCollective
|
||||
page](https://opencollective.com/appium).
|
||||
|
||||
### Compensation Scheme
|
||||
|
||||
With funds received through sponsorship, the Appium project wants to incentivize contributions of
|
||||
code, documentation efforts, maintenance, and project leadership. We have developed a scheme
|
||||
(inspired by one developed at the [WebdriverIO](https://github.com/webdriverio/webdriverio)
|
||||
project) for disbursing funds on a monthly basis to those who contribute to the project, as well as
|
||||
some other "upstream" open source projects.
|
||||
|
||||
Each month, 15% of sponsorship funds received will be donated to upstream projects, based on the
|
||||
discretion of the current TC. At this point, no attempt will be made to formalize quantitative
|
||||
notions of relevance. If you manage a project upstream of Appium and would like to be considered as
|
||||
part of this donation group, give us a shout!
|
||||
|
||||
Of the remaining 85% of sponsorship funds, 70% (roughly 60% of the original total) will go to
|
||||
project Committers (i.e., those in a role of maintenance), and 30% (roughly 25% of the original
|
||||
total) will go to Contributors (i.e., those making one-off or periodic contributions). The way that
|
||||
Committers and Contributors are paid for their efforts differs.
|
||||
|
||||
For Committers, each Committer will keep a monthly time sheet of hours contributed to the project.
|
||||
At the end of each month, the hours tracked from all Committers will be totalled, and then the
|
||||
Committer-allocated funds will be disbursed (via OpenCollective) on a pro rata basis. Within this
|
||||
scheme, Committers agree not to submit hours worked as part of their employment with a Development
|
||||
Partner (since this is part of the "sponsorship" contribution of the Development Partner).
|
||||
|
||||
For Contributors, when they make contributions which are successfully merged into the project,
|
||||
a Committer can discretionarily assign a "value tier" to the contribution. The "value tiers" and
|
||||
corresponding payouts are as follows:
|
||||
|
||||
- XS: a trivial change (e.g. a typo change or applying of an automatically suggested security
|
||||
patch). \$0.
|
||||
- S: a small but useful change. \$25.
|
||||
- M: a medium-small or slightly more complex change. \$50.
|
||||
- L: a very valuable or sizable change. \$100.
|
||||
- XL: a massive change or set of changes. \$500.
|
||||
|
||||
At the end of each month, Committers will total up the number of changes receiving potential
|
||||
payout. If the total amount of funds allocated for Contributor payout exceeds the total amount to
|
||||
be paid, then each Contributor will receive an OpenCollective link to claim their funds. If not
|
||||
enough funds exist to cover all payouts, then the payout amounts will be scaled down in a pro rata
|
||||
fashion.
|
||||
|
||||
The scope for Committer or Contributor payouts is work completed within any "core" Appium
|
||||
repository (i.e., those officially maintained by the Appium team, residing within the Appium
|
||||
organization on GitHub, under `https://github.com/appium`).
|
||||
|
||||
Some disclaimers: Payments will happen exclusively via OpenCollective. Recipients of funds are
|
||||
responsible for maintaining their OpenCollective account in a fashion where funds can be disbursed,
|
||||
and are responsible for any and all tax, financial, or legal consequences of receiving money in
|
||||
this way. Receipt of funds from this scheme holds the Appium project and the OpenJS Foundation free
|
||||
of any claim or obligation. While this document exists to clearly and publicly lay out the terms
|
||||
under which payments are generally made, the TC retains the right to grant or withhold funding on
|
||||
a discretionary of special basis. Basically, this scheme is run at the project's discretion, and is
|
||||
not a public service. Making contributions to the project under this scheme does not obligate the
|
||||
project to pay you for such work, or otherwise compensate you in any way.
|
||||
|
||||
### 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.
|
||||
|
||||
### Emeritus Contributors
|
||||
|
||||
* [@aluedeke](https://github.com/aluedeke)
|
||||
* [@astro03](https://github.com/Astro03)
|
||||
* [@bayandin](https://github.com/bayandin)
|
||||
* [@boneskull](https://github.com/boneskull)
|
||||
* [@bootstraponline](https://github.com/bootstraponline)
|
||||
* [@dandoveralba](https://github.com/dandoveralba)
|
||||
* [@ddkjin](https://github.com/ddkjin)
|
||||
* [@drpy](https://github.com/drpy)
|
||||
* [@dylanLacey](https://github.com/DylanLacey)
|
||||
* [@filmaj](https://github.com/filmaj)
|
||||
* [@gempesaw](https://github.com/gempesaw)
|
||||
* [@hugs](https://github.com/hugs)
|
||||
* [@imurchie](https://github.com/imurchie)
|
||||
* [@jamieEdge](https://github.com/JamieEdge)
|
||||
* [@jdeff](https://github.com/jdeff)
|
||||
* [@jonahss](https://github.com/Jonahss)
|
||||
* [@maudineormsby](https://github.com/maudineormsby)
|
||||
* [@moizjv](https://github.com/moizjv)
|
||||
* [@peepa](https://github.com/peepa)
|
||||
* [@penguinho](https://github.com/penguinho)
|
||||
* [@sbonebrake](https://github.com/sbonebrake)
|
||||
* [@scottdixon](https://github.com/scottdixon)
|
||||
* [@sebv](https://github.com/sebv)
|
||||
* [@sravanmedarapu](https://github.com/sravanmedarapu)
|
||||
* [@stuartbrussell-intuit](https://github.com/stuartbrussell-intuit)
|
||||
* [@tikhomirovSergey](https://github.com/TikhomirovSergey)
|
||||
* [@titusfortner](https://github.com/titusfortner)
|
||||
* [@vgrigoruk](https://github.com/vgrigoruk)
|
||||
* [@vmaxim](https://github.com/vmaxim)
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
"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;
|
||||
|
||||
module.exports = function (grunt) {
|
||||
grunt.initConfig({
|
||||
jshint: {
|
||||
options: {
|
||||
laxcomma: true
|
||||
, node: true
|
||||
, strict: true
|
||||
, indent: 2
|
||||
, undef: true
|
||||
, unused: true
|
||||
, eqeqeq: true
|
||||
},
|
||||
files: {
|
||||
src: ['*.js', './**/*.js'],
|
||||
options: {
|
||||
ignores: ['./submodules/**/*.js', './node_modules/**/*.js', './sample-code/**/*.js', './test/**/*.js', './lib/server/static/**/*.js', './lib/devices/firefoxos/atoms/*.js', './lib/devices/ios/uiauto/**/*.js']
|
||||
}
|
||||
},
|
||||
test: {
|
||||
src: ['test/**/*.js']
|
||||
, options: {
|
||||
ignores: ['./test/harmony/**/*.js', './test/functional/_joined/*.js']
|
||||
, expr: true
|
||||
, globals: {
|
||||
'describe': true
|
||||
, 'it': true
|
||||
, 'before': true
|
||||
, 'after': true
|
||||
, 'beforeEach': true
|
||||
, 'afterEach': true
|
||||
}
|
||||
}
|
||||
},
|
||||
examples: {
|
||||
src: ['sample-code/examples/node/**/*.js']
|
||||
, options: {
|
||||
expr: true
|
||||
, globals: {
|
||||
'describe': true
|
||||
, 'it': true
|
||||
, 'before': true
|
||||
, 'after': true
|
||||
, 'beforeEach': true
|
||||
, 'afterEach': true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, jscs: {
|
||||
files: [
|
||||
'**/*.js', '!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/**'],
|
||||
options: {
|
||||
config: ".jscs.json"
|
||||
}
|
||||
}
|
||||
, mochaTest: {
|
||||
unit: ['test/unit/*.js']
|
||||
, appiumutils: ['test/functional/appium/appiumutils.js']
|
||||
}
|
||||
, mochaTestConfig: {
|
||||
options: {
|
||||
timeout: 60000,
|
||||
reporter: 'spec'
|
||||
}
|
||||
}
|
||||
, maxBuffer: 2000 * 1024
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-newer');
|
||||
grunt.loadNpmTasks('grunt-mocha-test');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks("grunt-jscs-checker");
|
||||
grunt.registerTask('lint', ['newer:jshint','jscs']);
|
||||
grunt.registerTask('test', 'mochaTest:unit');
|
||||
grunt.registerTask('unit', 'mochaTest: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);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -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.
|
||||
|
||||
@@ -1,221 +1,149 @@
|
||||
<p align="center">
|
||||
<a href="https://appium.io/">
|
||||
<img alt="Appium" src="https://raw.githubusercontent.com/appium/appium/master/packages/appium/docs/overrides/assets/images/appium-logo-horiz.png" width="500">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
Cross-platform test automation for native, hybrid, mobile web and desktop apps.
|
||||
</p>
|
||||
## Appium
|
||||
|
||||
<div align="center">
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://david-dm.org/appium/appium)
|
||||
[](https://david-dm.org/appium/appium#info=devDependencies)
|
||||
[](https://travis-ci.org/appium/appium)
|
||||
[](https://saucelabs.com/u/appium)
|
||||
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_shield)
|
||||
[](https://github.com/vshymanskyy/StandWithUkraine/)
|
||||
[](https://www.unrwa.org/)
|
||||
[](https://saucelabs.com/u/appium)
|
||||
|
||||
</div>
|
||||
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).
|
||||
|
||||
***
|
||||
**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!
|
||||
|
||||
<p align="center"><b>
|
||||
<a href="https://appium.io">Documentation</a> |
|
||||
<a href="https://appium.io/docs/en/latest/intro/">Get Started</a> |
|
||||
<a href="https://appium.io/docs/en/latest/ecosystem/">Ecosystem</a> |
|
||||
<a href="https://github.com/appium/appium/blob/master/packages/appium/CHANGELOG.md">Changelog</a> |
|
||||
<a href="https://appium.io/docs/en/latest/contributing/">Contributing Guide</a> |
|
||||
<a href="https://discuss.appium.io">Discussion Forum</a>
|
||||
</b></p>
|
||||
### Supported Platforms
|
||||
|
||||
***
|
||||
* iOS
|
||||
* Android
|
||||
* FirefoxOS
|
||||
|
||||
Appium is an open-source automation framework that provides
|
||||
[WebDriver](https://www.w3.org/TR/webdriver/)-based automation possibilities for a wide range of
|
||||
different mobile, desktop and IoT platforms. Appium is modular and extensible, and supports multiple
|
||||
programming languages, which means there is an entire ecosystem of related software:
|
||||
* [__Drivers__](#drivers) add support for automating specific platforms
|
||||
* [__Clients__](#clients) allow writing Appium tests in your programming language of choice
|
||||
* [__Plugins__](#plugins) allow to further extend Appium functionality
|
||||
See the [platform support doc](/docs/en/appium-setup/platform-support.md) for more detailed information.
|
||||
|
||||
## Upgrading From Older Versions
|
||||
### Why Appium?
|
||||
|
||||
The Appium team only provides support for the most recent version of Appium. If you wish to upgrade from
|
||||
an older major Appium version, please refer to the migration guides:
|
||||
|
||||
* [Appium v2 to v3](https://appium.io/docs/en/latest/guides/migrating-2-to-3/)
|
||||
* [Appium v1 to v2](https://appium.io/docs/en/latest/guides/migrating-1-to-2/)
|
||||
|
||||
## Installation
|
||||
|
||||
Appium can be installed using `npm` (other package managers are not currently supported). Please
|
||||
check the [installation docs](http://appium.io/docs/en/latest/quickstart/install/) for the
|
||||
system requirements and further information.
|
||||
|
||||
If upgrading from Appium 1, make sure Appium 1 is fully uninstalled (`npm uninstall -g appium`).
|
||||
Unexpected errors might appear if this has not been done.
|
||||
|
||||
```bash
|
||||
npm i -g appium
|
||||
```
|
||||
|
||||
Note that this will only install the core Appium server, which cannot automate anything on its own.
|
||||
Please install [drivers](#drivers) for your target platforms in order to automate them.
|
||||
|
||||
## Drivers
|
||||
|
||||
Appium supports app automation across a variety of platforms, like iOS, Android, macOS, Windows,
|
||||
and more. Each platform is supported by one or more "drivers", which know how to automate that
|
||||
particular platform. You can find a full list of officially-supported and third-party drivers in
|
||||
[Appium Ecosystem's Drivers page](http://appium.io/docs/en/latest/ecosystem/drivers/).
|
||||
|
||||
Driver management is done using [Appium's Extension command-line interface](http://appium.io/docs/en/latest/cli/extensions/):
|
||||
|
||||
```bash
|
||||
# Install an official driver from npm (see documentation for a list of such drivers)
|
||||
appium driver install <driver-name>
|
||||
# Install any driver from npm
|
||||
appium driver install --source=npm <driver-name>
|
||||
# See documentation for installation from other sources
|
||||
|
||||
# List already installed drivers
|
||||
appium driver list --installed
|
||||
# Update a driver (it must be already installed)
|
||||
# This will NOT update the major version, in order to prevent breaking changes
|
||||
appium driver update <driver-name>
|
||||
# Update a driver to the most recent version (may include breaking changes)
|
||||
appium driver update <driver-name> --unsafe
|
||||
# Uninstall a driver (it won't last forever, will it?)
|
||||
appium driver uninstall <driver-name>
|
||||
```
|
||||
|
||||
## Clients
|
||||
|
||||
Client libraries enable writing Appium tests in different programming languages. There are
|
||||
officially-supported clients for Java, Python, Ruby, and .NET C#, as well as third-party clients
|
||||
for other languages. You can find a full list of clients in
|
||||
[Appium Ecosystem's Clients page](http://appium.io/docs/en/latest/ecosystem/clients/).
|
||||
|
||||
## Plugins
|
||||
|
||||
Plugins allow you to extend server functionality without changing the server code. The main
|
||||
difference between drivers and plugins is that the latter must be explicitly enabled on
|
||||
Appium server startup (all installed drivers are enabled by default):
|
||||
|
||||
```bash
|
||||
appium --use-plugins=<plugin-name>
|
||||
```
|
||||
|
||||
You can find a full list of officially-supported and third-party plugins in
|
||||
[Appium Ecosystem's Plugins page](http://appium.io/docs/en/latest/ecosystem/plugins/).
|
||||
|
||||
Similarly to drivers, plugin management is also done using
|
||||
[Appium's Extension command-line interface](http://appium.io/docs/en/latest/cli/extensions/):
|
||||
|
||||
```bash
|
||||
# Install an official plugin from npm (see documentation for a list of such plugins)
|
||||
appium plugin install <plugin-name>
|
||||
# Install any plugin from npm
|
||||
appium plugin install --source=npm <plugin-name>
|
||||
# See documentation for installation from other sources
|
||||
|
||||
# List already installed plugins
|
||||
appium plugin list --installed
|
||||
# Update a plugin (it must be already installed)
|
||||
# This will NOT update the major version, in order to prevent breaking changes
|
||||
appium plugin update <plugin-name>
|
||||
# Update a plugin to the most recent version (may include breaking changes)
|
||||
appium plugin update <plugin-name> --unsafe
|
||||
# Uninstall a plugin
|
||||
appium plugin uninstall <plugin-name>
|
||||
```
|
||||
|
||||
## Server Command Line Interface
|
||||
|
||||
In order to start sending commands to the Appium server, it must be running on the URL and port
|
||||
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/server/)
|
||||
is used to launch and configure the server:
|
||||
|
||||
```bash
|
||||
# Start the server on the default host (0.0.0.0) and port (4723)
|
||||
appium server
|
||||
# You can also omit the 'server' subcommand
|
||||
appium
|
||||
# Start the server on the given host, port and use a custom base path prefix (the default prefix is '/')
|
||||
appium --address 127.0.0.1 --port 9000 --base-path /wd/hub
|
||||
```
|
||||
|
||||
Appium supports execution of parallel server processes, as well as parallel driver sessions within a
|
||||
single server process. Refer the corresponding driver documentations regarding which mode is optimal
|
||||
for the particular driver or whether it supports parallel sessions.
|
||||
|
||||
## 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-compatible language such as
|
||||
Java, Python, Ruby and C#. There are also 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` 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) can be used to visually inspect
|
||||
the page source of applications across different platforms, facilitating easier test development.
|
||||
|
||||
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!
|
||||
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 are looking for a more comprehensive description of what this is all about, please read our
|
||||
documentation on [How Does Appium Work?](https://appium.io/docs/en/latest/intro/appium/).
|
||||
### I don't get it yet...
|
||||
|
||||
## Sponsors
|
||||
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).
|
||||
|
||||
Appium has a [Sponsorship Program](GOVERNANCE.md#sponsorship)! If you or your company uses Appium
|
||||
and wants to give back financially to the project, we use these funds to [encourage development and
|
||||
contributions](GOVERNANCE.md#compensation-scheme), as well as support other open source projects we
|
||||
rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenCollective page.
|
||||
### Requirements
|
||||
|
||||
### Development and Strategic Partners
|
||||
Your environment needs to be setup for the particular mobile platforms that you
|
||||
want to run tests on. See below for particular platform requirements.
|
||||
|
||||
Appium is incredibly grateful to our Development and Strategic Partners for their sustained
|
||||
contribution of project development and leadership!
|
||||
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.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<picture>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-dark.png" width="300" alt="Browserstack"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
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`.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.testmuai.com">
|
||||
<picture>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" width="300" alt="TestMu AI (formerly LambdaTest)"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
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).
|
||||
|
||||
### Other Sponsors
|
||||
#### iOS Requirements
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
|
||||
* Mac OS X 10.7 or higher, 10.9.2 recommended
|
||||
* XCode >= 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)
|
||||
|
||||
## License
|
||||
#### Android Requirements
|
||||
|
||||
[Apache-2.0](./LICENSE)
|
||||
* [Android SDK](http://developer.android.com) API >= 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)
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_large)
|
||||
#### FirefoxOS Requirements
|
||||
|
||||
`@appium/logger` package is under [ISC](./packages/logger/LICENSE) License.
|
||||
* [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
|
||||
|
||||
$ 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 source.
|
||||
|
||||
### Project Credits & Inspiration
|
||||
|
||||
[Credits](/docs/en/contributing-to-appium/credits.md)
|
||||
|
||||
### Mailing List
|
||||
|
||||
Announcements and debates often take place on the [Discussion Group](https://discuss.appium.io), be sure to sign up!
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
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.
|
||||
|
||||
### Using Robots
|
||||
|
||||
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!
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
# Roadmap
|
||||
|
||||
This is not a traditional roadmap. We don't have a typical product team with a typical product
|
||||
manager. The fact that the items below exist on a roadmap is no indication that we will ever have
|
||||
the opportunity to work on them. Instead this is more like a wishlist of outcomes that the project
|
||||
thinks would be valuable. If and when we get additional contributions of development work, this is
|
||||
a set of items that would be great for someone to work on! Ideally, interested devs would find
|
||||
something on this list and own it from start to finish! Let anyone on the project know if you're
|
||||
interested and we can help get you going.
|
||||
|
||||
### Core projects
|
||||
- **WebDriver BiDi support in the Appium server**: the WebDriver BiDi spec is underway, which details a different method for communicating with drivers. We should implement handling for these methods in our server so that Appium drivers can take advantage of the BiDi spec without additional work on their part.
|
||||
- **Redevelop automatically generated command docs**: due to changing TypeDoc support and the departure of one of our team, we were forced to remove our TypeDoc-based automatic docs generation tool. It would be nice to bring this back in a more maintainable form!
|
||||
|
||||
### Driver/platform-specific projects
|
||||
- **Better maintenance for our Android drivers**: we're looking for Android specialists to help maintain our Android drivers (UiAutomator2 and Espresso)
|
||||
- **Better maintenance for our iOS driver**: we're looking for iOS specialists to help maintain our XCUITest driver
|
||||
- **Better maintenance for [appium-ios-device](https://github.com/appium/appium-ios-device)**: this project is using outdated approaches and libraries. If it could be improved it would have a big impact on the performance of the XCUITest driver
|
||||
|
||||
### Client library projects
|
||||
- **Selenium compatibility client updates**: we'd like to rearchitect our flagship Appium clients to extend rather than wrap Selenium clients, reducing the overall surface area of the Appium clients and making them work more closely with existing Selenium client functionality.
|
||||
|
||||
### Appium Inspector projects
|
||||
- **Full support for web inspection**: currently the Appium Inspector has poor to no support for inspecing web pages (either mobile browsers or web content embedded in webviews). It's a common requirement to inspect web elements as part of writing Appium tests, and at the present time users are required to leave the Inspector and open up a browser's devtools.
|
||||
- **Record/Playback**: we have a basic record-to-code feature already. It would be nice to be able to save recorded steps and play them back with a little player/editor.
|
||||
- **Support for more platforms**: currently there is a fair bit of specialized handling for iOS and Android in the Appium inspector. Other platforms either work poorly or not at all with the Inspector. It would be great to establish a way for drivers to report all the information about how they work to the Inspector, so it can support any platform without needing special-cased code for it.
|
||||
- **Locator analysis and comparison**: it would be nice for users to get more information about the relative suitability of using different locators to find elements, as poor locator performance is a leading cause of Appium test instability.
|
||||
- **Dark theme**: for true hackers!
|
||||
- **Export/import of saved gestures**: it's currently not possible to port your saved gestures to other instances of the Inspector (i.e., to share with team members).
|
||||
- **Bulk export/import saved sessions**: would be nice to take your sessions and capabilities with you or to share with colleagues.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Sponsors & Backers
|
||||
|
||||
Please check [Sponsors & Backers](https://appium.io/docs/en/latest/sponsors/)
|
||||
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.
Binary file not shown.
Executable
+109
@@ -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
@@ -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); */ });
|
||||
}
|
||||
Executable
+23
@@ -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");
|
||||
});
|
||||
}
|
||||
Executable
+76
@@ -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
+56
@@ -0,0 +1,56 @@
|
||||
#!/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
|
||||
./reset.sh --hardcore --real-safari --chromedriver-install-all --chromedriver-version 2.10
|
||||
npm cache clear appium
|
||||
npm publish
|
||||
version=$(cat package.json | underscore extract version | sed 's/\"//g')
|
||||
git tag -a "v$version" -m "tag appium@$version for npm publish"
|
||||
git push --tags upstream $branch
|
||||
@@ -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
+153
@@ -0,0 +1,153 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
mocha_args=""
|
||||
ios_only=false
|
||||
ios6_only=false
|
||||
ios7_only=false
|
||||
ios71_only=false
|
||||
ios8_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" = "--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 $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=ios71 time $appium_mocha test/functional/gappium
|
||||
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
|
||||
echo "Start the android emulator api 16 and press Enter."
|
||||
read
|
||||
DEVICE=selendroid time $appium_mocha test/functional/gappium
|
||||
fi
|
||||
@@ -0,0 +1,11 @@
|
||||
export JAVA_HOME=$(/usr/libexec/java_home)
|
||||
|
||||
if [ -f $HOME/tools/ant/env ]; then
|
||||
source $HOME/tools/ant/env
|
||||
fi
|
||||
if [ -f $HOME/tools/maven/env ]; then
|
||||
source $HOME/tools/maven/env
|
||||
fi
|
||||
if [ -f $HOME/tools/android/env ]; then
|
||||
source $HOME/tools/android/env
|
||||
fi
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ "${TARBALL}" == '' ]]; then
|
||||
echo Please set the TARBALL env variable!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET=/tmp/${TARBALL}
|
||||
|
||||
echo "Starting to archive appium build into ${TARGET}."
|
||||
|
||||
tar \
|
||||
cfj ${TARGET} \
|
||||
-L \
|
||||
--exclude=.git \
|
||||
--exclude=submodules .
|
||||
|
||||
echo "Finished to archive appium build."
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ $CI_CONFIG == 'ios' ]]; then
|
||||
./ci/installers/install-ant.sh
|
||||
./ci/installers/install-maven.sh
|
||||
sudo grunt authorize
|
||||
elif [[ $CI_CONFIG == 'android' ]]; then
|
||||
./ci/installers/install-ant.sh
|
||||
./ci/installers/install-maven.sh
|
||||
./ci/installers/install-android.sh --api-19
|
||||
sudo grunt authorize
|
||||
elif [[ $CI_CONFIG == 'gappium' ]]; then
|
||||
if [[ $TRAVIS_PULL_REQUEST != false ]]; then
|
||||
# Skipping this config for pull requests, it takes too long.
|
||||
exit 0
|
||||
fi
|
||||
./ci/installers/install-ant.sh
|
||||
./ci/installers/install-maven.sh
|
||||
./ci/installers/install-android.sh --api-19 --api-18 --api-16
|
||||
npm install -g cordova
|
||||
sudo grunt authorize
|
||||
elif [[ $CI_CONFIG == 'selendroid' ]]; then
|
||||
if [[ $TRAVIS_PULL_REQUEST != false ]]; then
|
||||
# Skipping this config for pull requests, it takes too long.
|
||||
exit 0
|
||||
fi
|
||||
./ci/installers/install-ant.sh
|
||||
./ci/installers/install-maven.sh
|
||||
./ci/installers/install-android.sh --api-19 --api-16
|
||||
sudo grunt authorize
|
||||
fi
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
TARBALL=appium-${DEVICE_TYPE}-${BUILD_NUMBER}-${GIT_COMMIT:0:10}.tar.bz2
|
||||
|
||||
echo "TARBALL=${TARBALL}" >> ./ci/build-env.properties
|
||||
|
||||
cat ./ci/build-env.properties
|
||||
@@ -0,0 +1,10 @@
|
||||
- SAUCE_USERNAME=appium
|
||||
- SAUCE_REST_ROOT=https://saucelabs.com/rest/v1
|
||||
- APPIUM_HOST=ondemand.saucelabs.com
|
||||
- APPIUM_PORT=80
|
||||
- IOS_CONCURRENCY=30
|
||||
- ANDROID_CONCURRENCY=30
|
||||
- SELENDROID_CONCURRENCY=10
|
||||
- GAPPIUM_CONCURRENCY=10
|
||||
# below is SAUCE_ACCESS_KEY encrypted
|
||||
- secure: GXGFbQptLEsKlaWnpOL2EB9hqQ4XBT6tqg7REt5j1h1jYBsfHQHSgSLt1jpzOF5kooXVbw2K7IrZyNVBXEUHR00Hp6O72FBOd+SSj8uPCJBLjAOaJWs0ZtujqGHwHpe6gadFfn0L7q0ffoV5OJVeNHHcuw4f9BaA78fTFNfm1jE=
|
||||
@@ -0,0 +1,13 @@
|
||||
export SAUCE_REST_ROOT=https://saucelabs.com/rest/v1
|
||||
export APPIUM_HOST=ondemand.saucelabs.com
|
||||
export APPIUM_PORT=80
|
||||
|
||||
export IOS_CONCURRENCY=10
|
||||
export ANDROID_CONCURRENCY=10
|
||||
export SELENDROID_CONCURRENCY=5
|
||||
export GAPPIUM_CONCURRENCY=5
|
||||
export HTTP_RETRIES=2
|
||||
export HTTP_RETRY_DELAY=20000
|
||||
export DEBUG_CONNECTION=1
|
||||
export MOCHA_INIT_TIMEOUT=300000
|
||||
export LAUNCH_TIMEOUT='{"global":60000,"afterSimLaunch":30000}'
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
# Needs to be sourced!
|
||||
|
||||
set -e
|
||||
|
||||
curl -s -o use-node https://repository-cloudbees.forge.cloudbees.com/distributions/ci-addons/node/use-node
|
||||
NODE_VERSION=0.10.26 . ./use-node
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
androids=','
|
||||
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
"--api-19") androids+='android-19,';;
|
||||
"--api-18") androids+='android-18,';;
|
||||
"--api-16") androids+='android-16,';;
|
||||
esac
|
||||
|
||||
if [[ -n "$2" ]] && [[ "$2" != --* ]]; then
|
||||
shift
|
||||
shift
|
||||
else
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
COMPONENTS=build-tools-19.0.3${androids}extra-android-support
|
||||
|
||||
mkdir -p $HOME/tools/android
|
||||
|
||||
( curl -L https://raw.github.com/appium/android-sdk-installer/master/android-sdk-installer | \
|
||||
bash /dev/stdin --dir=$HOME/tools/android --install=$COMPONENTS ) &&\
|
||||
source $HOME/tools/android/env
|
||||
|
||||
# to configure the emulator, add sysimg-18 to COMPONENTS and uncomment the line belor
|
||||
# echo no | android create avd --force -n test -t android-18 --abi armeabi-v7a
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
mkdir -p $HOME/tools/ant
|
||||
cd $HOME/tools/ant
|
||||
wget -P /tmp http://www.us.apache.org/dist/ant/binaries/apache-ant-1.9.4-bin.tar.gz
|
||||
tar xzf /tmp/apache-ant-1.9.4-bin.tar.gz
|
||||
echo 'export PATH=$HOME/tools/ant/apache-ant-1.9.4/bin:$PATH' > $HOME/tools/ant/env
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
mkdir -p $HOME/tools/maven
|
||||
cd $HOME/tools/maven
|
||||
wget -P /tmp http://www.us.apache.org/dist/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
|
||||
tar xzf /tmp/apache-maven-3.1.1-bin.tar.gz
|
||||
echo 'export PATH=$HOME/tools/maven/apache-maven-3.1.1/bin:$PATH' > $HOME/tools/maven/env
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
git clone https://github.com/visionmedia/n.git /tmp/n
|
||||
cd /tmp/n
|
||||
make install
|
||||
n stable
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
mkdir -p $HOME/tools/sc
|
||||
cd $HOME/tools/sc
|
||||
wget -P /tmp https://saucelabs.com/downloads/sc-4.3-osx.zip
|
||||
unzip /tmp/sc-4.3-osx.zip -d $HOME/tools/sc
|
||||
echo 'export PATH=$HOME/tools/sc/sc-4.3-osx/bin:$PATH' > $HOME/tools/sc/env
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
SAUCE=1 \
|
||||
VERBOSE=1 \
|
||||
TARBALL="${TARBALL}" \
|
||||
DEVICE="android" \
|
||||
VERSION="4.3" \
|
||||
./node_modules/.bin/mocha \
|
||||
-g "@skip-ci|@skip-android-all|@android-arm-only" -i \
|
||||
"$@"
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
SAUCE=1 \
|
||||
VERBOSE=1 \
|
||||
TARBALL="${TARBALL}" \
|
||||
DEVICE="ios71" \
|
||||
VERSION="7.1" \
|
||||
./node_modules/.bin/mocha \
|
||||
-g "@skip-ci|@skip-ios71|@skip-ios7|@skip-ios-all" -i \
|
||||
"$@"
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
SAUCE=1 \
|
||||
VERBOSE=1 \
|
||||
TARBALL="${TARBALL}" \
|
||||
DEVICE="selendroid" \
|
||||
./node_modules/.bin/mocha \
|
||||
-g "@skip-ci|@skip-selendroid-all" -i \
|
||||
"$@"
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source ./ci/env.sh
|
||||
|
||||
function check_tarball {
|
||||
if [[ "${TARBALL}" == '' ]]; then
|
||||
echo Please set the TARBALL env variable!
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function show_functional_test_info {
|
||||
echo "APPIUM_BUILD_NUMBER --> ${APPIUM_BUILD_NUMBER}"
|
||||
echo "APPIUM_JOB_NUMBER --> ${APPIUM_JOB_NUMBER}"
|
||||
echo "TARBALL --> ${TARBALL}"
|
||||
}
|
||||
|
||||
if [[ $CI_CONFIG == 'unit' ]]; then
|
||||
npm install -g jshint grunt-cli
|
||||
npm install
|
||||
# cd docs
|
||||
# appium_doc_lint || exit 1
|
||||
# cd -
|
||||
npm test
|
||||
elif [[ $CI_CONFIG == 'build-ios' ]]; then
|
||||
check_tarball
|
||||
unset SUDO_UID
|
||||
echo OS X version: `sw_vers -productVersion`
|
||||
echo Xcode version: `xcodebuild build -version`
|
||||
echo Xcode path: `xcode-select --print-path`
|
||||
./reset.sh --no-npmlink --dev --ios
|
||||
|
||||
if [[ $UPLOAD_TO_SAUCE == 1 ]]; then
|
||||
TARBALL=$TARBALL ./ci/archive-build.sh
|
||||
# TARBALL=$TARBALL ./ci/upload_build_to_sauce.sh
|
||||
fi
|
||||
elif [[ $CI_CONFIG == 'ios-functional-tests' ]]; then
|
||||
check_tarball
|
||||
show_functional_test_info
|
||||
npm install
|
||||
TARBALL=sauce-storage:$TARBALL \
|
||||
./ci/tools/parallel-mocha.js \
|
||||
-p $IOS_CONCURRENCY \
|
||||
-c ios
|
||||
elif [[ $CI_CONFIG == 'build-android' ]]; then
|
||||
check_tarball
|
||||
echo JAVA_HOME: $JAVA_HOME
|
||||
./reset.sh --no-npmlink --dev --android
|
||||
if [[ $UPLOAD_TO_SAUCE == 1 ]]; then
|
||||
TARBALL=$TARBALL ./ci/archive-build.sh
|
||||
# TARBALL=$TARBALL ./ci/upload_build_to_sauce.sh
|
||||
fi
|
||||
elif [[ $CI_CONFIG == 'android-functional-tests' ]]; then
|
||||
check_tarball
|
||||
show_functional_test_info
|
||||
npm install
|
||||
TARBALL=sauce-storage:$TARBALL \
|
||||
./ci/tools/parallel-mocha.js \
|
||||
-p $ANDROID_CONCURRENCY \
|
||||
-c android
|
||||
elif [[ $CI_CONFIG == 'gappium' ]]; then
|
||||
check_tarball
|
||||
if [[ $TRAVIS_PULL_REQUEST != false ]]; then
|
||||
echo "Skipping this config for pull requests, it takes too long."
|
||||
exit 0
|
||||
fi
|
||||
# source ./ci/android_env
|
||||
echo OS X version: `sw_vers -productVersion`
|
||||
echo Xcode version: `xcodebuild build -version`
|
||||
echo Xcode path: `xcode-select --print-path`
|
||||
echo JAVA_HOME: $JAVA_HOME
|
||||
./reset.sh --ios --android --selendroid-quick --no-npmlink
|
||||
./reset.sh --dev --gappium --no-npmlink
|
||||
# if [[ $UPLOAD_TO_SAUCE == 1 ]]; then
|
||||
# TARBALL=$TARBALL ./ci/upload_build_to_sauce.sh
|
||||
# TARBALL=sauce-storage:$TARBALL \
|
||||
# ./ci/tools/parallel-mocha.js \
|
||||
# -p $GAPPIUM_CONCURRENCY \
|
||||
# -c gappium
|
||||
# fi
|
||||
elif [[ $CI_CONFIG == 'selendroid' ]]; then
|
||||
check_tarball
|
||||
if [[ $TRAVIS_PULL_REQUEST != false ]]; then
|
||||
echo "Skipping this config for pull requests, it takes too long."
|
||||
exit 0
|
||||
fi
|
||||
# source ./ci/android_env
|
||||
echo OS X version: `sw_vers -productVersion`
|
||||
echo Xcode version: `xcodebuild build -version`
|
||||
echo Xcode path: `xcode-select --print-path`
|
||||
echo JAVA_HOME: $JAVA_HOME
|
||||
./reset.sh --android --no-npmlink
|
||||
./reset.sh --dev --selendroid-quick --no-npmlink
|
||||
# if [[ $UPLOAD_TO_SAUCE == 1 ]]; then
|
||||
# TARBALL=$TARBALL ./ci/upload_build_to_sauce.sh
|
||||
# TARBALL=sauce-storage:$TARBALL \
|
||||
# ./ci/tools/parallel-mocha.js \
|
||||
# -p $SELENDROID_CONCURRENCY \
|
||||
# -c selendroid
|
||||
# fi
|
||||
fi
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
SC_DIR="/tmp/sc"
|
||||
READY_FILE="sc-ready-$RANDOM"
|
||||
|
||||
mkdir -p $SC_DIR && cd $SC_DIR
|
||||
touch $SC_DIR/sauce_connect.log
|
||||
|
||||
source $HOME/tools/sc/env
|
||||
|
||||
sc \
|
||||
-u $SAUCE_USERNAME \
|
||||
-k $SAUCE_ACCESS_KEY \
|
||||
--readyfile $READY_FILE\
|
||||
--tunnel-identifier $TRAVIS_JOB_NUMBER \
|
||||
-l $SC_DIR/sauce_connect.log \
|
||||
&> /dev/null &
|
||||
|
||||
echo 'waiting for sauce connect to start'
|
||||
tail -f $SC_DIR/sauce_connect.log &
|
||||
|
||||
# Wait for Connect to be ready before exiting
|
||||
while [ ! -f $READY_FILE ]; do
|
||||
sleep .5
|
||||
done
|
||||
@@ -0,0 +1,46 @@
|
||||
module.exports = {
|
||||
'ios':{
|
||||
'mocha-bin': 'ci/mochas/ios71-mocha',
|
||||
'glob-patterns': [
|
||||
'test/functional/common/**/*-specs.js',
|
||||
'test/functional/ios/**/*-specs.js'
|
||||
]
|
||||
},
|
||||
'android':{
|
||||
'mocha-bin': 'ci/mochas/android-mocha',
|
||||
'glob-patterns': [
|
||||
'test/functional/common/**/*-specs.js',
|
||||
'test/functional/android/**/*-specs.js'
|
||||
]
|
||||
},
|
||||
'gappium':[
|
||||
{
|
||||
'mocha-bin': 'ci/mochas/ios71-mocha',
|
||||
'glob-patterns': [
|
||||
'test/functional/gappium/**/*-specs.js'
|
||||
]
|
||||
},
|
||||
// TODO: gappium/android hangs on sauce.
|
||||
// suspect: context/contexts issues on linux
|
||||
// {
|
||||
// 'mocha-bin': 'ci/mochas/android-mocha',
|
||||
// 'glob-patterns': [
|
||||
// 'test/functional/gappium/**/*-specs.js'
|
||||
// ]
|
||||
// },
|
||||
// TODO: gappium/selendroid hangs on sauce.
|
||||
// suspect: context/contexts issues on linux
|
||||
// {
|
||||
// 'mocha-bin': 'ci/mochas/selendroid-mocha',
|
||||
// 'glob-patterns': [
|
||||
// 'test/functional/gappium/**/*-specs.js'
|
||||
// ]
|
||||
// }
|
||||
],
|
||||
'selendroid':{
|
||||
'mocha-bin': 'ci/mochas/selendroid-mocha',
|
||||
'glob-patterns': [
|
||||
'test/functional/selendroid/**/*-specs.js'
|
||||
]
|
||||
}
|
||||
};
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var yaml = require('js-yaml'),
|
||||
fs = require('fs'),
|
||||
_ = require('underscore');
|
||||
|
||||
var args = process.argv.slice(2);
|
||||
|
||||
function usage() {
|
||||
console.warn("Usage:");
|
||||
console.warn(" $(ci/tools/bash-env-tool.js set <config>)");
|
||||
console.warn(" $(ci/tools/bash-env-tool.js unset)");
|
||||
console.warn(" ci/tools/bash-env-tool.js show");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var ENV_VARIABLES = ['SAUCE_USERNAME', 'SAUCE_ACCESS_KEY', 'SAUCE_REST_ROOT',
|
||||
'APPIUM_HOST', 'APPIUM_PORT'];
|
||||
|
||||
if (args.length < 1) usage();
|
||||
|
||||
function set() {
|
||||
if (args.length < 2) usage();
|
||||
var doc = yaml.load(fs.readFileSync(args[1], 'utf8'));
|
||||
_(doc).chain()
|
||||
.filter(function (line) { return typeof line === 'string'; })
|
||||
.map(function (line) {
|
||||
var m = line.match(/^(.+)=(.*)$/);
|
||||
if (m) {
|
||||
return {key: m[1], value: m[2]};
|
||||
}
|
||||
}).filter(function (keyVal) {
|
||||
return ENV_VARIABLES.indexOf(keyVal.key) >= 0;
|
||||
}).each(function (keyVal) {
|
||||
console.log('export', keyVal.key + '=' + keyVal.value);
|
||||
});
|
||||
}
|
||||
|
||||
function unset() {
|
||||
_(ENV_VARIABLES).each(function (key) {
|
||||
console.log('unset', key);
|
||||
});
|
||||
}
|
||||
|
||||
function show() {
|
||||
_(ENV_VARIABLES).each(function (key) {
|
||||
console.log(key, '-->', process.env[key] ? process.env[key] : 'not set');
|
||||
});
|
||||
}
|
||||
|
||||
switch (args[0]) {
|
||||
case 'set':
|
||||
set();
|
||||
break;
|
||||
case 'unset':
|
||||
unset();
|
||||
break;
|
||||
case 'show':
|
||||
show();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(2),
|
||||
assert = require('assert');
|
||||
|
||||
var fs = require("fs");
|
||||
var data = JSON.parse(fs.readFileSync(args[0]));
|
||||
assert(data.filename);
|
||||
|
||||
switch (args[1]) {
|
||||
case 'filename':
|
||||
console.log(data.filename);
|
||||
break;
|
||||
default:
|
||||
console.log(data);
|
||||
}
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(2),
|
||||
Saucelabs = require('saucelabs'),
|
||||
Q = require('q'),
|
||||
_ = require('underscore'),
|
||||
prompt = require('prompt');
|
||||
|
||||
var buildId = args[0];
|
||||
|
||||
if (!buildId) {
|
||||
console.log('\nUsage: ci/tools/green-sauce-jobs <build_id>\n');
|
||||
console.log('\nExample: ci/tools/green-sauce-jobs 4711\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.SAUCE_ACCESS_KEY) {
|
||||
console.log('\nPlease set the SAUCE_USERNAME and SAUCE_ACCESS_KEY ' +
|
||||
'env variables!\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var account = new Saucelabs({
|
||||
username: process.env.SAUCE_USERNAME,
|
||||
password: process.env.SAUCE_ACCESS_KEY
|
||||
});
|
||||
|
||||
var getJobs = Q.nbind(account.getJobs, account);
|
||||
var updateJob = Q.nbind(account.updateJob, account);
|
||||
|
||||
var selectedJobs;
|
||||
|
||||
getJobs()
|
||||
.then(function (jobs) {
|
||||
return _(jobs).filter(function (job) {
|
||||
return job.build === buildId && !job.passed;
|
||||
}).map(function (job) {
|
||||
return _(job).pick('id', 'name', 'tags', 'build', 'passed', 'error');
|
||||
});
|
||||
}).then(function (jobs) {
|
||||
selectedJobs = jobs;
|
||||
if (jobs.length > 0) {
|
||||
console.log("\nJobs needing greening:\n");
|
||||
console.log(jobs);
|
||||
console.log("\nMark all these jobs as passed? (Y/N):\n");
|
||||
prompt.start();
|
||||
return Q.nfcall(prompt.get, {
|
||||
name: 'YesNo',
|
||||
validator: /^[ynYN]{1}$/m,
|
||||
warning: 'only (Y/N)',
|
||||
required: true
|
||||
});
|
||||
} else {
|
||||
console.log('All jobs are already green.');
|
||||
return false;
|
||||
}
|
||||
}).then(function (result) {
|
||||
if (result && result.YesNo.toLowerCase() === 'y') {
|
||||
console.log('Starting to green jobs.');
|
||||
return Q.all(selectedJobs.map(function (job) {
|
||||
var tags = job.tags || [];
|
||||
if (tags.indexOf('greened') < 0) job.tags.push('greened');
|
||||
return updateJob(job.id, {passed: true, tags: job.tags});
|
||||
})).then(function () { console.log('Finished to green jobs.'); });
|
||||
}
|
||||
}).done();
|
||||
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(2),
|
||||
Saucelabs = require('saucelabs'),
|
||||
Q = require('q'),
|
||||
_ = require('underscore'),
|
||||
prompt = require('prompt');
|
||||
|
||||
var CONCURRENCY = 10;
|
||||
|
||||
var buildId = args[0];
|
||||
|
||||
if (!buildId) {
|
||||
console.log('\nUsage: ci/tools/kill-sauce-jobs <build_id>\n');
|
||||
console.log('\nExample: ci/tools/kill-sauce-jobs 4711\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.SAUCE_ACCESS_KEY) {
|
||||
console.log('\nPlease set the SAUCE_USERNAME and SAUCE_ACCESS_KEY ' +
|
||||
'env variables!\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var account = new Saucelabs({
|
||||
username: process.env.SAUCE_USERNAME || 'appium',
|
||||
password: process.env.SAUCE_ACCESS_KEY
|
||||
});
|
||||
|
||||
var getJobs = Q.nbind(account.getJobs, account);
|
||||
var stopJob = Q.nbind(account.stopJob, account);
|
||||
|
||||
var selectedJobs;
|
||||
|
||||
getJobs()
|
||||
.then(function (jobs) {
|
||||
return _(jobs).filter(function (job) {
|
||||
return job.build === buildId &&
|
||||
['in progress','queued'].indexOf(job.status) >= 0;
|
||||
}).map(function (job) {
|
||||
return _(job).pick('id', 'name', 'tags', 'build', 'status');
|
||||
});
|
||||
}).then(function (jobs) {
|
||||
selectedJobs = jobs;
|
||||
if (jobs.length > 0) {
|
||||
console.log("\nWill kill jobs:\n");
|
||||
console.log(jobs);
|
||||
console.log("\nNumber of jobs to kill:", jobs.length, "\n");
|
||||
console.log("\nKill all these jobs? (Y/N):\n");
|
||||
prompt.start();
|
||||
return Q.nfcall(prompt.get, {
|
||||
name: 'YesNo',
|
||||
validator: /^[ynYN]{1}$/m,
|
||||
warning: 'only (Y/N)',
|
||||
required: true
|
||||
});
|
||||
} else {
|
||||
console.log('No jobs to kill.');
|
||||
return false;
|
||||
}
|
||||
}).then(function (result) {
|
||||
if (result && result.YesNo.toLowerCase() === 'y') {
|
||||
console.log('\nStarting to kill jobs.\n');
|
||||
var tasks = selectedJobs.map(function (job) {
|
||||
return function () {
|
||||
console.log('Killing job:', job.id);
|
||||
return stopJob(job.id, {}).then(function () {
|
||||
console.log('Job', job.id, "was killed" );
|
||||
}, function (err) {
|
||||
console.warn('Could not kill', job.id, 'err:', err);
|
||||
});
|
||||
};
|
||||
});
|
||||
var process = function () {
|
||||
console.log('\n');
|
||||
if (tasks.length === 0) return new Q();
|
||||
var batch = [];
|
||||
while (tasks.length >0 && batch.length < CONCURRENCY) {
|
||||
batch.push(tasks.shift()());
|
||||
}
|
||||
return Q.all(batch).then(function () {
|
||||
return process();
|
||||
});
|
||||
};
|
||||
return process().then(function () {
|
||||
console.log('\nFinished to kill jobs.\n');
|
||||
});
|
||||
}
|
||||
}).done();
|
||||
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(2),
|
||||
_ = require('underscore'),
|
||||
glob = require('glob'),
|
||||
async = require('async'),
|
||||
Q = require("q"),
|
||||
spawn = require('child_process').spawn,
|
||||
argparse = require('argparse');
|
||||
|
||||
|
||||
var parser = new argparse.ArgumentParser({
|
||||
description: 'Parallel Mocha'
|
||||
});
|
||||
parser.addArgument(
|
||||
[ '-p' ],
|
||||
{
|
||||
help: 'number of processes',
|
||||
type: 'int',
|
||||
required: true,
|
||||
dest: 'numOfWorkers'
|
||||
}
|
||||
);
|
||||
parser.addArgument(
|
||||
[ '-c' ],
|
||||
{
|
||||
help: 'test config',
|
||||
required: true,
|
||||
dest: 'config'
|
||||
}
|
||||
);
|
||||
var args = parser.parseArgs();
|
||||
|
||||
var config = require('../test-glob-config');
|
||||
|
||||
var fileInfos = config[args.config];
|
||||
if (!(fileInfos instanceof Array)) {
|
||||
fileInfos = [fileInfos];
|
||||
}
|
||||
|
||||
var allGood = true;
|
||||
|
||||
function runOne(mochaBin, filepath) {
|
||||
var deferred = Q.defer();
|
||||
var out = '';
|
||||
var child = spawn(mochaBin, [filepath]);
|
||||
child.on('error', function (err) {
|
||||
deferred.reject(err);
|
||||
});
|
||||
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', function (data) {
|
||||
out += data;
|
||||
});
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', function (data) {
|
||||
out += data;
|
||||
});
|
||||
child.on('close', function (code) {
|
||||
if (code !== 0) {
|
||||
var err = new Error(
|
||||
"Mocha process terminated with code: " + code + '.');
|
||||
err.out = out;
|
||||
return deferred.reject(err);
|
||||
}
|
||||
deferred.resolve(out);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
var queue = async.queue(function (task, done) {
|
||||
var startMs = Date.now();
|
||||
console.log('running ' + task.filepath);
|
||||
|
||||
var interval = setInterval(function () {
|
||||
console.log(task.filepath, 'has been running for',
|
||||
Math.round((Date.now() - startMs)/1000), 'seconds.');
|
||||
}, 300000);
|
||||
|
||||
runOne(task.mochaBin, task.filepath)
|
||||
.then(function (out) {
|
||||
console.log('finished to run', task.filepath,'\n', out);
|
||||
})
|
||||
.catch(function (err) {
|
||||
allGood = false;
|
||||
console.error(err + (err.out ? '\n' + err.out : ''));
|
||||
}).finally(function () { clearInterval(interval); })
|
||||
.nodeify(done);
|
||||
}, args.numOfWorkers);
|
||||
|
||||
queue.drain = function () {
|
||||
if (allGood) {
|
||||
console.log('\n\nALL GOOD\n\n');
|
||||
process.exit(0);
|
||||
}
|
||||
else {
|
||||
throw new Error('FAILING TESTS!');
|
||||
}
|
||||
};
|
||||
|
||||
function fillQueue(fileInfo) {
|
||||
var deferred = Q.defer();
|
||||
async.eachSeries(
|
||||
fileInfo['glob-patterns'],
|
||||
function (globPattern, done) {
|
||||
glob(globPattern, function (err, _files) {
|
||||
if (err) return done(err);
|
||||
_(_files).map(function (file) {
|
||||
queue.push({mochaBin: fileInfo['mocha-bin'], filepath: file});
|
||||
});
|
||||
done();
|
||||
});
|
||||
},
|
||||
function (err) {
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
queue.pause();
|
||||
Q.all(_(fileInfos).map(function (fileInfo) {
|
||||
return fillQueue(fileInfo);
|
||||
})).then(function () { queue.resume(); })
|
||||
.done();
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(2),
|
||||
assert = require('assert'),
|
||||
_ = require('underscore');
|
||||
|
||||
if (args.length !==2 ) {
|
||||
console.warn('Usage travis.yml-tool.js <.travis.yml> <config.yml>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var DEFAULTS = {
|
||||
SAUCE_REST_ROOT:'https://saucelabs.com/rest/v1',
|
||||
APPIUM_HOST:'ondemand.saucelabs.com',
|
||||
APPIUM_PORT:80,
|
||||
IOS_CONCURRENCY:10,
|
||||
ANDROID_CONCURRENCY:10,
|
||||
SELENDROID_CONCURRENCY:3,
|
||||
GAPPIUM_CONCURRENCY:3
|
||||
};
|
||||
|
||||
var fs = require("fs");
|
||||
var target = fs.readFileSync(args[0], 'UTF8');
|
||||
var config = fs.readFileSync(args[1], 'UTF8');
|
||||
|
||||
// replace secure env variable
|
||||
var secureLines = config.match(/^\s*- secure.*/gm).join('\n');
|
||||
secureLines = secureLines.replace(/^\s*-/mg, ' -');
|
||||
assert(secureLines);
|
||||
target = target.replace(/(^\s*- secure.*\r?\n)+/m, ' # <SECURE>\n');
|
||||
target = target.replace(/^ # <SECURE>.*$/m, secureLines);
|
||||
|
||||
// replace env variables
|
||||
_([
|
||||
'SAUCE_REST_ROOT', 'APPIUM_HOST','APPIUM_PORT', 'SAUCE_USERNAME',
|
||||
'IOS_CONCURRENCY', 'ANDROID_CONCURRENCY', 'SELENDROID_CONCURRENCY',
|
||||
'GAPPIUM_CONCURRENCY'
|
||||
]).each(function (varName) {
|
||||
var regex = new RegExp('- ' + varName + '=.*');
|
||||
var m = config.match(regex);
|
||||
var line = m ? m[0] : null;
|
||||
if (!line && DEFAULTS[varName]) {
|
||||
line = '- ' + varName + '=' + DEFAULTS[varName];
|
||||
}
|
||||
regex = new RegExp('- ' + varName + '=.*','g');
|
||||
target = target.replace(regex, line);
|
||||
});
|
||||
|
||||
fs.writeFileSync(args[0], target, 'UTF8');
|
||||
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source ./ci/env.sh
|
||||
|
||||
if [[ "${TARBALL}" == '' ]]; then
|
||||
echo Please set the TARBALL env variable!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE=/tmp/${TARBALL}
|
||||
|
||||
echo "Starting to upload appium from ${SOURCE} to ${TARBALL}."
|
||||
|
||||
UPLOAD_INFO_FILE=./build-upload-info.json
|
||||
|
||||
# zipping/uploading
|
||||
curl \
|
||||
-k \
|
||||
--silent \
|
||||
-u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
|
||||
-X POST "${SAUCE_REST_ROOT}/storage/${SAUCE_USERNAME}/${TARBALL}?overwrite=true" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @${SOURCE} \
|
||||
-o $UPLOAD_INFO_FILE
|
||||
|
||||
# --progress-bar \
|
||||
|
||||
# checking/printing result file
|
||||
ci/tools/build-upload-tool.js $UPLOAD_INFO_FILE
|
||||
rm ${SOURCE}
|
||||
echo "Finished to compress and upload appium."
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source ./ci/env.sh
|
||||
|
||||
if [[ "${TARBALL}" == '' ]]; then
|
||||
echo Please set the TARBALL env variable!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting to compress and upload appium to ${TARBALL}."
|
||||
|
||||
UPLOAD_INFO_FILE=./build-upload-info.json
|
||||
|
||||
# zipping/uploading
|
||||
tar \
|
||||
cfj - \
|
||||
-L \
|
||||
--exclude=.git \
|
||||
--exclude=submodules . | \
|
||||
curl \
|
||||
-k \
|
||||
--silent \
|
||||
-u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
|
||||
-X POST "${SAUCE_REST_ROOT}/storage/${SAUCE_USERNAME}/${TARBALL}?overwrite=true" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @- \
|
||||
-o $UPLOAD_INFO_FILE
|
||||
|
||||
# --progress-bar \
|
||||
|
||||
# checking/printing result file
|
||||
ci/tools/build-upload-tool.js $UPLOAD_INFO_FILE
|
||||
|
||||
echo "Finished to compress and upload appium."
|
||||
+9
-4
@@ -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
|
||||
|
||||
Current Appium 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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user